Reorganize layout system

This commit is contained in:
Matthias Neeracher 2007-12-23 12:45:17 +00:00
parent 964d56a0f7
commit 80fbc00f56
8 changed files with 230 additions and 98 deletions

80
Sources/VLLayout.cpp Normal file
View 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
View 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:

View File

@ -11,6 +11,7 @@
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#import "VLModel.h" #import "VLModel.h"
#import "VLLayout.h"
@class VLDocument; @class VLDocument;
@ -63,14 +64,7 @@ enum VLRecalc {
NSImage ** fMusic; NSImage ** fMusic;
VLRecalc fNeedsRecalc; VLRecalc fNeedsRecalc;
char fClickMode; char fClickMode;
float fClefKeyW;
float fMeasureW;
size_t fLastMeasures; size_t fLastMeasures;
int fGroups;
int fQuarterBeats;
int fDivPerGroup;
int fMeasPerSystem;
int fNumSystems;
float fDisplayScale; float fDisplayScale;
NSPoint fLastNoteCenter; NSPoint fLastNoteCenter;
NSTrackingRectTag fCursorTracking; NSTrackingRectTag fCursorTracking;
@ -88,6 +82,7 @@ enum VLRecalc {
int fNumStanzas; int fNumStanzas;
size_t fVolta; size_t fVolta;
size_t fVoltaOK; size_t fVoltaOK;
VLLayout * fLayout;
IBOutlet id fFieldEditor; IBOutlet id fFieldEditor;
IBOutlet id fRepeatSheet; IBOutlet id fRepeatSheet;

View File

@ -195,26 +195,23 @@ VLMusicElement sSemi2Accidental[12][12] = {
- (float) noteYInMeasure:(int)measure withPitch:(int)pitch accidental:(VLMusicElement*)accidental - (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]; + [self noteYWithPitch:pitch accidental:accidental];
} }
- (float) noteXInMeasure:(int)measure at:(VLFraction)at - (float) noteXInMeasure:(int)measure at:(VLFraction)at
{ {
const VLProperties & prop = [self song]->fProperties.front(); return fLayout->NotePosition(measure, at);
const float mx = fClefKeyW+(measure%fMeasPerSystem)*fMeasureW;
at *= 4 * prop.fDivisions;
int div = at.fNum / at.fDenom;
return mx + (div + (div / fDivPerGroup) + 1)*kNoteW;
} }
- (void) scrollMeasureToVisible:(int)measure - (void) scrollMeasureToVisible:(int)measure
{ {
NSRect r = NSMakeRect(fClefKeyW+(measure%fMeasPerSystem)*fMeasureW, const int system = fLayout->SystemForMeasure(measure);
[self systemY:measure/fMeasPerSystem]-kSystemBaseline, const VLSystemLayout & kLayout = (*fLayout)[system];
fMeasureW, kSystemH); NSRect r = NSMakeRect(
fLayout->MeasurePosition(measure),
[self systemY:system]-kSystemBaseline,
kLayout.MeasureWidth(), kSystemH);
[self scrollRectToVisible:r]; [self scrollRectToVisible:r];
} }
@ -264,17 +261,9 @@ VLMusicElement sSemi2Accidental[12][12] = {
NSSize sz = [scroll contentSize]; NSSize sz = [scroll contentSize];
const VLSong * song = [self song]; delete fLayout;
const VLProperties & prop = song->fProperties.front(); fLayout = new VLLayout(*[self song], sz.width / fDisplayScale);
sz.height = fLayout->NumSystems()*kSystemH;
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;
NSSize boundsSz = {sz.width / fDisplayScale, sz.height / fDisplayScale}; 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]))]; NSMakePoint(0.0, NSMaxY([dv frame])-NSHeight([cv bounds]))];
} }
fLastMeasures = song->CountMeasures(); fLastMeasures = [self song]->CountMeasures();
fNeedsRecalc = kNoRecalc; fNeedsRecalc = kNoRecalc;
} }
@ -304,11 +293,14 @@ VLMusicElement sSemi2Accidental[12][12] = {
NSFontAttributeName, NSFontAttributeName,
nil]; nil];
const float kSystemY = [self systemY:system]; const VLSystemLayout & kLayout = (*fLayout)[system];
const float kLineW = fClefKeyW + fMeasPerSystem*fMeasureW;
const VLSong * song = [self song]; 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]; NSBezierPath * bz = [NSBezierPath bezierPath];
@ -327,22 +319,22 @@ VLMusicElement sSemi2Accidental[12][12] = {
// Draw measure lines // Draw measure lines
// //
[bz setLineWidth:2.0]; [bz setLineWidth:2.0];
int m = system*fMeasPerSystem; int m = fLayout->FirstMeasure(system);
for (int measure = 0; measure<=fMeasPerSystem; ++measure, ++m) { for (int measure = 0; measure<=kLayout.NumMeasures(); ++measure, ++m) {
const float kDblLineOff = 1.5f; const float kDblLineOff = 1.5f;
const float kThick = 2.5f; const float kThick = 2.5f;
const float kThin = 1.0f; const float kThin = 1.0f;
const float kDotOff = 4.5f; const float kDotOff = 4.5f;
const float kDotRadius = 2.0f; const float kDotRadius = 2.0f;
const float kVoltaTextOff = 7.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; const float yy = kSystemY+4.0f*kLineH;
bool repeat; bool repeat;
size_t volta; size_t volta;
bool dotsPrecede= measure != 0 && bool dotsPrecede= measure != 0 &&
(song->DoesEndRepeat(m) (song->DoesEndRepeat(m)
|| (song->DoesEndEnding(m, &repeat) && repeat)); || (song->DoesEndEnding(m, &repeat) && repeat));
bool dotsFollow = measure<fMeasPerSystem && song->DoesBeginRepeat(m); bool dotsFollow = measure<kLayout.NumMeasures() && song->DoesBeginRepeat(m);
if (!dotsPrecede && !dotsFollow) { if (!dotsPrecede && !dotsFollow) {
// //
// Regular // Regular
@ -388,12 +380,12 @@ VLMusicElement sSemi2Accidental[12][12] = {
[bz fill]; [bz fill];
[bz removeAllPoints]; [bz removeAllPoints];
} }
if (measure<fMeasPerSystem) { if (measure<kLayout.NumMeasures()) {
if (song->DoesBeginEnding(m, 0, &volta)) { if (song->DoesBeginEnding(m, 0, &volta)) {
[bz setLineWidth:kThin]; [bz setLineWidth:kThin];
[bz moveToPoint: NSMakePoint(x+kDblLineOff, yy+0.5f*kLineH)]; [bz moveToPoint: NSMakePoint(x+kDblLineOff, yy+0.5f*kLineH)];
[bz lineToPoint: NSMakePoint(x+kDblLineOff, yy+2.0f*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 stroke];
[bz removeAllPoints]; [bz removeAllPoints];
[bz setLineWidth:2.0]; [bz setLineWidth:2.0];
@ -409,10 +401,10 @@ VLMusicElement sSemi2Accidental[12][12] = {
} }
if (song->DoesEndEnding(m+1, &repeat)) { if (song->DoesEndEnding(m+1, &repeat)) {
[bz setLineWidth:kThin]; [bz setLineWidth:kThin];
[bz moveToPoint: NSMakePoint(x+0.5f*fMeasureW, yy+2.0f*kLineH)]; [bz moveToPoint: NSMakePoint(x+0.5f*kMeasureW, yy+2.0f*kLineH)];
[bz lineToPoint: NSMakePoint(x+fMeasureW-kDblLineOff, yy+2.0f*kLineH)]; [bz lineToPoint: NSMakePoint(x+kMeasureW-kDblLineOff, yy+2.0f*kLineH)];
if (repeat) 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 stroke];
[bz removeAllPoints]; [bz removeAllPoints];
[bz setLineWidth:2.0]; [bz setLineWidth:2.0];
@ -429,13 +421,13 @@ VLMusicElement sSemi2Accidental[12][12] = {
// //
[bz setLineWidth:0.0]; [bz setLineWidth:0.0];
[[NSColor colorWithDeviceWhite:0.8f alpha:1.0f] set]; [[NSColor colorWithDeviceWhite:0.8f alpha:1.0f] set];
for (int measure = 0; measure<fMeasPerSystem; ++measure) { for (int measure = 0; measure<kLayout.NumMeasures(); ++measure) {
const float mx = fClefKeyW+measure*fMeasureW; const float mx = kLayout.MeasurePosition(measure);
const float y0 = kSystemY-(fNumBotLedgers+1)*kLineH; const float y0 = kSystemY-(fNumBotLedgers+1)*kLineH;
const float yy = kSystemY+(fNumTopLedgers+5)*kLineH; const float yy = kSystemY+(fNumTopLedgers+5)*kLineH;
for (int group = 0; group < fGroups; ++group) { for (int group = 0; group < kLayout.NumGroups(); ++group) {
for (int div = 0; div < fDivPerGroup; ++div) { for (int div = 0; div < kLayout.DivPerGroup(); ++div) {
const float x = mx+(group*(fDivPerGroup+1)+div+1)*kNoteW; const float x = mx+(group*(kLayout.DivPerGroup()+1)+div+1)*kNoteW;
[bz moveToPoint: NSMakePoint(x, y0)]; [bz moveToPoint: NSMakePoint(x, y0)];
[bz lineToPoint: NSMakePoint(x, yy)]; [bz lineToPoint: NSMakePoint(x, yy)];
} }
@ -452,24 +444,24 @@ VLMusicElement sSemi2Accidental[12][12] = {
// //
// Draw measure # // Draw measure #
// //
[[NSString stringWithFormat:@"%d", system*fMeasPerSystem+1] [[NSString stringWithFormat:@"%d", fLayout->FirstMeasure(system)+1]
drawAtPoint: NSMakePoint(kMeasNoX, kSystemY+kMeasNoY) drawAtPoint: NSMakePoint(kMeasNoX, kSystemY+kMeasNoY)
withAttributes: sMeasNoFont]; withAttributes: sMeasNoFont];
// //
// Draw key (sharps & flats) // Draw key (sharps & flats)
// //
if (prop.fKey > 0) { if (kProp.fKey > 0) {
float x = kClefX+kClefW; float x = kClefX+kClefW;
for (int i=0; i<prop.fKey; ++i) { for (int i=0; i<kProp.fKey; ++i) {
[[self musicElement:kMusicSharp] [[self musicElement:kMusicSharp]
compositeToPoint: compositeToPoint:
NSMakePoint(x, kSystemY+sSharpPos[i]+kSharpY) NSMakePoint(x, kSystemY+sSharpPos[i]+kSharpY)
operation: NSCompositeSourceOver]; operation: NSCompositeSourceOver];
x += kAccW; x += kAccW;
} }
} else if (prop.fKey < 0) { } else if (kProp.fKey < 0) {
float x = kClefX+kClefW; float x = kClefX+kClefW;
for (int i=0; -i>prop.fKey; ++i) { for (int i=0; -i>kProp.fKey; ++i) {
[[self musicElement: kMusicFlat] [[self musicElement: kMusicFlat]
compositeToPoint: compositeToPoint:
NSMakePoint(x, kSystemY+sFlatPos[i]+kFlatY) NSMakePoint(x, kSystemY+sFlatPos[i]+kFlatY)
@ -482,7 +474,7 @@ VLMusicElement sSemi2Accidental[12][12] = {
- (void)drawBackgroundForSystem:(int)system - (void)drawBackgroundForSystem:(int)system
{ {
const float kSystemY = [self systemY:system]; const float kSystemY = [self systemY:system];
const float kLineW = fClefKeyW + fMeasPerSystem*fMeasureW; const float kLineW = (*fLayout)[system].SystemWidth();
NSArray * colors = [NSColor controlAlternatingRowBackgroundColors]; NSArray * colors = [NSColor controlAlternatingRowBackgroundColors];
[NSGraphicsContext saveGraphicsState]; [NSGraphicsContext saveGraphicsState];
@ -501,20 +493,21 @@ VLMusicElement sSemi2Accidental[12][12] = {
- (void)highlightSelectionForSystem:(int)system - (void)highlightSelectionForSystem:(int)system
{ {
int startMeas = std::max(fSelStart-system*fMeasPerSystem, 0); int startMeas = std::max(fSelStart-fLayout->FirstMeasure(system), 0);
int endMeas = std::min(fSelEnd-system*fMeasPerSystem, fMeasPerSystem); int endMeas = std::min(fSelEnd-fLayout->FirstMeasure(system), (*fLayout)[system].NumMeasures());
const float kRawSystemY = [self systemY:system]-kSystemBaseline; const float kRawSystemY = [self systemY:system]-kSystemBaseline;
const VLSystemLayout & kLayout = (*fLayout)[system];
[NSGraphicsContext saveGraphicsState]; [NSGraphicsContext saveGraphicsState];
[[NSColor selectedTextBackgroundColor] setFill]; [[NSColor selectedTextBackgroundColor] setFill];
if (fSelStart == fSelEnd) if (fSelStart == fSelEnd)
[NSBezierPath fillRect: [NSBezierPath fillRect:
NSMakeRect(fClefKeyW+startMeas*fMeasureW-kMeasTol, kRawSystemY, NSMakeRect(kLayout.MeasurePosition(startMeas)-kMeasTol, kRawSystemY,
2.0f*kMeasTol, kSystemH)]; 2.0f*kMeasTol, kSystemH)];
else else
[NSBezierPath fillRect: [NSBezierPath fillRect:
NSMakeRect(fClefKeyW+startMeas*fMeasureW, kRawSystemY, NSMakeRect(kLayout.MeasurePosition(startMeas), kRawSystemY,
(endMeas-startMeas)*fMeasureW, kSystemH)]; (endMeas-startMeas)*kLayout.MeasureWidth(), kSystemH)];
[NSGraphicsContext restoreGraphicsState]; [NSGraphicsContext restoreGraphicsState];
} }
@ -530,10 +523,9 @@ VLMusicElement sSemi2Accidental[12][12] = {
[NSGraphicsContext restoreGraphicsState]; [NSGraphicsContext restoreGraphicsState];
size_t stanzas = [self song]->CountStanzas(); size_t stanzas = [self song]->CountStanzas();
const float kLineW = fClefKeyW + fMeasPerSystem*fMeasureW; for (int system = 0; system<fLayout->NumSystems(); ++system) {
for (int system = 0; system<fNumSystems; ++system) {
const float kSystemY = [self systemY: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)) if (!NSIntersectsRect(rect, systemRect))
continue; // This system does not need to be drawn continue; // This system does not need to be drawn
@ -543,8 +535,8 @@ VLMusicElement sSemi2Accidental[12][12] = {
// on top. // on top.
// //
if (fSelStart <= fSelEnd if (fSelStart <= fSelEnd
&& (system+1)*fMeasPerSystem > fSelStart && fLayout->FirstMeasure(system+1) > fSelStart
&& system*fMeasPerSystem < fSelEnd+(fSelStart==fSelEnd) && fLayout->FirstMeasure(system) < fSelEnd+(fSelStart==fSelEnd)
) )
[self highlightSelectionForSystem:system]; [self highlightSelectionForSystem:system];
[self drawGridForSystem:system]; [self drawGridForSystem:system];
@ -734,39 +726,42 @@ static int8_t sSharpAcc[] = {
NSPoint loc = [event locationInWindow]; NSPoint loc = [event locationInWindow];
loc = [self convertPoint:loc fromView:nil]; 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; 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.y = fmodf(loc.y, kSystemH);
loc.x -= fClefKeyW; loc.x -= kLayout.ClefKeyWidth();
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);
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; return fCursorRegion = kRegionNowhere;
fCursorMeasure = measure+system*fMeasPerSystem; fCursorMeasure = measure+fLayout->FirstMeasure(system);
if (fCursorMeasure > [self song]->fMeasures.size()) if (fCursorMeasure > [self song]->fMeasures.size())
return fCursorRegion = kRegionNowhere; return fCursorRegion = kRegionNowhere;
else else
return fCursorRegion = kRegionMeasure; 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; return fCursorRegion = kRegionNowhere;
int measure = static_cast<int>(loc.x / fMeasureW); int measure = static_cast<int>(loc.x / kMeasureW);
loc.x -= measure*fMeasureW; loc.x -= measure*kMeasureW;
int group = static_cast<int>(loc.x / ((fDivPerGroup+1)*kNoteW)); int group = static_cast<int>(loc.x / ((kLayout.DivPerGroup()+1)*kNoteW));
loc.x -= group*(fDivPerGroup+1)*kNoteW; loc.x -= group*(kLayout.DivPerGroup()+1)*kNoteW;
int div = static_cast<int>(roundf(loc.x / kNoteW))-1; int div = static_cast<int>(roundf(loc.x / kNoteW))-1;
div = std::min(std::max(div, 0), fDivPerGroup-1); div = std::min(std::max(div, 0), kLayout.DivPerGroup()-1);
fCursorAt = VLFraction(div+group*fDivPerGroup, 4*prop.fDivisions); fCursorAt = VLFraction(div+group*kLayout.DivPerGroup(), 4*prop.fDivisions);
fCursorMeasure = measure+system*fMeasPerSystem; fCursorMeasure = measure+fLayout->FirstMeasure(system);
if (fCursorMeasure > [self song]->fMeasures.size()) if (fCursorMeasure > [self song]->fMeasures.size())
return fCursorRegion = kRegionNowhere; return fCursorRegion = kRegionNowhere;
@ -1044,3 +1039,4 @@ static int8_t sSharpAcc[] = {
} }
@end @end

View File

@ -229,12 +229,14 @@ std::string NormalizeName(NSString* rawName)
{ {
const VLSong * song = [self song]; const VLSong * song = [self song];
const float kSystemY = [self systemY:system]; const float kSystemY = [self systemY:system];
const int kFirstMeas = fLayout->FirstMeasure(system);
const VLSystemLayout & kLayout = (*fLayout)[system];
// //
// Build new list // Build new list
// //
for (int m = 0; m<fMeasPerSystem; ++m) { for (int m = 0; m<kLayout.NumMeasures(); ++m) {
int measIdx = m+system*fMeasPerSystem; int measIdx = m+kFirstMeas;
if (measIdx >= song->CountMeasures()) if (measIdx >= song->CountMeasures())
break; break;
const VLMeasure measure = song->fMeasures[measIdx]; const VLMeasure measure = song->fMeasures[measIdx];
@ -268,7 +270,7 @@ std::string NormalizeName(NSString* rawName)
- (void) highlightChordInMeasure:(int)measure at:(VLFraction)at - (void) highlightChordInMeasure:(int)measure at:(VLFraction)at
{ {
const VLProperties & prop = [self song]->fProperties.front(); const VLProperties & prop = [self song]->fProperties.front();
const float kSystemY = [self systemY:measure / fMeasPerSystem]; const float kSystemY = [self systemY:fLayout->SystemForMeasure(measure)];
NSRect r = NSRect r =
NSMakeRect([self noteXInMeasure:measure at:at]-kNoteW*0.5f, NSMakeRect([self noteXInMeasure:measure at:at]-kNoteW*0.5f,
kSystemY+kChordY, prop.fDivisions*kNoteW, kChordH); kSystemY+kChordY, prop.fDivisions*kNoteW, kChordH);

View File

@ -114,12 +114,14 @@
const VLSong * song = [self song]; const VLSong * song = [self song];
const float kSystemY = [self systemY:system]; const float kSystemY = [self systemY:system];
const VLSystemLayout & kLayout = (*fLayout)[system];
const int kFirstMeas = fLayout->FirstMeasure(system);
// //
// Build new list // Build new list
// //
for (int m = 0; m<fMeasPerSystem; ++m) { for (int m = 0; m<kLayout.NumMeasures(); ++m) {
int measIdx = m+system*fMeasPerSystem; int measIdx = m+kFirstMeas;
if (measIdx >= song->CountMeasures()) if (measIdx >= song->CountMeasures())
break; break;
const VLMeasure measure = song->fMeasures[measIdx]; const VLMeasure measure = song->fMeasures[measIdx];

View File

@ -93,7 +93,7 @@
withPitch:fCursorPitch accidental:&accidental] - kNoteY; withPitch:fCursorPitch accidental:&accidental] - kNoteY;
[self drawLedgerLinesWithPitch:fCursorPitch [self drawLedgerLinesWithPitch:fCursorPitch
at:NSMakePoint(cursorX, at:NSMakePoint(cursorX,
[self systemY:fCursorMeasure/fMeasPerSystem])]; [self systemY:fLayout->SystemForMeasure(fCursorMeasure)])];
cursorElt = kMusicNoteCursor; cursorElt = kMusicNoteCursor;
break; break;
case 'r': case 'r':
@ -277,19 +277,22 @@
- (void) drawNotesForSystem:(int)system - (void) drawNotesForSystem:(int)system
{ {
const int kFirstMeas = fLayout->FirstMeasure(system);
const VLSong * song = [self song]; 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]; float kSystemY = [self systemY:system];
for (int m = 0; m<fMeasPerSystem; ++m) { for (int m = 0; m<kLayout.NumMeasures(); ++m) {
VLMusicElement accidentals[7]; VLMusicElement accidentals[7];
memset(accidentals, 0, 7*sizeof(VLMusicElement)); memset(accidentals, 0, 7*sizeof(VLMusicElement));
int measIdx = m+system*fMeasPerSystem; int measIdx = m+kFirstMeas;
if (measIdx >= song->CountMeasures()) if (measIdx >= song->CountMeasures())
break; break;
const VLMeasure & measure = song->fMeasures[measIdx]; const VLMeasure & measure = song->fMeasures[measIdx];
VLNoteList melody; VLNoteList melody;
measure.DecomposeNotes(song->fProperties[measure.fPropIdx], melody); measure.DecomposeNotes(kProp, melody);
VLFraction at(0); VLFraction at(0);
for (VLNoteList::const_iterator note = melody.begin(); for (VLNoteList::const_iterator note = melody.begin();
note != melody.end(); note != melody.end();
@ -312,7 +315,7 @@
acc = kMusicNothing; // Don't repeat accidentals acc = kMusicNothing; // Don't repeat accidentals
else if (acc == kMusicNothing) else if (acc == kMusicNothing)
if (accidentals[step] == kMusicNatural) // Resume signature if (accidentals[step] == kMusicNatural) // Resume signature
acc = prop.fKey < 0 ? kMusicFlat : kMusicSharp; acc = kProp.fKey < 0 ? kMusicFlat : kMusicSharp;
else else
acc = kMusicNatural; acc = kMusicNatural;
[self drawNote:note->fVisual & VLNote::kNoteHead [self drawNote:note->fVisual & VLNote::kNoteHead
@ -331,7 +334,7 @@
at += note->fDuration; at += note->fDuration;
} }
} }
if (fCursorPitch != VLNote::kNoPitch && fCursorMeasure/fMeasPerSystem == system) if (fCursorPitch != VLNote::kNoPitch && fLayout->SystemForMeasure(fCursorMeasure) == system)
[self drawNoteCursor]; [self drawNoteCursor];
} }

View File

@ -75,6 +75,7 @@
95C461FE0B04432700649F92 /* MMA in Copy MMA Library */ = {isa = PBXBuildFile; fileRef = 95C461DD0B04430F00649F92 /* MMA */; }; 95C461FE0B04432700649F92 /* MMA in Copy MMA Library */ = {isa = PBXBuildFile; fileRef = 95C461DD0B04430F00649F92 /* MMA */; };
95C462000B04472E00649F92 /* mmaWrapper in Copy Tools */ = {isa = PBXBuildFile; fileRef = 95C461FF0B04472900649F92 /* mmaWrapper */; }; 95C462000B04472E00649F92 /* mmaWrapper in Copy Tools */ = {isa = PBXBuildFile; fileRef = 95C461FF0B04472900649F92 /* mmaWrapper */; };
95C462830B045CB700649F92 /* lilyWrapper in Copy Tools */ = {isa = PBXBuildFile; fileRef = 95C4627A0B045C8E00649F92 /* lilyWrapper */; }; 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 */; }; 95D0C2FC0B785D020061080E /* rebuildGrooves in Copy Tools */ = {isa = PBXBuildFile; fileRef = 95D0C2FB0B785D020061080E /* rebuildGrooves */; };
95E04DA70AEB486E006F30A0 /* TVLLilypond.mm in Sources */ = {isa = PBXBuildFile; fileRef = 95E04DA60AEB486E006F30A0 /* TVLLilypond.mm */; }; 95E04DA70AEB486E006F30A0 /* TVLLilypond.mm in Sources */ = {isa = PBXBuildFile; fileRef = 95E04DA60AEB486E006F30A0 /* TVLLilypond.mm */; };
95E04DA80AEB4878006F30A0 /* VLDocument.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2A37F4ACFDCFA73011CA2CEA /* VLDocument.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>"; }; 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>"; }; 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>"; }; 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>"; }; 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; }; 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>"; }; 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 */ = { 2A37F4ABFDCFA73011CA2CEA /* Classes */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
95D059780D1E6B0D00E28FAE /* VLLayout.cpp */,
95D059790D1E6B0D00E28FAE /* VLLayout.h */,
9588365A0C6FABBA004B4162 /* VLDebugFlags.cpp */, 9588365A0C6FABBA004B4162 /* VLDebugFlags.cpp */,
9588365B0C6FABBA004B4162 /* VLDebugFlags.h */, 9588365B0C6FABBA004B4162 /* VLDebugFlags.h */,
9588363A0C6F9C7D004B4162 /* VLPListDocument.h */, 9588363A0C6F9C7D004B4162 /* VLPListDocument.h */,
@ -750,6 +755,7 @@
9545C5C30C092F4600251547 /* VLMMAWriter.cpp in Sources */, 9545C5C30C092F4600251547 /* VLMMAWriter.cpp in Sources */,
9588363C0C6F9C7D004B4162 /* VLPListDocument.mm in Sources */, 9588363C0C6F9C7D004B4162 /* VLPListDocument.mm in Sources */,
9588365C0C6FABBA004B4162 /* VLDebugFlags.cpp in Sources */, 9588365C0C6FABBA004B4162 /* VLDebugFlags.cpp in Sources */,
95D0597A0D1E6B0D00E28FAE /* VLLayout.cpp in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };