Added undo support

This commit is contained in:
Matthias Neeracher 2006-12-04 07:04:24 +00:00
parent 94f23e92f2
commit 9af760d1dc
13 changed files with 227 additions and 34 deletions

View File

@ -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

View File

@ -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
View 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
View 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

View File

@ -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";
} }

View File

@ -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);

View File

@ -233,20 +233,21 @@ 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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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, &noteDur, &triplet); prop.VisualNote(at, partialDur, &noteDur, &triplet);
if (pitch != VLNote::kNoPitch) { if (pitch != VLNote::kNoPitch) {
VLMusicElement accidental; VLMusicElement accidental;

View File

@ -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;
}; };