Show mixed property state in menus

This commit is contained in:
Matthias Neeracher 2008-01-16 13:04:01 +00:00
parent b92c94ce7e
commit 5423e65457
6 changed files with 1430 additions and 1343 deletions

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -91,6 +91,9 @@ enum VLRecalc {
IBOutlet id fRepeatMsg; IBOutlet id fRepeatMsg;
IBOutlet id fEndingMsg; IBOutlet id fEndingMsg;
IBOutlet id fGrooveMenu; IBOutlet id fGrooveMenu;
IBOutlet id fKeyMenu;
IBOutlet id fTimeMenu;
IBOutlet id fDivisionMenu;
} }
- (IBAction) setKey:(id)sender; - (IBAction) setKey:(id)sender;

View File

@ -983,6 +983,8 @@ static int8_t sSharpAcc[] = {
[doc addObserver:self]; [doc addObserver:self];
[doc addObserver:self forKeyPath:@"song" options:0 context:nil]; [doc addObserver:self forKeyPath:@"song" options:0 context:nil];
[doc addObserver:self forKeyPath:@"songKey" options:0 context:nil]; [doc addObserver:self forKeyPath:@"songKey" options:0 context:nil];
[doc addObserver:self forKeyPath:@"songTime" options:0 context:nil];
[doc addObserver:self forKeyPath:@"songDivisions" options:0 context:nil];
[doc addObserver:self forKeyPath:@"songGroove" options:0 context:nil]; [doc addObserver:self forKeyPath:@"songGroove" options:0 context:nil];
[self setGrooveMenu:[doc valueForKey:@"songGroove"]]; [self setGrooveMenu:[doc valueForKey:@"songGroove"]];
@ -990,12 +992,16 @@ static int8_t sSharpAcc[] = {
fNumTopLedgers = std::max<int>(song->CountTopLedgers(), 1); fNumTopLedgers = std::max<int>(song->CountTopLedgers(), 1);
fNumBotLedgers = std::max<int>(song->CountBotLedgers(), 1); fNumBotLedgers = std::max<int>(song->CountBotLedgers(), 1);
fNumStanzas = std::max<int>(song->CountStanzas(), 2); fNumStanzas = std::max<int>(song->CountStanzas(), 2);
[self updateMenus];
} }
- (void)removeObservers:(id)target - (void)removeObservers:(id)target
{ {
[target removeObserver:self forKeyPath:@"song"]; [target removeObserver:self forKeyPath:@"song"];
[target removeObserver:self forKeyPath:@"songKey"]; [target removeObserver:self forKeyPath:@"songKey"];
[target removeObserver:self forKeyPath:@"songTime"];
[target removeObserver:self forKeyPath:@"songDivisions"];
[target removeObserver:self forKeyPath:@"songGroove"]; [target removeObserver:self forKeyPath:@"songGroove"];
} }
@ -1004,8 +1010,13 @@ static int8_t sSharpAcc[] = {
if ([keyPath isEqual:@"songKey"]) { if ([keyPath isEqual:@"songKey"]) {
fNeedsRecalc = kRecalc; fNeedsRecalc = kRecalc;
[self setNeedsDisplay: YES]; [self setNeedsDisplay: YES];
[self updateKeyMenu];
} else if ([keyPath isEqual:@"song"]) { } else if ([keyPath isEqual:@"song"]) {
[self setNeedsDisplay: YES]; [self setNeedsDisplay: YES];
} else if ([keyPath isEqual:@"songTime"]) {
[self updateTimeMenu];
} else if ([keyPath isEqual:@"songDivisions"]) {
[self updateDivisionMenu];
} else if ([keyPath isEqual:@"songGroove"]) { } else if ([keyPath isEqual:@"songGroove"]) {
[self setGrooveMenu:[[self document] valueForKey:@"songGroove"]]; [self setGrooveMenu:[[self document] valueForKey:@"songGroove"]];
} }

View File

@ -26,6 +26,11 @@
- (IBAction)insertJumpToCoda:(id)sender; - (IBAction)insertJumpToCoda:(id)sender;
- (IBAction)insertBreak:(id)sender; - (IBAction)insertBreak:(id)sender;
- (void)updateKeyMenu;
- (void)updateTimeMenu;
- (void)updateDivisionMenu;
- (void)updateMenus;
@end @end
// Local Variables: // Local Variables:

View File

@ -12,6 +12,19 @@
#import "VLSheetViewSelection.h" #import "VLSheetViewSelection.h"
#import "VLDocument.h" #import "VLDocument.h"
@interface NSMenuItem (VLSetStateToOff)
- (void) VLSetStateToOff;
@end
@implementation NSMenuItem (VLSetStateToOff)
- (void) VLSetStateToOff
{
[self setState:NSOffState];
}
@end
// //
// We're too lazy to properly serialize our private pasteboard format. // We're too lazy to properly serialize our private pasteboard format.
// //
@ -22,6 +35,7 @@ static VLSong sPasteboard;
- (void)editSelection - (void)editSelection
{ {
fSelStart = fSelEnd = fCursorMeasure; fSelStart = fSelEnd = fCursorMeasure;
[self updateMenus];
[self setNeedsDisplay:YES]; [self setNeedsDisplay:YES];
} }
@ -42,15 +56,19 @@ static VLSong sPasteboard;
std::max(0, std::min<int>(fCursorMeasure, [self song]->CountMeasures())); std::max(0, std::min<int>(fCursorMeasure, [self song]->CountMeasures()));
if (fCursorMeasure > fSelEnd) { if (fCursorMeasure > fSelEnd) {
fSelEnd = fCursorMeasure; fSelEnd = fCursorMeasure;
[self updateMenus];
[self setNeedsDisplay:YES]; [self setNeedsDisplay:YES];
} else if (fCursorMeasure < fSelStart) { } else if (fCursorMeasure < fSelStart) {
fSelStart = fCursorMeasure; fSelStart = fCursorMeasure;
[self updateMenus];
[self setNeedsDisplay:YES]; [self setNeedsDisplay:YES];
} else if (prevMeasure == fSelEnd && fCursorMeasure<prevMeasure) { } else if (prevMeasure == fSelEnd && fCursorMeasure<prevMeasure) {
fSelEnd = fCursorMeasure; fSelEnd = fCursorMeasure;
[self updateMenus];
[self setNeedsDisplay:YES]; [self setNeedsDisplay:YES];
} else if (prevMeasure == fSelStart && fCursorMeasure>prevMeasure) { } else if (prevMeasure == fSelStart && fCursorMeasure>prevMeasure) {
fSelStart = fCursorMeasure; fSelStart = fCursorMeasure;
[self updateMenus];
[self setNeedsDisplay:YES]; [self setNeedsDisplay:YES];
} }
break; break;
@ -317,4 +335,82 @@ static VLSong sPasteboard;
[[self document] didChangeSong]; [[self document] didChangeSong];
} }
inline int KeyModeTag(const VLProperties & prop)
{
return (prop.fKey << 8) | (prop.fMode & 0xFF);
}
- (void)updateKeyMenu
{
NSMenu *menu = [fKeyMenu menu];
NSRange sections = [self sectionsInSelection];
VLSong *song = [self song];
[[menu itemArray] makeObjectsPerformSelector:@selector(VLSetStateToOff)];
int firstTag = KeyModeTag(song->fProperties[sections.location]);
[fKeyMenu selectItemWithTag:firstTag];
int firstState = NSOnState;
while (--sections.length > 0) {
int thisTag = KeyModeTag(song->fProperties[++sections.location]);
if (thisTag != firstTag) {
firstState = NSMixedState;
[[menu itemWithTag:thisTag] setState:NSMixedState];
}
}
[[menu itemWithTag:firstTag] setState:firstState];
}
inline int TimeTag(const VLProperties & prop)
{
return (prop.fTime.fNum << 8) | prop.fTime.fDenom;
}
- (void)updateTimeMenu
{
NSMenu *menu = [fTimeMenu menu];
NSRange sections = [self sectionsInSelection];
VLSong *song = [self song];
[[menu itemArray] makeObjectsPerformSelector:@selector(VLSetStateToOff)];
int firstTag = TimeTag(song->fProperties[sections.location]);
[fTimeMenu selectItemWithTag:firstTag];
int firstState = NSOnState;
while (--sections.length > 0) {
int thisTag = TimeTag(song->fProperties[++sections.location]);
if (thisTag != firstTag) {
firstState = NSMixedState;
[[menu itemWithTag:thisTag] setState:NSMixedState];
}
}
[[menu itemWithTag:firstTag] setState:firstState];
}
- (void)updateDivisionMenu
{
NSMenu *menu = [fDivisionMenu menu];
NSRange sections = [self sectionsInSelection];
VLSong *song = [self song];
[[menu itemArray] makeObjectsPerformSelector:@selector(VLSetStateToOff)];
int firstTag = song->fProperties[sections.location].fDivisions;
[fDivisionMenu selectItemWithTag:firstTag];
int firstState = NSOnState;
while (--sections.length > 0) {
int thisTag = song->fProperties[++sections.location].fDivisions;
if (thisTag != firstTag) {
firstState = NSMixedState;
[[menu itemWithTag:thisTag] setState:NSMixedState];
}
}
[[menu itemWithTag:firstTag] setState:firstState];
}
- (void)updateMenus
{
[self updateKeyMenu];
[self updateTimeMenu];
[self updateDivisionMenu];
}
@end @end