mirror of
https://github.com/microtherion/VocalEasel.git
synced 2024-12-22 11:14:00 +00:00
Reorganize layout system
This commit is contained in:
parent
964d56a0f7
commit
80fbc00f56
80
Sources/VLLayout.cpp
Normal file
80
Sources/VLLayout.cpp
Normal file
|
@ -0,0 +1,80 @@
|
|||
//
|
||||
// File: VLLayout.cpp - Dimensions for lead sheet layout
|
||||
//
|
||||
// Author(s):
|
||||
//
|
||||
// (MN) Matthias Neeracher
|
||||
//
|
||||
// Copyright © 2007 Matthias Neeracher
|
||||
//
|
||||
|
||||
#include "VLLayout.h"
|
||||
#include "VLSheetViewInternal.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <cmath>
|
||||
|
||||
VLSystemLayout::VLSystemLayout(const VLProperties & prop, float width)
|
||||
{
|
||||
fDivisions = prop.fDivisions;
|
||||
fNumGroups = prop.fTime.fNum / std::max(prop.fTime.fDenom / 4, 1);
|
||||
fDivPerGroup = fDivisions * prop.fTime.fNum * 4 / (prop.fTime.fDenom * fNumGroups);
|
||||
fClefKeyWidth = kClefX+kClefW+(std::labs(prop.fKey)+1)*kKeyW;
|
||||
fMeasureWidth = fNumGroups*(fDivPerGroup+1)*kNoteW;
|
||||
fNumMeasures= std::max<int>(1, std::floor((width-fClefKeyWidth) / fMeasureWidth));
|
||||
}
|
||||
|
||||
VLLayout::VLLayout(const VLSong & song, float width)
|
||||
{
|
||||
for (size_t meas = 0; meas<song.fMeasures.size(); ) {
|
||||
const VLProperties & prop = song.fProperties[song.fMeasures[meas].fPropIdx];
|
||||
push_back(VLSystemLayout(prop, width));
|
||||
meas += back().NumMeasures();
|
||||
}
|
||||
}
|
||||
|
||||
int VLLayout::FirstMeasure(int system) const
|
||||
{
|
||||
int meas = 0;
|
||||
for (int sys=0; sys<system; ++sys)
|
||||
meas += (*this)[sys].NumMeasures();
|
||||
return meas;
|
||||
}
|
||||
|
||||
int VLLayout::SystemForMeasure(int measure) const
|
||||
{
|
||||
int sys;
|
||||
for (sys=0; sys<size(); ++sys) {
|
||||
measure -= (*this)[sys].NumMeasures();
|
||||
if (measure < 0)
|
||||
break;
|
||||
}
|
||||
return sys;
|
||||
}
|
||||
|
||||
float VLLayout::MeasurePosition(int measure) const
|
||||
{
|
||||
for (int sys=0; sys<size(); ++sys) {
|
||||
const VLSystemLayout & layout = (*this)[sys];
|
||||
if (measure < layout.NumMeasures())
|
||||
return layout.MeasurePosition(measure);
|
||||
measure -= layout.NumMeasures();
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float VLLayout::NotePosition(int measure, VLFraction at) const
|
||||
{
|
||||
for (int sys=0; sys<size(); ++sys) {
|
||||
const VLSystemLayout & layout = (*this)[sys];
|
||||
if (measure < layout.NumMeasures()) {
|
||||
int div = at.fNum*4*layout.Divisions() / at.fDenom;
|
||||
|
||||
return layout.MeasurePosition(measure)
|
||||
+ (div + div/layout.DivPerGroup() + 1)*kNoteW;
|
||||
}
|
||||
measure -= layout.NumMeasures();
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
48
Sources/VLLayout.h
Normal file
48
Sources/VLLayout.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
//
|
||||
// File: VLLayout.h - Dimensions for lead sheet layout
|
||||
//
|
||||
// Author(s):
|
||||
//
|
||||
// (MN) Matthias Neeracher
|
||||
//
|
||||
// Copyright © 2007 Matthias Neeracher
|
||||
//
|
||||
|
||||
#include <VLModel.h>
|
||||
#include <vector>
|
||||
|
||||
class VLSystemLayout {
|
||||
public:
|
||||
VLSystemLayout(const VLProperties & prop, float width);
|
||||
|
||||
float ClefKeyWidth() const { return fClefKeyWidth; }
|
||||
float MeasureWidth() const { return fMeasureWidth; }
|
||||
float MeasurePosition(int m) const { return fClefKeyWidth+m*fMeasureWidth; }
|
||||
float SystemWidth() const { return MeasurePosition(fNumMeasures); }
|
||||
int Divisions() const { return fDivisions; }
|
||||
int NumGroups() const { return fNumGroups; }
|
||||
int DivPerGroup() const { return fDivPerGroup; }
|
||||
int NumMeasures() const { return fNumMeasures; }
|
||||
private:
|
||||
float fClefKeyWidth;
|
||||
float fMeasureWidth;
|
||||
int fDivisions;
|
||||
int fNumGroups;
|
||||
int fDivPerGroup;
|
||||
int fNumMeasures;
|
||||
};
|
||||
|
||||
class VLLayout : public std::vector<VLSystemLayout> {
|
||||
public:
|
||||
VLLayout(const VLSong & song, float width);
|
||||
|
||||
int FirstMeasure(int system) const;
|
||||
int SystemForMeasure(int measure) const;
|
||||
int NumSystems() const { return size(); }
|
||||
float MeasurePosition(int measure) const;
|
||||
float NotePosition(int measure, VLFraction at) const;
|
||||
};
|
||||
|
||||
// Local Variables:
|
||||
// mode:C++
|
||||
// End:
|
|
@ -11,6 +11,7 @@
|
|||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#import "VLModel.h"
|
||||
#import "VLLayout.h"
|
||||
|
||||
@class VLDocument;
|
||||
|
||||
|
@ -63,14 +64,7 @@ enum VLRecalc {
|
|||
NSImage ** fMusic;
|
||||
VLRecalc fNeedsRecalc;
|
||||
char fClickMode;
|
||||
float fClefKeyW;
|
||||
float fMeasureW;
|
||||
size_t fLastMeasures;
|
||||
int fGroups;
|
||||
int fQuarterBeats;
|
||||
int fDivPerGroup;
|
||||
int fMeasPerSystem;
|
||||
int fNumSystems;
|
||||
float fDisplayScale;
|
||||
NSPoint fLastNoteCenter;
|
||||
NSTrackingRectTag fCursorTracking;
|
||||
|
@ -88,6 +82,7 @@ enum VLRecalc {
|
|||
int fNumStanzas;
|
||||
size_t fVolta;
|
||||
size_t fVoltaOK;
|
||||
VLLayout * fLayout;
|
||||
|
||||
IBOutlet id fFieldEditor;
|
||||
IBOutlet id fRepeatSheet;
|
||||
|
|
|
@ -195,26 +195,23 @@ VLMusicElement sSemi2Accidental[12][12] = {
|
|||
|
||||
- (float) noteYInMeasure:(int)measure withPitch:(int)pitch accidental:(VLMusicElement*)accidental
|
||||
{
|
||||
return [self systemY:measure/fMeasPerSystem]
|
||||
return [self systemY:fLayout->SystemForMeasure(measure)]
|
||||
+ [self noteYWithPitch:pitch accidental:accidental];
|
||||
}
|
||||
|
||||
- (float) noteXInMeasure:(int)measure at:(VLFraction)at
|
||||
{
|
||||
const VLProperties & prop = [self song]->fProperties.front();
|
||||
const float mx = fClefKeyW+(measure%fMeasPerSystem)*fMeasureW;
|
||||
|
||||
at *= 4 * prop.fDivisions;
|
||||
int div = at.fNum / at.fDenom;
|
||||
|
||||
return mx + (div + (div / fDivPerGroup) + 1)*kNoteW;
|
||||
return fLayout->NotePosition(measure, at);
|
||||
}
|
||||
|
||||
- (void) scrollMeasureToVisible:(int)measure
|
||||
{
|
||||
NSRect r = NSMakeRect(fClefKeyW+(measure%fMeasPerSystem)*fMeasureW,
|
||||
[self systemY:measure/fMeasPerSystem]-kSystemBaseline,
|
||||
fMeasureW, kSystemH);
|
||||
const int system = fLayout->SystemForMeasure(measure);
|
||||
const VLSystemLayout & kLayout = (*fLayout)[system];
|
||||
NSRect r = NSMakeRect(
|
||||
fLayout->MeasurePosition(measure),
|
||||
[self systemY:system]-kSystemBaseline,
|
||||
kLayout.MeasureWidth(), kSystemH);
|
||||
[self scrollRectToVisible:r];
|
||||
}
|
||||
|
||||
|
@ -264,17 +261,9 @@ VLMusicElement sSemi2Accidental[12][12] = {
|
|||
|
||||
NSSize sz = [scroll contentSize];
|
||||
|
||||
const VLSong * song = [self song];
|
||||
const VLProperties & prop = song->fProperties.front();
|
||||
|
||||
fGroups = prop.fTime.fNum / std::max(prop.fTime.fDenom / 4, 1);
|
||||
fQuarterBeats = (prop.fTime.fNum*4) / prop.fTime.fDenom;
|
||||
fDivPerGroup = prop.fDivisions * (fQuarterBeats / fGroups);
|
||||
fClefKeyW = kClefX+kClefW+(std::labs(prop.fKey)+1)*kKeyW;
|
||||
fMeasureW = fGroups*(fDivPerGroup+1)*kNoteW;
|
||||
fMeasPerSystem = std::max<int>(1, std::floor((sz.width-fClefKeyW) / fDisplayScale / fMeasureW));
|
||||
fNumSystems = std::max(2lu, (song->CountMeasures()+fMeasPerSystem-1)/fMeasPerSystem);
|
||||
sz.height = fNumSystems*kSystemH;
|
||||
delete fLayout;
|
||||
fLayout = new VLLayout(*[self song], sz.width / fDisplayScale);
|
||||
sz.height = fLayout->NumSystems()*kSystemH;
|
||||
|
||||
NSSize boundsSz = {sz.width / fDisplayScale, sz.height / fDisplayScale};
|
||||
|
||||
|
@ -290,7 +279,7 @@ VLMusicElement sSemi2Accidental[12][12] = {
|
|||
NSMakePoint(0.0, NSMaxY([dv frame])-NSHeight([cv bounds]))];
|
||||
}
|
||||
|
||||
fLastMeasures = song->CountMeasures();
|
||||
fLastMeasures = [self song]->CountMeasures();
|
||||
fNeedsRecalc = kNoRecalc;
|
||||
}
|
||||
|
||||
|
@ -304,11 +293,14 @@ VLMusicElement sSemi2Accidental[12][12] = {
|
|||
NSFontAttributeName,
|
||||
nil];
|
||||
|
||||
const float kSystemY = [self systemY:system];
|
||||
const float kLineW = fClefKeyW + fMeasPerSystem*fMeasureW;
|
||||
|
||||
const VLSystemLayout & kLayout = (*fLayout)[system];
|
||||
const VLSong * song = [self song];
|
||||
const VLProperties & prop = song->fProperties.front();
|
||||
const VLProperties & kProp =
|
||||
song->fProperties[song->fMeasures[fLayout->FirstMeasure(system)].fPropIdx];
|
||||
|
||||
const float kSystemY = [self systemY:system];
|
||||
const float kLineW = (*fLayout)[system].SystemWidth();
|
||||
const float kMeasureW = kLayout.MeasureWidth();
|
||||
|
||||
NSBezierPath * bz = [NSBezierPath bezierPath];
|
||||
|
||||
|
@ -327,22 +319,22 @@ VLMusicElement sSemi2Accidental[12][12] = {
|
|||
// Draw measure lines
|
||||
//
|
||||
[bz setLineWidth:2.0];
|
||||
int m = system*fMeasPerSystem;
|
||||
for (int measure = 0; measure<=fMeasPerSystem; ++measure, ++m) {
|
||||
int m = fLayout->FirstMeasure(system);
|
||||
for (int measure = 0; measure<=kLayout.NumMeasures(); ++measure, ++m) {
|
||||
const float kDblLineOff = 1.5f;
|
||||
const float kThick = 2.5f;
|
||||
const float kThin = 1.0f;
|
||||
const float kDotOff = 4.5f;
|
||||
const float kDotRadius = 2.0f;
|
||||
const float kVoltaTextOff = 7.0f;
|
||||
const float x = fClefKeyW+measure*fMeasureW;
|
||||
const float x = kLayout.MeasurePosition(measure);
|
||||
const float yy = kSystemY+4.0f*kLineH;
|
||||
bool repeat;
|
||||
size_t volta;
|
||||
bool dotsPrecede= measure != 0 &&
|
||||
(song->DoesEndRepeat(m)
|
||||
|| (song->DoesEndEnding(m, &repeat) && repeat));
|
||||
bool dotsFollow = measure<fMeasPerSystem && song->DoesBeginRepeat(m);
|
||||
bool dotsFollow = measure<kLayout.NumMeasures() && song->DoesBeginRepeat(m);
|
||||
if (!dotsPrecede && !dotsFollow) {
|
||||
//
|
||||
// Regular
|
||||
|
@ -388,12 +380,12 @@ VLMusicElement sSemi2Accidental[12][12] = {
|
|||
[bz fill];
|
||||
[bz removeAllPoints];
|
||||
}
|
||||
if (measure<fMeasPerSystem) {
|
||||
if (measure<kLayout.NumMeasures()) {
|
||||
if (song->DoesBeginEnding(m, 0, &volta)) {
|
||||
[bz setLineWidth:kThin];
|
||||
[bz moveToPoint: NSMakePoint(x+kDblLineOff, yy+0.5f*kLineH)];
|
||||
[bz lineToPoint: NSMakePoint(x+kDblLineOff, yy+2.0f*kLineH)];
|
||||
[bz lineToPoint: NSMakePoint(x+0.5f*fMeasureW, yy+2.0f*kLineH)];
|
||||
[bz lineToPoint: NSMakePoint(x+0.5f*kMeasureW, yy+2.0f*kLineH)];
|
||||
[bz stroke];
|
||||
[bz removeAllPoints];
|
||||
[bz setLineWidth:2.0];
|
||||
|
@ -409,10 +401,10 @@ VLMusicElement sSemi2Accidental[12][12] = {
|
|||
}
|
||||
if (song->DoesEndEnding(m+1, &repeat)) {
|
||||
[bz setLineWidth:kThin];
|
||||
[bz moveToPoint: NSMakePoint(x+0.5f*fMeasureW, yy+2.0f*kLineH)];
|
||||
[bz lineToPoint: NSMakePoint(x+fMeasureW-kDblLineOff, yy+2.0f*kLineH)];
|
||||
[bz moveToPoint: NSMakePoint(x+0.5f*kMeasureW, yy+2.0f*kLineH)];
|
||||
[bz lineToPoint: NSMakePoint(x+kMeasureW-kDblLineOff, yy+2.0f*kLineH)];
|
||||
if (repeat)
|
||||
[bz lineToPoint: NSMakePoint(x+fMeasureW-kDblLineOff, yy+0.5f*kLineH)];
|
||||
[bz lineToPoint: NSMakePoint(x+kMeasureW-kDblLineOff, yy+0.5f*kLineH)];
|
||||
[bz stroke];
|
||||
[bz removeAllPoints];
|
||||
[bz setLineWidth:2.0];
|
||||
|
@ -429,13 +421,13 @@ VLMusicElement sSemi2Accidental[12][12] = {
|
|||
//
|
||||
[bz setLineWidth:0.0];
|
||||
[[NSColor colorWithDeviceWhite:0.8f alpha:1.0f] set];
|
||||
for (int measure = 0; measure<fMeasPerSystem; ++measure) {
|
||||
const float mx = fClefKeyW+measure*fMeasureW;
|
||||
for (int measure = 0; measure<kLayout.NumMeasures(); ++measure) {
|
||||
const float mx = kLayout.MeasurePosition(measure);
|
||||
const float y0 = kSystemY-(fNumBotLedgers+1)*kLineH;
|
||||
const float yy = kSystemY+(fNumTopLedgers+5)*kLineH;
|
||||
for (int group = 0; group < fGroups; ++group) {
|
||||
for (int div = 0; div < fDivPerGroup; ++div) {
|
||||
const float x = mx+(group*(fDivPerGroup+1)+div+1)*kNoteW;
|
||||
for (int group = 0; group < kLayout.NumGroups(); ++group) {
|
||||
for (int div = 0; div < kLayout.DivPerGroup(); ++div) {
|
||||
const float x = mx+(group*(kLayout.DivPerGroup()+1)+div+1)*kNoteW;
|
||||
[bz moveToPoint: NSMakePoint(x, y0)];
|
||||
[bz lineToPoint: NSMakePoint(x, yy)];
|
||||
}
|
||||
|
@ -452,24 +444,24 @@ VLMusicElement sSemi2Accidental[12][12] = {
|
|||
//
|
||||
// Draw measure #
|
||||
//
|
||||
[[NSString stringWithFormat:@"%d", system*fMeasPerSystem+1]
|
||||
[[NSString stringWithFormat:@"%d", fLayout->FirstMeasure(system)+1]
|
||||
drawAtPoint: NSMakePoint(kMeasNoX, kSystemY+kMeasNoY)
|
||||
withAttributes: sMeasNoFont];
|
||||
//
|
||||
// Draw key (sharps & flats)
|
||||
//
|
||||
if (prop.fKey > 0) {
|
||||
if (kProp.fKey > 0) {
|
||||
float x = kClefX+kClefW;
|
||||
for (int i=0; i<prop.fKey; ++i) {
|
||||
for (int i=0; i<kProp.fKey; ++i) {
|
||||
[[self musicElement:kMusicSharp]
|
||||
compositeToPoint:
|
||||
NSMakePoint(x, kSystemY+sSharpPos[i]+kSharpY)
|
||||
operation: NSCompositeSourceOver];
|
||||
x += kAccW;
|
||||
}
|
||||
} else if (prop.fKey < 0) {
|
||||
} else if (kProp.fKey < 0) {
|
||||
float x = kClefX+kClefW;
|
||||
for (int i=0; -i>prop.fKey; ++i) {
|
||||
for (int i=0; -i>kProp.fKey; ++i) {
|
||||
[[self musicElement: kMusicFlat]
|
||||
compositeToPoint:
|
||||
NSMakePoint(x, kSystemY+sFlatPos[i]+kFlatY)
|
||||
|
@ -482,7 +474,7 @@ VLMusicElement sSemi2Accidental[12][12] = {
|
|||
- (void)drawBackgroundForSystem:(int)system
|
||||
{
|
||||
const float kSystemY = [self systemY:system];
|
||||
const float kLineW = fClefKeyW + fMeasPerSystem*fMeasureW;
|
||||
const float kLineW = (*fLayout)[system].SystemWidth();
|
||||
|
||||
NSArray * colors = [NSColor controlAlternatingRowBackgroundColors];
|
||||
[NSGraphicsContext saveGraphicsState];
|
||||
|
@ -501,20 +493,21 @@ VLMusicElement sSemi2Accidental[12][12] = {
|
|||
|
||||
- (void)highlightSelectionForSystem:(int)system
|
||||
{
|
||||
int startMeas = std::max(fSelStart-system*fMeasPerSystem, 0);
|
||||
int endMeas = std::min(fSelEnd-system*fMeasPerSystem, fMeasPerSystem);
|
||||
int startMeas = std::max(fSelStart-fLayout->FirstMeasure(system), 0);
|
||||
int endMeas = std::min(fSelEnd-fLayout->FirstMeasure(system), (*fLayout)[system].NumMeasures());
|
||||
const float kRawSystemY = [self systemY:system]-kSystemBaseline;
|
||||
const VLSystemLayout & kLayout = (*fLayout)[system];
|
||||
|
||||
[NSGraphicsContext saveGraphicsState];
|
||||
[[NSColor selectedTextBackgroundColor] setFill];
|
||||
if (fSelStart == fSelEnd)
|
||||
[NSBezierPath fillRect:
|
||||
NSMakeRect(fClefKeyW+startMeas*fMeasureW-kMeasTol, kRawSystemY,
|
||||
NSMakeRect(kLayout.MeasurePosition(startMeas)-kMeasTol, kRawSystemY,
|
||||
2.0f*kMeasTol, kSystemH)];
|
||||
else
|
||||
[NSBezierPath fillRect:
|
||||
NSMakeRect(fClefKeyW+startMeas*fMeasureW, kRawSystemY,
|
||||
(endMeas-startMeas)*fMeasureW, kSystemH)];
|
||||
NSMakeRect(kLayout.MeasurePosition(startMeas), kRawSystemY,
|
||||
(endMeas-startMeas)*kLayout.MeasureWidth(), kSystemH)];
|
||||
[NSGraphicsContext restoreGraphicsState];
|
||||
}
|
||||
|
||||
|
@ -530,10 +523,9 @@ VLMusicElement sSemi2Accidental[12][12] = {
|
|||
[NSGraphicsContext restoreGraphicsState];
|
||||
|
||||
size_t stanzas = [self song]->CountStanzas();
|
||||
const float kLineW = fClefKeyW + fMeasPerSystem*fMeasureW;
|
||||
for (int system = 0; system<fNumSystems; ++system) {
|
||||
for (int system = 0; system<fLayout->NumSystems(); ++system) {
|
||||
const float kSystemY = [self systemY:system];
|
||||
NSRect systemRect = NSMakeRect(kLineX, kSystemY-kSystemBaseline, kLineW, kSystemH);
|
||||
NSRect systemRect = NSMakeRect(kLineX, kSystemY-kSystemBaseline, (*fLayout)[system].SystemWidth(), kSystemH);
|
||||
if (!NSIntersectsRect(rect, systemRect))
|
||||
continue; // This system does not need to be drawn
|
||||
|
||||
|
@ -543,8 +535,8 @@ VLMusicElement sSemi2Accidental[12][12] = {
|
|||
// on top.
|
||||
//
|
||||
if (fSelStart <= fSelEnd
|
||||
&& (system+1)*fMeasPerSystem > fSelStart
|
||||
&& system*fMeasPerSystem < fSelEnd+(fSelStart==fSelEnd)
|
||||
&& fLayout->FirstMeasure(system+1) > fSelStart
|
||||
&& fLayout->FirstMeasure(system) < fSelEnd+(fSelStart==fSelEnd)
|
||||
)
|
||||
[self highlightSelectionForSystem:system];
|
||||
[self drawGridForSystem:system];
|
||||
|
@ -734,39 +726,42 @@ static int8_t sSharpAcc[] = {
|
|||
NSPoint loc = [event locationInWindow];
|
||||
loc = [self convertPoint:loc fromView:nil];
|
||||
|
||||
if (loc.y < 0.0f || loc.y >= fNumSystems*kSystemH)
|
||||
if (loc.y < 0.0f || loc.y >= fLayout->NumSystems()*kSystemH)
|
||||
return fCursorRegion = kRegionNowhere;
|
||||
|
||||
int system = fNumSystems - static_cast<int>(loc.y / kSystemH) - 1;
|
||||
int system = fLayout->NumSystems() - static_cast<int>(loc.y / kSystemH) - 1;
|
||||
const VLSystemLayout & kLayout = (*fLayout)[system];
|
||||
const float kMeasureW = kLayout.MeasureWidth();
|
||||
loc.y = fmodf(loc.y, kSystemH);
|
||||
|
||||
loc.x -= fClefKeyW;
|
||||
if (loc.y > kSystemBaseline && loc.y < kSystemBaseline+4.0f*kLineH
|
||||
&& fmodf(loc.x+kMeasTol, fMeasureW) < 2*kMeasTol
|
||||
) {
|
||||
int measure = static_cast<int>((loc.x+kMeasTol)/fMeasureW);
|
||||
loc.x -= kLayout.ClefKeyWidth();
|
||||
|
||||
if (measure < 0 || measure > fMeasPerSystem)
|
||||
if (loc.y > kSystemBaseline && loc.y < kSystemBaseline+4.0f*kLineH
|
||||
&& fmodf(loc.x+kMeasTol, kMeasureW) < 2*kMeasTol
|
||||
) {
|
||||
int measure = static_cast<int>((loc.x+kMeasTol)/kMeasureW);
|
||||
|
||||
if (measure < 0 || measure > kLayout.NumMeasures())
|
||||
return fCursorRegion = kRegionNowhere;
|
||||
|
||||
fCursorMeasure = measure+system*fMeasPerSystem;
|
||||
fCursorMeasure = measure+fLayout->FirstMeasure(system);
|
||||
|
||||
if (fCursorMeasure > [self song]->fMeasures.size())
|
||||
return fCursorRegion = kRegionNowhere;
|
||||
else
|
||||
return fCursorRegion = kRegionMeasure;
|
||||
}
|
||||
if (loc.x < 0.0f || loc.x >= fMeasPerSystem*fMeasureW)
|
||||
if (loc.x < 0.0f || loc.x >= kLayout.NumMeasures()*kMeasureW)
|
||||
return fCursorRegion = kRegionNowhere;
|
||||
|
||||
int measure = static_cast<int>(loc.x / fMeasureW);
|
||||
loc.x -= measure*fMeasureW;
|
||||
int group = static_cast<int>(loc.x / ((fDivPerGroup+1)*kNoteW));
|
||||
loc.x -= group*(fDivPerGroup+1)*kNoteW;
|
||||
int measure = static_cast<int>(loc.x / kMeasureW);
|
||||
loc.x -= measure*kMeasureW;
|
||||
int group = static_cast<int>(loc.x / ((kLayout.DivPerGroup()+1)*kNoteW));
|
||||
loc.x -= group*(kLayout.DivPerGroup()+1)*kNoteW;
|
||||
int div = static_cast<int>(roundf(loc.x / kNoteW))-1;
|
||||
div = std::min(std::max(div, 0), fDivPerGroup-1);
|
||||
fCursorAt = VLFraction(div+group*fDivPerGroup, 4*prop.fDivisions);
|
||||
fCursorMeasure = measure+system*fMeasPerSystem;
|
||||
div = std::min(std::max(div, 0), kLayout.DivPerGroup()-1);
|
||||
fCursorAt = VLFraction(div+group*kLayout.DivPerGroup(), 4*prop.fDivisions);
|
||||
fCursorMeasure = measure+fLayout->FirstMeasure(system);
|
||||
|
||||
if (fCursorMeasure > [self song]->fMeasures.size())
|
||||
return fCursorRegion = kRegionNowhere;
|
||||
|
@ -1044,3 +1039,4 @@ static int8_t sSharpAcc[] = {
|
|||
}
|
||||
|
||||
@end
|
||||
|
|
@ -229,12 +229,14 @@ std::string NormalizeName(NSString* rawName)
|
|||
{
|
||||
const VLSong * song = [self song];
|
||||
const float kSystemY = [self systemY:system];
|
||||
const int kFirstMeas = fLayout->FirstMeasure(system);
|
||||
const VLSystemLayout & kLayout = (*fLayout)[system];
|
||||
|
||||
//
|
||||
// Build new list
|
||||
//
|
||||
for (int m = 0; m<fMeasPerSystem; ++m) {
|
||||
int measIdx = m+system*fMeasPerSystem;
|
||||
for (int m = 0; m<kLayout.NumMeasures(); ++m) {
|
||||
int measIdx = m+kFirstMeas;
|
||||
if (measIdx >= song->CountMeasures())
|
||||
break;
|
||||
const VLMeasure measure = song->fMeasures[measIdx];
|
||||
|
@ -268,7 +270,7 @@ std::string NormalizeName(NSString* rawName)
|
|||
- (void) highlightChordInMeasure:(int)measure at:(VLFraction)at
|
||||
{
|
||||
const VLProperties & prop = [self song]->fProperties.front();
|
||||
const float kSystemY = [self systemY:measure / fMeasPerSystem];
|
||||
const float kSystemY = [self systemY:fLayout->SystemForMeasure(measure)];
|
||||
NSRect r =
|
||||
NSMakeRect([self noteXInMeasure:measure at:at]-kNoteW*0.5f,
|
||||
kSystemY+kChordY, prop.fDivisions*kNoteW, kChordH);
|
||||
|
|
|
@ -114,12 +114,14 @@
|
|||
|
||||
const VLSong * song = [self song];
|
||||
const float kSystemY = [self systemY:system];
|
||||
const VLSystemLayout & kLayout = (*fLayout)[system];
|
||||
const int kFirstMeas = fLayout->FirstMeasure(system);
|
||||
|
||||
//
|
||||
// Build new list
|
||||
//
|
||||
for (int m = 0; m<fMeasPerSystem; ++m) {
|
||||
int measIdx = m+system*fMeasPerSystem;
|
||||
for (int m = 0; m<kLayout.NumMeasures(); ++m) {
|
||||
int measIdx = m+kFirstMeas;
|
||||
if (measIdx >= song->CountMeasures())
|
||||
break;
|
||||
const VLMeasure measure = song->fMeasures[measIdx];
|
||||
|
|
|
@ -93,7 +93,7 @@
|
|||
withPitch:fCursorPitch accidental:&accidental] - kNoteY;
|
||||
[self drawLedgerLinesWithPitch:fCursorPitch
|
||||
at:NSMakePoint(cursorX,
|
||||
[self systemY:fCursorMeasure/fMeasPerSystem])];
|
||||
[self systemY:fLayout->SystemForMeasure(fCursorMeasure)])];
|
||||
cursorElt = kMusicNoteCursor;
|
||||
break;
|
||||
case 'r':
|
||||
|
@ -277,19 +277,22 @@
|
|||
|
||||
- (void) drawNotesForSystem:(int)system
|
||||
{
|
||||
const int kFirstMeas = fLayout->FirstMeasure(system);
|
||||
const VLSong * song = [self song];
|
||||
const VLProperties & prop = song->fProperties.front();
|
||||
const VLProperties & kProp =
|
||||
song->fProperties[song->fMeasures[kFirstMeas].fPropIdx];
|
||||
const VLSystemLayout & kLayout = (*fLayout)[system];
|
||||
|
||||
float kSystemY = [self systemY:system];
|
||||
for (int m = 0; m<fMeasPerSystem; ++m) {
|
||||
for (int m = 0; m<kLayout.NumMeasures(); ++m) {
|
||||
VLMusicElement accidentals[7];
|
||||
memset(accidentals, 0, 7*sizeof(VLMusicElement));
|
||||
int measIdx = m+system*fMeasPerSystem;
|
||||
int measIdx = m+kFirstMeas;
|
||||
if (measIdx >= song->CountMeasures())
|
||||
break;
|
||||
const VLMeasure & measure = song->fMeasures[measIdx];
|
||||
VLNoteList melody;
|
||||
measure.DecomposeNotes(song->fProperties[measure.fPropIdx], melody);
|
||||
measure.DecomposeNotes(kProp, melody);
|
||||
VLFraction at(0);
|
||||
for (VLNoteList::const_iterator note = melody.begin();
|
||||
note != melody.end();
|
||||
|
@ -312,7 +315,7 @@
|
|||
acc = kMusicNothing; // Don't repeat accidentals
|
||||
else if (acc == kMusicNothing)
|
||||
if (accidentals[step] == kMusicNatural) // Resume signature
|
||||
acc = prop.fKey < 0 ? kMusicFlat : kMusicSharp;
|
||||
acc = kProp.fKey < 0 ? kMusicFlat : kMusicSharp;
|
||||
else
|
||||
acc = kMusicNatural;
|
||||
[self drawNote:note->fVisual & VLNote::kNoteHead
|
||||
|
@ -331,7 +334,7 @@
|
|||
at += note->fDuration;
|
||||
}
|
||||
}
|
||||
if (fCursorPitch != VLNote::kNoPitch && fCursorMeasure/fMeasPerSystem == system)
|
||||
if (fCursorPitch != VLNote::kNoPitch && fLayout->SystemForMeasure(fCursorMeasure) == system)
|
||||
[self drawNoteCursor];
|
||||
}
|
||||
|
||||
|
|
|
@ -75,6 +75,7 @@
|
|||
95C461FE0B04432700649F92 /* MMA in Copy MMA Library */ = {isa = PBXBuildFile; fileRef = 95C461DD0B04430F00649F92 /* MMA */; };
|
||||
95C462000B04472E00649F92 /* mmaWrapper in Copy Tools */ = {isa = PBXBuildFile; fileRef = 95C461FF0B04472900649F92 /* mmaWrapper */; };
|
||||
95C462830B045CB700649F92 /* lilyWrapper in Copy Tools */ = {isa = PBXBuildFile; fileRef = 95C4627A0B045C8E00649F92 /* lilyWrapper */; };
|
||||
95D0597A0D1E6B0D00E28FAE /* VLLayout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95D059780D1E6B0D00E28FAE /* VLLayout.cpp */; };
|
||||
95D0C2FC0B785D020061080E /* rebuildGrooves in Copy Tools */ = {isa = PBXBuildFile; fileRef = 95D0C2FB0B785D020061080E /* rebuildGrooves */; };
|
||||
95E04DA70AEB486E006F30A0 /* TVLLilypond.mm in Sources */ = {isa = PBXBuildFile; fileRef = 95E04DA60AEB486E006F30A0 /* TVLLilypond.mm */; };
|
||||
95E04DA80AEB4878006F30A0 /* VLDocument.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2A37F4ACFDCFA73011CA2CEA /* VLDocument.mm */; };
|
||||
|
@ -246,6 +247,8 @@
|
|||
95C461DD0B04430F00649F92 /* MMA */ = {isa = PBXFileReference; lastKnownFileType = folder; name = MMA; path = mma/MMA; sourceTree = "<group>"; };
|
||||
95C461FF0B04472900649F92 /* mmaWrapper */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.sh; name = mmaWrapper; path = Tools/mmaWrapper; sourceTree = "<group>"; };
|
||||
95C4627A0B045C8E00649F92 /* lilyWrapper */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.sh; name = lilyWrapper; path = Tools/lilyWrapper; sourceTree = "<group>"; };
|
||||
95D059780D1E6B0D00E28FAE /* VLLayout.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VLLayout.cpp; path = Sources/VLLayout.cpp; sourceTree = "<group>"; };
|
||||
95D059790D1E6B0D00E28FAE /* VLLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLLayout.h; path = Sources/VLLayout.h; sourceTree = "<group>"; };
|
||||
95D0C2FB0B785D020061080E /* rebuildGrooves */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; fileEncoding = 4; name = rebuildGrooves; path = Tools/rebuildGrooves; sourceTree = "<group>"; };
|
||||
95E04DA00AEB4837006F30A0 /* TVLLilypond */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = TVLLilypond; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
95E04DA60AEB486E006F30A0 /* TVLLilypond.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; name = TVLLilypond.mm; path = Tests/TVLLilypond.mm; sourceTree = "<group>"; };
|
||||
|
@ -381,6 +384,8 @@
|
|||
2A37F4ABFDCFA73011CA2CEA /* Classes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
95D059780D1E6B0D00E28FAE /* VLLayout.cpp */,
|
||||
95D059790D1E6B0D00E28FAE /* VLLayout.h */,
|
||||
9588365A0C6FABBA004B4162 /* VLDebugFlags.cpp */,
|
||||
9588365B0C6FABBA004B4162 /* VLDebugFlags.h */,
|
||||
9588363A0C6F9C7D004B4162 /* VLPListDocument.h */,
|
||||
|
@ -750,6 +755,7 @@
|
|||
9545C5C30C092F4600251547 /* VLMMAWriter.cpp in Sources */,
|
||||
9588363C0C6F9C7D004B4162 /* VLPListDocument.mm in Sources */,
|
||||
9588365C0C6FABBA004B4162 /* VLDebugFlags.cpp in Sources */,
|
||||
95D0597A0D1E6B0D00E28FAE /* VLLayout.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue
Block a user