From afe4f8078d852e1819256c791a46967520a7ea3d Mon Sep 17 00:00:00 2001 From: Matthias Neeracher Date: Sat, 2 Dec 2006 09:02:44 +0000 Subject: [PATCH] Edit lyrics --- Sources/VLModel.cpp | 91 ++++++++++++++++++++++++++++++++---- Sources/VLModel.h | 2 + Sources/VLSheetView.h | 1 + Sources/VLSheetView.mm | 3 ++ Sources/VLSheetViewLyrics.h | 12 +++-- Sources/VLSheetViewLyrics.mm | 31 ++++++++---- 6 files changed, 115 insertions(+), 25 deletions(-) diff --git a/Sources/VLModel.cpp b/Sources/VLModel.cpp index 5a92a51..9fea0ef 100644 --- a/Sources/VLModel.cpp +++ b/Sources/VLModel.cpp @@ -1160,7 +1160,6 @@ bool VLSong::NextWord(size_t stanza, size_t & measure, VLFraction & at) VLNoteList::iterator note = fMeasures[measure].fMelody.begin(); VLNoteList::iterator end = fMeasures[measure].fMelody.end(); bool hasWord = false; - VLFraction word(0); VLFraction now(0); while (note != meas.fMelody.end()) { @@ -1168,20 +1167,92 @@ bool VLSong::NextWord(size_t stanza, size_t & measure, VLFraction & at) if (note->fLyrics.size() < stanza || !(note->fLyrics[stanza-1].fKind & VLSyllable::kHasPrev) ) { - word = now; - hasWord = true; + at = now; + + return true; } now += note->fDuration; ++note; } - if (hasWord) { - at = word; - - return true; - } else { - firstMeasure = false; - } + firstMeasure = false; } while (++measure < fMeasures.size()); return false; } + +std::string VLSong::GetWord(size_t stanza, size_t measure, VLFraction at) +{ + std::string word; + + do { + VLMeasure & meas = fMeasures[measure]; + VLNoteList::iterator note = fMeasures[measure].fMelody.begin(); + VLNoteList::iterator end = fMeasures[measure].fMelody.end(); + VLFraction now(0); + + while (note != meas.fMelody.end()) { + if (now >= at && note->fPitch != VLNote::kNoPitch) { + if (word.size()) + word += '-'; + if (stanza <= note->fLyrics.size()) { + word += note->fLyrics[stanza-1].fText; + if (!(note->fLyrics[stanza-1].fKind & VLSyllable::kHasNext)) + return word; + } + } + now += note->fDuration; + ++note; + } + at = 0; + } while (++measure < fMeasures.size()); + + return word; +} + +void VLSong::SetWord(size_t stanza, size_t measure, VLFraction at, std::string word) +{ + uint8_t kind = 0; + bool cleanup = false; + + do { + VLMeasure & meas = fMeasures[measure]; + VLNoteList::iterator note = fMeasures[measure].fMelody.begin(); + VLNoteList::iterator end = fMeasures[measure].fMelody.end(); + VLFraction now(0); + + while (note != meas.fMelody.end()) { + if (now >= at && note->fPitch != VLNote::kNoPitch) { + if (cleanup) { + // + // Make sure that following syllable doesn't have + // kHasPrev set + // + if (note->fLyrics.size() >= stanza) + note->fLyrics[stanza-1].fKind &= ~VLSyllable::kHasPrev; + + return; + } + if (note->fLyrics.size()fLyrics.resize(stanza); + size_t root = word.find('-'); + std::string syll; + if (root == std::string::npos) { + syll = word; + kind &= ~VLSyllable::kHasNext; + cleanup = true; + } else { + syll = word.substr(0, root); + word.erase(0, root+1); + kind |= VLSyllable::kHasNext; + } + note->fLyrics[stanza-1].fText = syll; + note->fLyrics[stanza-1].fKind = kind; + kind |= VLSyllable::kHasPrev; + } + now += note->fDuration; + ++note; + } + at = 0; + } while (++measure < fMeasures.size()); +} + diff --git a/Sources/VLModel.h b/Sources/VLModel.h index 15c1d3c..7fcc122 100644 --- a/Sources/VLModel.h +++ b/Sources/VLModel.h @@ -258,6 +258,8 @@ struct VLSong { bool FindWord(size_t stanza, size_t & measure, VLFraction & at); bool PrevWord(size_t stanza, size_t & measure, VLFraction & at); bool NextWord(size_t stanza, size_t & measure, VLFraction & at); + std::string GetWord(size_t stanza, size_t measure, VLFraction at); + void SetWord(size_t stanza, size_t measure, VLFraction at, std::string word); size_t CountMeasures() const { return fMeasures.size(); } size_t CountStanzas() const; diff --git a/Sources/VLSheetView.h b/Sources/VLSheetView.h index d7a102b..558ce3a 100644 --- a/Sources/VLSheetView.h +++ b/Sources/VLSheetView.h @@ -73,6 +73,7 @@ enum VLRecalc { int fCursorPitch; int fCursorActualPitch; VLMusicElement fCursorAccidental; + size_t fCursorStanza; IBOutlet id fFieldEditor; } diff --git a/Sources/VLSheetView.mm b/Sources/VLSheetView.mm index 2b8bfc6..820829d 100644 --- a/Sources/VLSheetView.mm +++ b/Sources/VLSheetView.mm @@ -10,6 +10,7 @@ #import "VLSheetViewInternal.h" #import "VLSheetViewChords.h" #import "VLSheetViewNotes.h" +#import "VLSheetViewLyrics.h" #import "VLSoundOut.h" #import "VLDocument.h" @@ -597,6 +598,8 @@ static int8_t sSharpAcc[] = { fCursorAt = VLFraction(fCursorAt.fNum / scale, 4); return fCursorRegion = kRegionChord; } else if (loc.y < kSystemY+kLyricsY) { + fCursorStanza = static_cast((kSystemY+kLyricsY-loc.y) / kLyricsH) + + 1; return fCursorRegion = kRegionLyrics; } diff --git a/Sources/VLSheetViewLyrics.h b/Sources/VLSheetViewLyrics.h index 6b19262..51a0746 100644 --- a/Sources/VLSheetViewLyrics.h +++ b/Sources/VLSheetViewLyrics.h @@ -9,14 +9,16 @@ #import "VLSheetWindow.h" @interface VLLyricsEditable : VLEditable { - VLSheetView * fView; - VLSong * fSong; - int fMeasure; - VLFract fAt; + VLSheetView * fView; + VLSong * fSong; + size_t fStanza; + size_t fMeasure; + VLFraction fAt; } - (VLLyricsEditable *)initWithView:(VLSheetView *)view song:(VLSong *)song + stanza:(int)stanza measure:(int)measure at:(VLFract)at; - (NSString *) stringValue; @@ -32,7 +34,7 @@ - (void) editLyrics; - (void) drawLyricsForSystem:(int)system stanza:(size_t)stanza; -- (void) highlightLyricsInMeasure:(int)measure at:(VLFraction)at stanza:(size_t)stanza; +- (void) highlightLyricsInStanza:(size_t)stanza measure:(int)measure at:(VLFraction)at; @end diff --git a/Sources/VLSheetViewLyrics.mm b/Sources/VLSheetViewLyrics.mm index cd1e797..d42e700 100644 --- a/Sources/VLSheetViewLyrics.mm +++ b/Sources/VLSheetViewLyrics.mm @@ -17,15 +17,19 @@ - (VLLyricsEditable *)initWithView:(VLSheetView *)view song:(VLSong *)song + stanza:(int)stanza measure:(int)measure at:(VLFract)at { self = [super init]; fView = view; fSong = song; + fStanza = stanza; fMeasure= measure; fAt = at; + fSong->FindWord(fStanza, fMeasure, fAt); + [fView setNeedsDisplay: YES]; return self; @@ -33,10 +37,13 @@ - (NSString *) stringValue { + std::string word = fSong->GetWord(fStanza, fMeasure, fAt); + return [NSString stringWithUTF8String:word.c_str()]; } - (void) setStringValue:(NSString *)val { + fSong->SetWord(fStanza, fMeasure, fAt, [val UTF8String]); } - (BOOL) validValue:(NSString *)val @@ -45,16 +52,26 @@ } - (void) moveToNext -{ +{ + if (!fSong->NextWord(fStanza, fMeasure, fAt)) { + fMeasure = 0; + fAt = 0; + fSong->FindWord(fStanza, fMeasure, fAt); + } } - (void) moveToPrev { + if (!fSong->PrevWord(fStanza, fMeasure, fAt)) { + fMeasure = fSong->CountMeasures()-1; + fAt = fSong->fMeasures[fMeasure].fProperties->fTime; + fSong->PrevWord(fStanza, fMeasure, fAt); + } } - (void) highlightCursor { - [fView highlightLyricsInMeasure:fMeasure at:fAt]; + [fView highlightLyricsInStanza:fStanza measure:fMeasure at:fAt]; } @end @@ -117,21 +134,15 @@ [[VLLyricsEditable alloc] initWithView:self song:[self song] + stanza:fCursorStanza measure:fCursorMeasure at:fCursorAt]; [self setEditTarget:e]; [fFieldEditor selectText:self]; } -- (void) highlightLyricsInMeasure:(int)measure at:(VLFraction)at stanza:(size_t)stanza +- (void) highlightLyricsInStanza:(size_t)stanza measure:(int)measure at:(VLFraction)at { - const VLProperties & prop = [self song]->fProperties.front(); - const float kSystemY = [self systemY:measure / fMeasPerSystem]; - NSRect r = - NSMakeRect([self noteXInMeasure:measure at:at]-kNoteW*0.5f, - kSystemY+kChordY, prop.fDivisions*kNoteW, kChordH); - [[NSColor colorWithCalibratedWhite:0.8f alpha:1.0f] setFill]; - NSRectFillUsingOperation(r, NSCompositePlusDarker); } @end