mirror of
https://github.com/microtherion/VocalEasel.git
synced 2024-12-22 19:23:59 +00:00
Show mixed property state in menus
This commit is contained in:
parent
b92c94ce7e
commit
5423e65457
2658
English.lproj/VLDocument.nib/designable.nib
generated
2658
English.lproj/VLDocument.nib/designable.nib
generated
File diff suppressed because it is too large
Load Diff
BIN
English.lproj/VLDocument.nib/keyedobjects.nib
generated
BIN
English.lproj/VLDocument.nib/keyedobjects.nib
generated
Binary file not shown.
|
@ -91,6 +91,9 @@ enum VLRecalc {
|
|||
IBOutlet id fRepeatMsg;
|
||||
IBOutlet id fEndingMsg;
|
||||
IBOutlet id fGrooveMenu;
|
||||
IBOutlet id fKeyMenu;
|
||||
IBOutlet id fTimeMenu;
|
||||
IBOutlet id fDivisionMenu;
|
||||
}
|
||||
|
||||
- (IBAction) setKey:(id)sender;
|
||||
|
|
|
@ -983,6 +983,8 @@ static int8_t sSharpAcc[] = {
|
|||
[doc addObserver:self];
|
||||
[doc addObserver:self forKeyPath:@"song" 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];
|
||||
[self setGrooveMenu:[doc valueForKey:@"songGroove"]];
|
||||
|
||||
|
@ -990,12 +992,16 @@ static int8_t sSharpAcc[] = {
|
|||
fNumTopLedgers = std::max<int>(song->CountTopLedgers(), 1);
|
||||
fNumBotLedgers = std::max<int>(song->CountBotLedgers(), 1);
|
||||
fNumStanzas = std::max<int>(song->CountStanzas(), 2);
|
||||
|
||||
[self updateMenus];
|
||||
}
|
||||
|
||||
- (void)removeObservers:(id)target
|
||||
{
|
||||
[target removeObserver:self forKeyPath:@"song"];
|
||||
[target removeObserver:self forKeyPath:@"songKey"];
|
||||
[target removeObserver:self forKeyPath:@"songTime"];
|
||||
[target removeObserver:self forKeyPath:@"songDivisions"];
|
||||
[target removeObserver:self forKeyPath:@"songGroove"];
|
||||
}
|
||||
|
||||
|
@ -1004,8 +1010,13 @@ static int8_t sSharpAcc[] = {
|
|||
if ([keyPath isEqual:@"songKey"]) {
|
||||
fNeedsRecalc = kRecalc;
|
||||
[self setNeedsDisplay: YES];
|
||||
[self updateKeyMenu];
|
||||
} else if ([keyPath isEqual:@"song"]) {
|
||||
[self setNeedsDisplay: YES];
|
||||
} else if ([keyPath isEqual:@"songTime"]) {
|
||||
[self updateTimeMenu];
|
||||
} else if ([keyPath isEqual:@"songDivisions"]) {
|
||||
[self updateDivisionMenu];
|
||||
} else if ([keyPath isEqual:@"songGroove"]) {
|
||||
[self setGrooveMenu:[[self document] valueForKey:@"songGroove"]];
|
||||
}
|
||||
|
|
|
@ -26,6 +26,11 @@
|
|||
- (IBAction)insertJumpToCoda:(id)sender;
|
||||
- (IBAction)insertBreak:(id)sender;
|
||||
|
||||
- (void)updateKeyMenu;
|
||||
- (void)updateTimeMenu;
|
||||
- (void)updateDivisionMenu;
|
||||
- (void)updateMenus;
|
||||
|
||||
@end
|
||||
|
||||
// Local Variables:
|
||||
|
|
|
@ -12,6 +12,19 @@
|
|||
#import "VLSheetViewSelection.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.
|
||||
//
|
||||
|
@ -22,6 +35,7 @@ static VLSong sPasteboard;
|
|||
- (void)editSelection
|
||||
{
|
||||
fSelStart = fSelEnd = fCursorMeasure;
|
||||
[self updateMenus];
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
|
||||
|
@ -42,15 +56,19 @@ static VLSong sPasteboard;
|
|||
std::max(0, std::min<int>(fCursorMeasure, [self song]->CountMeasures()));
|
||||
if (fCursorMeasure > fSelEnd) {
|
||||
fSelEnd = fCursorMeasure;
|
||||
[self updateMenus];
|
||||
[self setNeedsDisplay:YES];
|
||||
} else if (fCursorMeasure < fSelStart) {
|
||||
fSelStart = fCursorMeasure;
|
||||
[self updateMenus];
|
||||
[self setNeedsDisplay:YES];
|
||||
} else if (prevMeasure == fSelEnd && fCursorMeasure<prevMeasure) {
|
||||
fSelEnd = fCursorMeasure;
|
||||
[self updateMenus];
|
||||
[self setNeedsDisplay:YES];
|
||||
} else if (prevMeasure == fSelStart && fCursorMeasure>prevMeasure) {
|
||||
fSelStart = fCursorMeasure;
|
||||
[self updateMenus];
|
||||
[self setNeedsDisplay:YES];
|
||||
}
|
||||
break;
|
||||
|
@ -317,4 +335,82 @@ static VLSong sPasteboard;
|
|||
[[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
|
||||
|
|
Loading…
Reference in New Issue
Block a user