mirror of
https://github.com/microtherion/VocalEasel.git
synced 2024-12-22 19:23:59 +00:00
Implement measure selection
This commit is contained in:
parent
9af760d1dc
commit
52c8f61efd
|
@ -43,7 +43,8 @@ enum VLRegion {
|
|||
kRegionNowhere,
|
||||
kRegionNote,
|
||||
kRegionChord,
|
||||
kRegionLyrics
|
||||
kRegionLyrics,
|
||||
kRegionMeasure
|
||||
};
|
||||
|
||||
enum VLRecalc {
|
||||
|
@ -75,6 +76,8 @@ enum VLRecalc {
|
|||
int fCursorActualPitch;
|
||||
VLMusicElement fCursorAccidental;
|
||||
size_t fCursorStanza;
|
||||
int fSelStart;
|
||||
int fSelEnd;
|
||||
|
||||
IBOutlet id fFieldEditor;
|
||||
}
|
||||
|
|
|
@ -85,6 +85,8 @@ static float sFlatPos[] = {
|
|||
fClickMode = ' ';
|
||||
fDisplayScale = 1.0f;
|
||||
fCursorPitch = VLNote::kNoPitch;
|
||||
fSelStart = 0;
|
||||
fSelEnd = -1;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
@ -382,6 +384,25 @@ VLMusicElement sSemi2Accidental[12][12] = {
|
|||
}
|
||||
}
|
||||
|
||||
- (void)highlightSelectionForSystem:(int)system
|
||||
{
|
||||
int startMeas = std::max(fSelStart-system*fMeasPerSystem, 0);
|
||||
int endMeas = std::min(fSelEnd-system*fMeasPerSystem, fMeasPerSystem);
|
||||
const float kRawSystemY = [self systemY:system]-kSystemY;
|
||||
|
||||
[NSGraphicsContext saveGraphicsState];
|
||||
[[NSColor selectedTextBackgroundColor] setFill];
|
||||
if (fSelStart == fSelEnd)
|
||||
[NSBezierPath fillRect:
|
||||
NSMakeRect(fClefKeyW+startMeas*fMeasureW-kMeasTol, kRawSystemY,
|
||||
2.0f*kMeasTol, kSystemH)];
|
||||
else
|
||||
[NSBezierPath fillRect:
|
||||
NSMakeRect(fClefKeyW+startMeas*fMeasureW, kRawSystemY,
|
||||
(endMeas-startMeas)*fMeasureW, kSystemH)];
|
||||
[NSGraphicsContext restoreGraphicsState];
|
||||
}
|
||||
|
||||
- (void)drawRect:(NSRect)rect
|
||||
{
|
||||
if (fNeedsRecalc)
|
||||
|
@ -396,6 +417,15 @@ VLMusicElement sSemi2Accidental[12][12] = {
|
|||
kLineW, kSystemH-kClefY)
|
||||
))
|
||||
continue; // This system does not need to be drawn
|
||||
//
|
||||
// When highlighting, draw highlight FIRST and then draw our stuff
|
||||
// on top.
|
||||
//
|
||||
if (fSelStart <= fSelEnd
|
||||
&& (system+1)*fMeasPerSystem > fSelStart
|
||||
&& system*fMeasPerSystem < fSelEnd+(fSelStart==fSelEnd)
|
||||
)
|
||||
[self highlightSelectionForSystem:system];
|
||||
[self drawGridForSystem:system];
|
||||
[self drawNotesForSystem:system];
|
||||
[self drawChordsForSystem:system];
|
||||
|
@ -573,6 +603,21 @@ static int8_t sSharpAcc[] = {
|
|||
loc.y = fmodf(loc.y, kSystemH);
|
||||
|
||||
loc.x -= fClefKeyW;
|
||||
if (loc.y > kSystemY && loc.y < kSystemY+4.0f*kLineH
|
||||
&& fmodf(loc.x+kMeasTol, fMeasureW) < 2*kMeasTol
|
||||
) {
|
||||
int measure = static_cast<int>((loc.x+kMeasTol)/fMeasureW);
|
||||
|
||||
if (measure < 0 || measure > fMeasPerSystem)
|
||||
return fCursorRegion = kRegionNowhere;
|
||||
|
||||
fCursorMeasure = measure+system*fMeasPerSystem;
|
||||
|
||||
if (fCursorMeasure > [self song]->fMeasures.size())
|
||||
return fCursorRegion = kRegionNowhere;
|
||||
else
|
||||
return fCursorRegion = kRegionMeasure;
|
||||
}
|
||||
if (loc.x < 0.0f || loc.x >= fMeasPerSystem*fMeasureW)
|
||||
return fCursorRegion = kRegionNowhere;
|
||||
|
||||
|
@ -644,6 +689,7 @@ static int8_t sSharpAcc[] = {
|
|||
|
||||
- (void) mouseDown:(NSEvent *)event
|
||||
{
|
||||
fSelEnd = -1;
|
||||
switch ([self findRegionForEvent:event]) {
|
||||
case kRegionNote:
|
||||
[self addNoteAtCursor];
|
||||
|
@ -653,11 +699,53 @@ static int8_t sSharpAcc[] = {
|
|||
break;
|
||||
case kRegionLyrics:
|
||||
[self editLyrics];
|
||||
break;
|
||||
case kRegionMeasure:
|
||||
fSelStart = fSelEnd = fCursorMeasure;
|
||||
[self setNeedsDisplay:YES];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) mouseDragged:(NSEvent *)event
|
||||
{
|
||||
if (fCursorRegion != kRegionMeasure)
|
||||
[super mouseDragged:event];
|
||||
[self autoscroll:event];
|
||||
int prevMeasure = fCursorMeasure;
|
||||
switch ([self findRegionForEvent:event]) {
|
||||
case kRegionNote:
|
||||
case kRegionChord:
|
||||
case kRegionLyrics:
|
||||
if (fCursorAt.fNum)
|
||||
++fCursorMeasure;
|
||||
//
|
||||
// Fall through
|
||||
//
|
||||
case kRegionMeasure:
|
||||
if (fCursorMeasure > fSelEnd) {
|
||||
fSelEnd = fCursorMeasure;
|
||||
[self setNeedsDisplay:YES];
|
||||
} else if (fCursorMeasure < fSelStart) {
|
||||
fSelStart = fCursorMeasure;
|
||||
[self setNeedsDisplay:YES];
|
||||
} else if (prevMeasure == fSelEnd && fCursorMeasure<prevMeasure) {
|
||||
fSelEnd = fCursorMeasure;
|
||||
[self setNeedsDisplay:YES];
|
||||
} else if (prevMeasure == fSelStart && fCursorMeasure>prevMeasure) {
|
||||
fSelStart = fCursorMeasure;
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fCursorMeasure = prevMeasure;
|
||||
break;
|
||||
}
|
||||
fCursorRegion = kRegionMeasure;
|
||||
}
|
||||
|
||||
- (void) keyDown:(NSEvent *)event
|
||||
{
|
||||
NSString * k = [event charactersIgnoringModifiers];
|
||||
|
|
|
@ -13,6 +13,7 @@ const float kSystemY = 5.0f*kLineH;
|
|||
const float kClefX = 20.5f;
|
||||
const float kClefY =-15.0f;
|
||||
const float kClefW = 30.0f;
|
||||
const float kMeasTol = 3.5f;
|
||||
const float kMeasNoX = 10.0f;
|
||||
const float kMeasNoY = 4.5f*kLineH;
|
||||
const float kNoteW = 12.0f;
|
||||
|
|
Loading…
Reference in New Issue
Block a user