mirror of
https://github.com/microtherion/VocalEasel.git
synced 2024-12-23 03:34:00 +00:00
Added undo support
This commit is contained in:
parent
94f23e92f2
commit
9af760d1dc
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#import "VLModel.h"
|
#import "VLModel.h"
|
||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
|
#import "VLKeyValueUndo.h"
|
||||||
|
|
||||||
@class VLSheetWindow;
|
@class VLSheetWindow;
|
||||||
@class VLPDFWindow;
|
@class VLPDFWindow;
|
||||||
|
@ -29,6 +30,7 @@
|
||||||
VLSheetWindow * sheetWin;
|
VLSheetWindow * sheetWin;
|
||||||
VLLogWindow * logWin;
|
VLLogWindow * logWin;
|
||||||
VLPDFWindow * pdfWin;
|
VLPDFWindow * pdfWin;
|
||||||
|
VLKeyValueUndo* undo;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (VLSong *) song;
|
- (VLSong *) song;
|
||||||
|
@ -49,6 +51,8 @@
|
||||||
- (NSString *) baseName;
|
- (NSString *) baseName;
|
||||||
- (NSURL *) fileURLWithExtension:(NSString*)extension;
|
- (NSURL *) fileURLWithExtension:(NSString*)extension;
|
||||||
- (NSTask *) taskWithLaunchPath:(NSString *)path arguments:(NSArray *)args;
|
- (NSTask *) taskWithLaunchPath:(NSString *)path arguments:(NSArray *)args;
|
||||||
|
- (void) willChangeSong;
|
||||||
|
- (void) didChangeSong;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,43 @@
|
||||||
#import "VLSheetWindow.h"
|
#import "VLSheetWindow.h"
|
||||||
#import "VLSoundOut.h"
|
#import "VLSoundOut.h"
|
||||||
|
|
||||||
|
@interface VLSongWrapper : NSObject {
|
||||||
|
VLSong * wrappedSong;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (VLSongWrapper *)wrapperWithSong:(VLSong *)song;
|
||||||
|
- (VLSong *)song;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation VLSongWrapper
|
||||||
|
|
||||||
|
- (id)initWithSong:(VLSong *)song
|
||||||
|
{
|
||||||
|
if (self = [super init])
|
||||||
|
wrappedSong = new VLSong(*song);
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) dealloc
|
||||||
|
{
|
||||||
|
delete wrappedSong;
|
||||||
|
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (VLSongWrapper *)wrapperWithSong:(VLSong *)song
|
||||||
|
{
|
||||||
|
return [[[VLSongWrapper alloc] initWithSong:song] autorelease];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (VLSong *)song
|
||||||
|
{
|
||||||
|
return wrappedSong;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
@implementation VLDocument
|
@implementation VLDocument
|
||||||
|
|
||||||
- (id)init
|
- (id)init
|
||||||
|
@ -35,6 +72,17 @@
|
||||||
logWin = nil;
|
logWin = nil;
|
||||||
tmpPath = nil;
|
tmpPath = nil;
|
||||||
vcsWrapper = nil;
|
vcsWrapper = nil;
|
||||||
|
[self setHasUndoManager:YES];
|
||||||
|
undo =
|
||||||
|
[[VLKeyValueUndo alloc] initWithOwner:self
|
||||||
|
keysAndNames: [NSDictionary dictionaryWithObjectsAndKeys:
|
||||||
|
@"", @"songTitle",
|
||||||
|
@"", @"songLyricist",
|
||||||
|
@"", @"songComposer",
|
||||||
|
@"", @"songArranger",
|
||||||
|
@"", @"songGroove",
|
||||||
|
@"", @"songTempo",
|
||||||
|
nil]];
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
@ -49,6 +97,7 @@
|
||||||
[songComposer release];
|
[songComposer release];
|
||||||
[songArranger release];
|
[songArranger release];
|
||||||
[vcsWrapper release];
|
[vcsWrapper release];
|
||||||
|
[undo release];
|
||||||
|
|
||||||
if (tmpPath) {
|
if (tmpPath) {
|
||||||
[[NSFileManager defaultManager] removeFileAtPath:tmpPath handler:nil];
|
[[NSFileManager defaultManager] removeFileAtPath:tmpPath handler:nil];
|
||||||
|
@ -119,6 +168,8 @@
|
||||||
|
|
||||||
- (void) setKey:(int)key transpose:(BOOL)transpose
|
- (void) setKey:(int)key transpose:(BOOL)transpose
|
||||||
{
|
{
|
||||||
|
[self willChangeSong];
|
||||||
|
|
||||||
VLProperties & prop = song->fProperties.front();
|
VLProperties & prop = song->fProperties.front();
|
||||||
|
|
||||||
if (transpose)
|
if (transpose)
|
||||||
|
@ -139,6 +190,8 @@
|
||||||
|
|
||||||
- (void) setTimeNum:(int)num denom:(int)denom
|
- (void) setTimeNum:(int)num denom:(int)denom
|
||||||
{
|
{
|
||||||
|
[self willChangeSong];
|
||||||
|
|
||||||
VLProperties & prop = song->fProperties.front();
|
VLProperties & prop = song->fProperties.front();
|
||||||
|
|
||||||
prop.fTime = VLFraction(num, denom);
|
prop.fTime = VLFraction(num, denom);
|
||||||
|
@ -155,6 +208,8 @@
|
||||||
|
|
||||||
- (void) setDivisions:(int)divisions
|
- (void) setDivisions:(int)divisions
|
||||||
{
|
{
|
||||||
|
[self willChangeSong];
|
||||||
|
|
||||||
VLProperties & prop = song->fProperties.front();
|
VLProperties & prop = song->fProperties.front();
|
||||||
|
|
||||||
prop.fDivisions = divisions;
|
prop.fDivisions = divisions;
|
||||||
|
@ -328,4 +383,31 @@
|
||||||
[[self logWin] showWindow:sender];
|
[[self logWin] showWindow:sender];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) willChangeSong
|
||||||
|
{
|
||||||
|
[self willChangeValueForKey:@"song"];
|
||||||
|
[[self undoManager] registerUndoWithTarget:self
|
||||||
|
selector:@selector(restoreSong:)
|
||||||
|
object:[VLSongWrapper wrapperWithSong:song]];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) didChangeSong
|
||||||
|
{
|
||||||
|
[self didChangeValueForKey:@"song"];
|
||||||
|
[self updateChangeCount:NSChangeDone];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) restoreSong:(VLSongWrapper *)savedSong
|
||||||
|
{
|
||||||
|
[self willChangeSong];
|
||||||
|
[self willChangeValueForKey:@"songKey"];
|
||||||
|
[self willChangeValueForKey:@"songTime"];
|
||||||
|
[self willChangeValueForKey:@"songDivisions"];
|
||||||
|
song->swap(*[savedSong song]);
|
||||||
|
[self didChangeValueForKey:@"songKey"];
|
||||||
|
[self didChangeValueForKey:@"songTime"];
|
||||||
|
[self didChangeValueForKey:@"songDivisions"];
|
||||||
|
[self didChangeSong];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
18
Sources/VLKeyValueUndo.h
Normal file
18
Sources/VLKeyValueUndo.h
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
//
|
||||||
|
// VLKeyValueUndo.h
|
||||||
|
// Vocalese
|
||||||
|
//
|
||||||
|
// Created by Matthias Neeracher on 12/3/06.
|
||||||
|
// Copyright 2006 __MyCompanyName__. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
@interface VLKeyValueUndo : NSObject {
|
||||||
|
id owner;
|
||||||
|
NSDictionary * keysAndNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)initWithOwner:(id)owner keysAndNames:(NSDictionary *)keysAndNames;
|
||||||
|
|
||||||
|
@end
|
54
Sources/VLKeyValueUndo.mm
Normal file
54
Sources/VLKeyValueUndo.mm
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
//
|
||||||
|
// VLKeyValueUndo.mm
|
||||||
|
// Vocalese
|
||||||
|
//
|
||||||
|
// Created by Matthias Neeracher on 12/3/06.
|
||||||
|
// Copyright 2006 __MyCompanyName__. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "VLKeyValueUndo.h"
|
||||||
|
|
||||||
|
|
||||||
|
@implementation VLKeyValueUndo
|
||||||
|
|
||||||
|
- (id)initWithOwner:(id)o keysAndNames:(NSDictionary *)kn
|
||||||
|
{
|
||||||
|
owner = o;
|
||||||
|
keysAndNames = [kn retain];
|
||||||
|
|
||||||
|
for (NSEnumerator * e = [keysAndNames keyEnumerator];
|
||||||
|
NSString * key = [e nextObject];
|
||||||
|
)
|
||||||
|
[owner addObserver:self forKeyPath:key
|
||||||
|
options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew
|
||||||
|
context:[keysAndNames objectForKey:key]];
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) dealloc
|
||||||
|
{
|
||||||
|
for (NSEnumerator * e = [keysAndNames keyEnumerator];
|
||||||
|
NSString * key = [e nextObject];
|
||||||
|
)
|
||||||
|
[owner removeObserver:self forKeyPath:key];
|
||||||
|
|
||||||
|
[keysAndNames release];
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
|
||||||
|
{
|
||||||
|
id oldVal = [change objectForKey:NSKeyValueChangeOldKey];
|
||||||
|
id newVal = [change objectForKey:NSKeyValueChangeNewKey];
|
||||||
|
|
||||||
|
if (![oldVal isEqual:newVal]) {
|
||||||
|
NSUndoManager * undo = [owner undoManager];
|
||||||
|
NSString * name = [keysAndNames objectForKey:keyPath];
|
||||||
|
[undo registerUndoWithTarget:owner selector:@selector(setValuesForKeysWithDictionary:)
|
||||||
|
object: [NSDictionary dictionaryWithObjectsAndKeys: oldVal, keyPath, nil]];
|
||||||
|
[undo setActionName: name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
|
@ -32,9 +32,9 @@
|
||||||
for (size_t m=0; m<song->CountMeasures(); ++m) {
|
for (size_t m=0; m<song->CountMeasures(); ++m) {
|
||||||
sprintf(buf, "%-5d", m+1);
|
sprintf(buf, "%-5d", m+1);
|
||||||
mmaFile += buf;
|
mmaFile += buf;
|
||||||
song->fMeasures[m].MMAChords(mmas);
|
song->fMeasures[m].MMAChords(mmas, prop);
|
||||||
mmaFile += mmas;
|
mmaFile += mmas;
|
||||||
song->fMeasures[m].MMANotes(mmas);
|
song->fMeasures[m].MMANotes(mmas, prop);
|
||||||
mmaFile += "\t{ " + mmas + " }\n";
|
mmaFile += "\t{ " + mmas + " }\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -737,11 +737,11 @@ void VLProperties::VisualNote(VLFraction at, VLFraction actualDur,
|
||||||
}
|
}
|
||||||
|
|
||||||
VLMeasure::VLMeasure()
|
VLMeasure::VLMeasure()
|
||||||
: fProperties(0)
|
: fPropIdx(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void VLMeasure::MMANotes(std::string & notes) const
|
void VLMeasure::MMANotes(std::string & notes, const VLProperties & prop) const
|
||||||
{
|
{
|
||||||
VLFraction at(0);
|
VLFraction at(0);
|
||||||
VLNoteList::const_iterator i = fMelody.begin();
|
VLNoteList::const_iterator i = fMelody.begin();
|
||||||
|
@ -750,7 +750,7 @@ void VLMeasure::MMANotes(std::string & notes) const
|
||||||
notes.clear();
|
notes.clear();
|
||||||
for (; i!=e; ++i) {
|
for (; i!=e; ++i) {
|
||||||
std::string note;
|
std::string note;
|
||||||
i->MMAName(note, at, *fProperties);
|
i->MMAName(note, at, prop);
|
||||||
if (notes.size())
|
if (notes.size())
|
||||||
notes += ' ';
|
notes += ' ';
|
||||||
notes += note+';';
|
notes += note+';';
|
||||||
|
@ -758,7 +758,7 @@ void VLMeasure::MMANotes(std::string & notes) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VLMeasure::MMAChords(std::string & chords) const
|
void VLMeasure::MMAChords(std::string & chords, const VLProperties & prop) const
|
||||||
{
|
{
|
||||||
VLChordList::const_iterator i = fChords.begin();
|
VLChordList::const_iterator i = fChords.begin();
|
||||||
VLChordList::const_iterator e = fChords.end();
|
VLChordList::const_iterator e = fChords.end();
|
||||||
|
@ -766,7 +766,7 @@ void VLMeasure::MMAChords(std::string & chords) const
|
||||||
chords.clear();
|
chords.clear();
|
||||||
for (; i!=e; ++i) {
|
for (; i!=e; ++i) {
|
||||||
std::string chord;
|
std::string chord;
|
||||||
i->MMAName(chord, fProperties->fKey >= 0);
|
i->MMAName(chord, prop.fKey >= 0);
|
||||||
if (chords.size())
|
if (chords.size())
|
||||||
chords += ' ';
|
chords += ' ';
|
||||||
chords += chord;
|
chords += chord;
|
||||||
|
@ -786,12 +786,17 @@ VLSong::VLSong()
|
||||||
rchord.fDuration = 1;
|
rchord.fDuration = 1;
|
||||||
|
|
||||||
for (int i=0; i<32; ++i) {
|
for (int i=0; i<32; ++i) {
|
||||||
fMeasures[i].fProperties = &fProperties.front();
|
|
||||||
fMeasures[i].fChords.push_back(rchord);
|
fMeasures[i].fChords.push_back(rchord);
|
||||||
fMeasures[i].fMelody.push_back(rest);
|
fMeasures[i].fMelody.push_back(rest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VLSong::swap(VLSong & other)
|
||||||
|
{
|
||||||
|
fProperties.swap(other.fProperties);
|
||||||
|
fMeasures.swap(other.fMeasures);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Deal with chords - a bit simpler
|
// Deal with chords - a bit simpler
|
||||||
//
|
//
|
||||||
|
@ -1046,7 +1051,7 @@ void VLSong::LilypondNotes(std::string & notes) const
|
||||||
|
|
||||||
for (; i!=e; ++i) {
|
for (; i!=e; ++i) {
|
||||||
std::string note;
|
std::string note;
|
||||||
i->LilypondName(note, at, *fMeasures[measure].fProperties);
|
i->LilypondName(note, at, fProperties[fMeasures[measure].fPropIdx]);
|
||||||
at += i->fDuration;
|
at += i->fDuration;
|
||||||
notes += note+" ";
|
notes += note+" ";
|
||||||
}
|
}
|
||||||
|
@ -1065,7 +1070,7 @@ void VLSong::LilypondChords(std::string & chords) const
|
||||||
{
|
{
|
||||||
chords = "";
|
chords = "";
|
||||||
for (size_t measure=0; measure<fMeasures.size(); ++measure) {
|
for (size_t measure=0; measure<fMeasures.size(); ++measure) {
|
||||||
bool useSharps = fMeasures[measure].fProperties->fKey>=0;
|
bool useSharps = fProperties[fMeasures[measure].fPropIdx].fKey>=0;
|
||||||
VLChordList::const_iterator i = fMeasures[measure].fChords.begin();
|
VLChordList::const_iterator i = fMeasures[measure].fChords.begin();
|
||||||
VLChordList::const_iterator e = fMeasures[measure].fChords.end();
|
VLChordList::const_iterator e = fMeasures[measure].fChords.end();
|
||||||
|
|
||||||
|
@ -1145,7 +1150,7 @@ bool VLSong::PrevWord(size_t stanza, size_t & measure, VLFraction & at)
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
at = meas.fProperties->fTime;
|
at = fProperties[meas.fPropIdx].fTime;
|
||||||
}
|
}
|
||||||
} while (measure-- > 0);
|
} while (measure-- > 0);
|
||||||
|
|
||||||
|
|
|
@ -233,21 +233,22 @@ typedef std::list<VLChord> VLChordList;
|
||||||
typedef std::list<VLLyricsNote> VLNoteList;
|
typedef std::list<VLLyricsNote> VLNoteList;
|
||||||
|
|
||||||
struct VLMeasure {
|
struct VLMeasure {
|
||||||
VLProperties * fProperties;
|
int8_t fPropIdx;
|
||||||
VLChordList fChords;
|
VLChordList fChords;
|
||||||
VLNoteList fMelody;
|
VLNoteList fMelody;
|
||||||
|
|
||||||
VLMeasure();
|
VLMeasure();
|
||||||
|
|
||||||
void MMANotes(std::string & notes) const;
|
void MMANotes(std::string & notes, const VLProperties & prop) const;
|
||||||
void MMAChords(std::string & chords) const;
|
void MMAChords(std::string & chords, const VLProperties & prop) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VLSong {
|
struct VLSong {
|
||||||
VLSong();
|
VLSong();
|
||||||
|
void swap(VLSong & other);
|
||||||
|
|
||||||
std::list<VLProperties> fProperties;
|
std::vector<VLProperties> fProperties;
|
||||||
std::vector<VLMeasure> fMeasures;
|
std::vector<VLMeasure> fMeasures;
|
||||||
|
|
||||||
void AddChord(VLChord chord, size_t measure, VLFraction at);
|
void AddChord(VLChord chord, size_t measure, VLFraction at);
|
||||||
void AddNote(VLLyricsNote note, size_t measure, VLFraction at);
|
void AddNote(VLLyricsNote note, size_t measure, VLFraction at);
|
||||||
|
|
|
@ -740,4 +740,17 @@ static int8_t sSharpAcc[] = {
|
||||||
[self setScaleFactor: fDisplayScale / sqrt(sqrt(2.0))];
|
[self setScaleFactor: fDisplayScale / sqrt(sqrt(2.0))];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)awakeFromNib
|
||||||
|
{
|
||||||
|
[[self document] addObserver:self forKeyPath:@"song" options:0 context:nil];
|
||||||
|
[[self document] addObserver:self forKeyPath:@"songKey" options:0 context:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)o change:(NSDictionary *)c context:(id)ctx
|
||||||
|
{
|
||||||
|
if ([keyPath isEqual:@"songKey"])
|
||||||
|
fNeedsRecalc = kRecalc;
|
||||||
|
[self setNeedsDisplay: YES];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -121,10 +121,11 @@ std::string NormalizeName(NSString* rawName)
|
||||||
} else {
|
} else {
|
||||||
VLChord chord(chordName);
|
VLChord chord(chordName);
|
||||||
VLSoundOut::Instance()->PlayChord(chord);
|
VLSoundOut::Instance()->PlayChord(chord);
|
||||||
|
|
||||||
|
[[fView document] willChangeSong];
|
||||||
fSong->AddChord(chord, fMeasure, fAt);
|
fSong->AddChord(chord, fMeasure, fAt);
|
||||||
[fView setNeedsDisplay:YES];
|
[[fView document] didChangeSong];
|
||||||
}
|
}
|
||||||
[[fView document] updateChangeCount:NSChangeDone];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) validValue:(NSString *)val
|
- (BOOL) validValue:(NSString *)val
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
VLSong * fSong;
|
VLSong * fSong;
|
||||||
size_t fStanza;
|
size_t fStanza;
|
||||||
size_t fMeasure;
|
size_t fMeasure;
|
||||||
VLFraction fAt;
|
VLFract fAt;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (VLLyricsEditable *)initWithView:(VLSheetView *)view
|
- (VLLyricsEditable *)initWithView:(VLSheetView *)view
|
||||||
|
|
|
@ -28,7 +28,9 @@
|
||||||
fMeasure= measure;
|
fMeasure= measure;
|
||||||
fAt = at;
|
fAt = at;
|
||||||
|
|
||||||
fSong->FindWord(fStanza, fMeasure, fAt);
|
VLFraction At = fAt;
|
||||||
|
fSong->FindWord(fStanza, fMeasure, At);
|
||||||
|
fAt = At;
|
||||||
|
|
||||||
[fView setNeedsDisplay: YES];
|
[fView setNeedsDisplay: YES];
|
||||||
|
|
||||||
|
@ -43,7 +45,9 @@
|
||||||
|
|
||||||
- (void) setStringValue:(NSString *)val
|
- (void) setStringValue:(NSString *)val
|
||||||
{
|
{
|
||||||
|
[[fView document] willChangeSong];
|
||||||
fSong->SetWord(fStanza, fMeasure, fAt, [val UTF8String]);
|
fSong->SetWord(fStanza, fMeasure, fAt, [val UTF8String]);
|
||||||
|
[[fView document] didChangeSong];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) validValue:(NSString *)val
|
- (BOOL) validValue:(NSString *)val
|
||||||
|
@ -53,20 +57,24 @@
|
||||||
|
|
||||||
- (void) moveToNext
|
- (void) moveToNext
|
||||||
{
|
{
|
||||||
if (!fSong->NextWord(fStanza, fMeasure, fAt)) {
|
VLFraction at = fAt;
|
||||||
|
if (!fSong->NextWord(fStanza, fMeasure, at)) {
|
||||||
fMeasure = 0;
|
fMeasure = 0;
|
||||||
fAt = 0;
|
at = 0;
|
||||||
fSong->FindWord(fStanza, fMeasure, fAt);
|
fSong->FindWord(fStanza, fMeasure, at);
|
||||||
}
|
}
|
||||||
|
fAt = at;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) moveToPrev
|
- (void) moveToPrev
|
||||||
{
|
{
|
||||||
if (!fSong->PrevWord(fStanza, fMeasure, fAt)) {
|
VLFraction at = fAt;
|
||||||
|
if (!fSong->PrevWord(fStanza, fMeasure, at)) {
|
||||||
fMeasure = fSong->CountMeasures()-1;
|
fMeasure = fSong->CountMeasures()-1;
|
||||||
fAt = fSong->fMeasures[fMeasure].fProperties->fTime;
|
at = fSong->fProperties.front().fTime;
|
||||||
fSong->PrevWord(fStanza, fMeasure, fAt);
|
fSong->PrevWord(fStanza, fMeasure, at);
|
||||||
}
|
}
|
||||||
|
fAt = at;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) highlightCursor
|
- (void) highlightCursor
|
||||||
|
|
|
@ -20,13 +20,12 @@
|
||||||
if (fCursorMeasure > -1) {
|
if (fCursorMeasure > -1) {
|
||||||
VLNote newNote(1, fClickMode==' ' ? fCursorActualPitch : VLNote::kNoPitch);
|
VLNote newNote(1, fClickMode==' ' ? fCursorActualPitch : VLNote::kNoPitch);
|
||||||
|
|
||||||
|
[[self document] willChangeSong];
|
||||||
if (fClickMode == 'k')
|
if (fClickMode == 'k')
|
||||||
[self song]->DelNote(fCursorMeasure, fCursorAt);
|
[self song]->DelNote(fCursorMeasure, fCursorAt);
|
||||||
else
|
else
|
||||||
[self song]->AddNote(VLLyricsNote(newNote), fCursorMeasure, fCursorAt);
|
[self song]->AddNote(VLLyricsNote(newNote), fCursorMeasure, fCursorAt);
|
||||||
|
[[self document] didChangeSong];
|
||||||
[self setNeedsDisplay:YES];
|
|
||||||
[[self document] updateChangeCount:NSChangeDone];
|
|
||||||
|
|
||||||
if (fClickMode == ' ')
|
if (fClickMode == ' ')
|
||||||
VLSoundOut::Instance()->PlayNote(newNote);
|
VLSoundOut::Instance()->PlayNote(newNote);
|
||||||
|
@ -269,8 +268,8 @@
|
||||||
VLFraction partialDur; // Actual value of note drawn
|
VLFraction partialDur; // Actual value of note drawn
|
||||||
VLFraction noteDur; // Visual value of note
|
VLFraction noteDur; // Visual value of note
|
||||||
bool triplet;
|
bool triplet;
|
||||||
measure.fProperties->PartialNote(at, dur, &partialDur);
|
prop.PartialNote(at, dur, &partialDur);
|
||||||
measure.fProperties->VisualNote(at, partialDur, ¬eDur, &triplet);
|
prop.VisualNote(at, partialDur, ¬eDur, &triplet);
|
||||||
|
|
||||||
if (pitch != VLNote::kNoPitch) {
|
if (pitch != VLNote::kNoPitch) {
|
||||||
VLMusicElement accidental;
|
VLMusicElement accidental;
|
||||||
|
|
|
@ -40,6 +40,8 @@
|
||||||
95498DBD0AE3812F006B5F81 /* VLSoundSched.mm in Sources */ = {isa = PBXBuildFile; fileRef = 95498DBC0AE3812F006B5F81 /* VLSoundSched.mm */; };
|
95498DBD0AE3812F006B5F81 /* VLSoundSched.mm in Sources */ = {isa = PBXBuildFile; fileRef = 95498DBC0AE3812F006B5F81 /* VLSoundSched.mm */; };
|
||||||
954BBD860AEDDE5300BBFD5F /* VLAppController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 954BBD850AEDDE5300BBFD5F /* VLAppController.mm */; };
|
954BBD860AEDDE5300BBFD5F /* VLAppController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 954BBD850AEDDE5300BBFD5F /* VLAppController.mm */; };
|
||||||
954BBD9A0AEDE81500BBFD5F /* VLPitchTransformer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 954BBD990AEDE81500BBFD5F /* VLPitchTransformer.mm */; };
|
954BBD9A0AEDE81500BBFD5F /* VLPitchTransformer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 954BBD990AEDE81500BBFD5F /* VLPitchTransformer.mm */; };
|
||||||
|
955CBA4E0B2366DD001CF4A1 /* VLKeyValueUndo.h in Copy MMA Library */ = {isa = PBXBuildFile; fileRef = 955CBA4C0B2366DD001CF4A1 /* VLKeyValueUndo.h */; };
|
||||||
|
955CBA4F0B2366DD001CF4A1 /* VLKeyValueUndo.mm in Sources */ = {isa = PBXBuildFile; fileRef = 955CBA4D0B2366DD001CF4A1 /* VLKeyValueUndo.mm */; };
|
||||||
955E58E5095658AB0045FDA5 /* VLModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 955E58E4095658AB0045FDA5 /* VLModel.cpp */; };
|
955E58E5095658AB0045FDA5 /* VLModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 955E58E4095658AB0045FDA5 /* VLModel.cpp */; };
|
||||||
955E59610957C1400045FDA5 /* TVLChord.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 955E59600957C1400045FDA5 /* TVLChord.cpp */; };
|
955E59610957C1400045FDA5 /* TVLChord.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 955E59600957C1400045FDA5 /* TVLChord.cpp */; };
|
||||||
955E59640957C15A0045FDA5 /* VLModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 955E58E4095658AB0045FDA5 /* VLModel.cpp */; };
|
955E59640957C15A0045FDA5 /* VLModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 955E58E4095658AB0045FDA5 /* VLModel.cpp */; };
|
||||||
|
@ -106,6 +108,7 @@
|
||||||
95009B640B0ED18700EB33A4 /* CAConditionalMacros.h in Copy MMA Library */,
|
95009B640B0ED18700EB33A4 /* CAConditionalMacros.h in Copy MMA Library */,
|
||||||
95009B650B0ED18700EB33A4 /* CAMath.h in Copy MMA Library */,
|
95009B650B0ED18700EB33A4 /* CAMath.h in Copy MMA Library */,
|
||||||
95E299BF0B2006F5001977D2 /* VLSheetViewLyrics.h in Copy MMA Library */,
|
95E299BF0B2006F5001977D2 /* VLSheetViewLyrics.h in Copy MMA Library */,
|
||||||
|
955CBA4E0B2366DD001CF4A1 /* VLKeyValueUndo.h in Copy MMA Library */,
|
||||||
);
|
);
|
||||||
name = "Copy MMA Library";
|
name = "Copy MMA Library";
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
@ -167,6 +170,8 @@
|
||||||
954BBD850AEDDE5300BBFD5F /* VLAppController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = VLAppController.mm; path = Sources/VLAppController.mm; sourceTree = "<group>"; };
|
954BBD850AEDDE5300BBFD5F /* VLAppController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = VLAppController.mm; path = Sources/VLAppController.mm; sourceTree = "<group>"; };
|
||||||
954BBD980AEDE81500BBFD5F /* VLPitchTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLPitchTransformer.h; path = Sources/VLPitchTransformer.h; sourceTree = "<group>"; };
|
954BBD980AEDE81500BBFD5F /* VLPitchTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLPitchTransformer.h; path = Sources/VLPitchTransformer.h; sourceTree = "<group>"; };
|
||||||
954BBD990AEDE81500BBFD5F /* VLPitchTransformer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = VLPitchTransformer.mm; path = Sources/VLPitchTransformer.mm; sourceTree = "<group>"; };
|
954BBD990AEDE81500BBFD5F /* VLPitchTransformer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = VLPitchTransformer.mm; path = Sources/VLPitchTransformer.mm; sourceTree = "<group>"; };
|
||||||
|
955CBA4C0B2366DD001CF4A1 /* VLKeyValueUndo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLKeyValueUndo.h; path = Sources/VLKeyValueUndo.h; sourceTree = "<group>"; };
|
||||||
|
955CBA4D0B2366DD001CF4A1 /* VLKeyValueUndo.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = VLKeyValueUndo.mm; path = Sources/VLKeyValueUndo.mm; sourceTree = "<group>"; };
|
||||||
955E58E3095658AB0045FDA5 /* VLModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLModel.h; path = Sources/VLModel.h; sourceTree = "<group>"; };
|
955E58E3095658AB0045FDA5 /* VLModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VLModel.h; path = Sources/VLModel.h; sourceTree = "<group>"; };
|
||||||
955E58E4095658AB0045FDA5 /* VLModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VLModel.cpp; path = Sources/VLModel.cpp; sourceTree = "<group>"; };
|
955E58E4095658AB0045FDA5 /* VLModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VLModel.cpp; path = Sources/VLModel.cpp; sourceTree = "<group>"; };
|
||||||
955E595C0957C0FC0045FDA5 /* TVLChord */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = TVLChord; sourceTree = BUILT_PRODUCTS_DIR; };
|
955E595C0957C0FC0045FDA5 /* TVLChord */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = TVLChord; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
@ -356,6 +361,8 @@
|
||||||
954BBD850AEDDE5300BBFD5F /* VLAppController.mm */,
|
954BBD850AEDDE5300BBFD5F /* VLAppController.mm */,
|
||||||
954BBD980AEDE81500BBFD5F /* VLPitchTransformer.h */,
|
954BBD980AEDE81500BBFD5F /* VLPitchTransformer.h */,
|
||||||
954BBD990AEDE81500BBFD5F /* VLPitchTransformer.mm */,
|
954BBD990AEDE81500BBFD5F /* VLPitchTransformer.mm */,
|
||||||
|
955CBA4C0B2366DD001CF4A1 /* VLKeyValueUndo.h */,
|
||||||
|
955CBA4D0B2366DD001CF4A1 /* VLKeyValueUndo.mm */,
|
||||||
);
|
);
|
||||||
name = Classes;
|
name = Classes;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -634,6 +641,7 @@
|
||||||
95009B2C0B0ECF9000EB33A4 /* CAStreamBasicDescription.cpp in Sources */,
|
95009B2C0B0ECF9000EB33A4 /* CAStreamBasicDescription.cpp in Sources */,
|
||||||
95009B500B0ED0BB00EB33A4 /* CADebugMacros.cpp in Sources */,
|
95009B500B0ED0BB00EB33A4 /* CADebugMacros.cpp in Sources */,
|
||||||
95E299C00B2006F5001977D2 /* VLSheetViewLyrics.mm in Sources */,
|
95E299C00B2006F5001977D2 /* VLSheetViewLyrics.mm in Sources */,
|
||||||
|
955CBA4F0B2366DD001CF4A1 /* VLKeyValueUndo.mm in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user