VocalEasel/Sources/VLSheetViewChords.mm

269 lines
6.7 KiB
Plaintext
Raw Normal View History

2006-09-11 02:49:56 +00:00
//
2007-04-27 06:41:34 +00:00
// File: VLSheetViewChords.mm - Chord editing functionality
2006-09-11 02:49:56 +00:00
//
2007-04-27 06:41:34 +00:00
// Author(s):
//
// (MN) Matthias Neeracher
//
2018-02-19 00:59:23 +00:00
// Copyright © 2006-2018 Matthias Neeracher
2006-09-11 02:49:56 +00:00
//
#import "VLSheetView.h"
#import "VLSheetViewChords.h"
#import "VLSheetViewInternal.h"
#import "VLDocument.h"
2006-09-11 02:49:56 +00:00
#import "VLModel.h"
#import "VLSoundOut.h"
2006-10-03 17:52:54 +00:00
std::string NormalizeName(NSString* rawName)
{
std::string chordName =
rawName ? (const char *)[[rawName lowercaseString] UTF8String] : "";
2006-10-03 17:52:54 +00:00
//
// Normalize # and b
//
for (;;) {
size_t found;
2006-09-11 02:49:56 +00:00
2006-10-03 17:52:54 +00:00
found = chordName.find(" ", 0, 1);
if (found != std::string::npos) {
chordName.erase(found);
continue;
}
break;
}
return chordName;
}
@interface NSAttributedString (Chords)
+ (NSAttributedString *) attributedStringWithCppString:(const std::string &)s
attributes:(NSDictionary *)a;
@end
@implementation NSAttributedString (Chords)
+ (NSAttributedString *) attributedStringWithCppString:(const std::string &)s
2006-09-11 02:49:56 +00:00
attributes:(NSDictionary *)a
{
return [[[NSAttributedString alloc]
initWithString:[NSString stringWithUTF8String:s.c_str()]
attributes: a]
autorelease];
}
2006-10-03 17:52:54 +00:00
@end
@implementation VLChordEditable
- (VLChordEditable *)initWithView:(VLSheetView *)view
2006-10-03 17:52:54 +00:00
song:(VLSong *)song
2011-09-11 02:03:22 +00:00
at:(VLLocation)at;
2006-10-03 17:52:54 +00:00
{
2011-09-11 02:03:22 +00:00
self = [super init];
fView = view;
fSong = song;
fSelection = at;
2006-10-03 17:52:54 +00:00
[fView setNeedsDisplay: YES];
2006-10-03 17:52:54 +00:00
return self;
}
- (NSString *) stringValue
{
2011-09-11 02:03:22 +00:00
if (fSelection.fMeasure >= fSong->CountMeasures())
2007-05-05 05:42:34 +00:00
return @"";
2011-09-11 02:03:22 +00:00
const VLMeasure measure = fSong->fMeasures[fSelection.fMeasure];
2006-10-03 17:52:54 +00:00
const VLChordList & chords = measure.fChords;
VLFraction at(0);
for (VLChordList::const_iterator chord = chords.begin();
2011-09-11 02:03:22 +00:00
chord != chords.end() && at <= fSelection.fAt;
2006-10-03 17:52:54 +00:00
++chord
) {
2011-09-11 02:03:22 +00:00
if (at == fSelection.fAt && chord->fPitch != VLNote::kNoPitch) {
2006-10-03 17:52:54 +00:00
//
// Found it!
//
2006-10-29 07:48:39 +00:00
VLSoundOut::Instance()->PlayChord(*chord);
2011-09-11 02:03:22 +00:00
const VLProperties & prop = fSong->Properties(fSelection.fMeasure);
2006-10-03 17:52:54 +00:00
std::string name, ext, root;
chord->Name(name, ext, root, prop.fKey > 0);
2006-10-29 07:48:39 +00:00
NSString * ns = [NSString stringWithUTF8String:name.c_str()];
NSString * es = [NSString stringWithUTF8String:ext.c_str()];
NSString * rs = [NSString stringWithUTF8String:root.c_str()];
return [NSString stringWithFormat:@"%@%@%s%@", ns, es,
[rs length] ? "/" : "", rs];
2006-10-03 17:52:54 +00:00
}
at += chord->fDuration;
}
return @"";
}
- (void) setStringValue:(NSString *)val
{
std::string chordName = NormalizeName(val);
if (!chordName.size()) {
2007-05-04 05:41:25 +00:00
[[fView document] willChangeSong];
2011-09-11 02:03:22 +00:00
fSong->DelChord(fSelection);
2007-05-04 05:41:25 +00:00
[[fView document] didChangeSong];
2006-10-03 17:52:54 +00:00
} else {
VLChord chord(chordName);
VLSoundOut::Instance()->PlayChord(chord);
2006-12-04 07:04:24 +00:00
[[fView document] willChangeSong];
2011-09-11 02:03:22 +00:00
fSong->AddChord(chord, fSelection);
2006-12-04 07:04:24 +00:00
[[fView document] didChangeSong];
2006-10-03 17:52:54 +00:00
}
}
- (BOOL) validValue:(NSString *)val
{
std::string chordName = NormalizeName(val);
if (!chordName.size())
return YES;
//
// Check for valid chord
//
VLChord chord(chordName);
return chord.fPitch != VLNote::kNoPitch;
}
- (void) moveToNext
{
const VLProperties & prop = fSong->Properties(fSelection.fMeasure);
2011-09-11 02:03:22 +00:00
fSelection.fAt = fSelection.fAt+VLFraction(1,4);
if (fSelection.fAt >= prop.fTime) {
fSelection.fAt = VLFraction(0,4);
fSelection.fMeasure = (fSelection.fMeasure+1) % fSong->CountMeasures();
[fView scrollMeasureToVisible:fSelection.fMeasure];
}
}
- (void) moveToPrev
{
2011-09-11 02:03:22 +00:00
if (fSelection.fAt < VLFraction(1,4)) {
fSelection.fMeasure =
(fSelection.fMeasure+fSong->CountMeasures()-1) % fSong->CountMeasures();
const VLProperties & prop = fSong->Properties(fSelection.fMeasure);
2011-09-11 02:03:22 +00:00
fSelection.fAt = prop.fTime - VLFraction(1,4);
[fView scrollMeasureToVisible:fSelection.fMeasure];
} else
2011-09-11 02:03:22 +00:00
fSelection.fAt = fSelection.fAt-VLFraction(1,4);
}
- (void) highlightCursor
{
2011-09-11 02:03:22 +00:00
[fView highlightChord:fSelection];
}
2006-10-03 17:52:54 +00:00
@end
@implementation VLSheetView (Chords)
2006-09-11 02:49:56 +00:00
- (NSAttributedString *) stringWithChord:(const VLChord &)chord
{
const VLSong * song = [self song];
const VLProperties & prop = song->fProperties.front();
static NSDictionary * sBigFont = nil;
static NSDictionary * sSuperFont = nil;
if (!sBigFont)
sBigFont =
[[NSDictionary alloc] initWithObjectsAndKeys:
[NSFont fontWithName: @"Helvetica" size: 14],
NSFontAttributeName,
nil];
if (!sSuperFont)
sSuperFont =
[[NSDictionary alloc] initWithObjectsAndKeys:
[NSFont fontWithName: @"Helvetica" size: 12],
NSFontAttributeName,
[NSNumber numberWithInt: 1],
NSSuperscriptAttributeName,
nil];
std::string name, ext, root;
if (chord.fPitch != VLNote::kNoPitch)
chord.Name(name, ext, root, prop.fKey > 0);
NSMutableAttributedString * s =
[[[NSMutableAttributedString alloc] init] autorelease];
[s appendAttributedString:
2006-10-03 17:52:54 +00:00
[NSAttributedString attributedStringWithCppString: name
2006-09-11 02:49:56 +00:00
attributes: sBigFont]];
[s appendAttributedString:
2006-10-03 17:52:54 +00:00
[NSAttributedString attributedStringWithCppString: ext.size() ? ext : " "
2006-09-11 02:49:56 +00:00
attributes: sSuperFont]];
if (root.size())
[s appendAttributedString:
2006-10-03 17:52:54 +00:00
[NSAttributedString attributedStringWithCppString: "/" + root
2006-09-11 02:49:56 +00:00
attributes: sBigFont]];
return s;
}
- (void) drawChordsForSystem:(int)system
2006-09-11 02:49:56 +00:00
{
2007-12-23 12:45:17 +00:00
const VLSong * song = [self song];
const float kSystemY = [self systemY:system];
const int kFirstMeas = fLayout->FirstMeasure(system);
const VLSystemLayout & kLayout = (*fLayout)[system];
2006-09-11 02:49:56 +00:00
//
// Build new list
//
2007-12-23 12:45:17 +00:00
for (int m = 0; m<kLayout.NumMeasures(); ++m) {
2018-02-19 00:59:23 +00:00
uint32_t measIdx = m+kFirstMeas;
if (measIdx >= song->CountMeasures())
break;
const VLMeasure measure = song->fMeasures[measIdx];
const VLChordList & chords = measure.fChords;
2011-09-11 02:03:22 +00:00
VLLocation at = {measIdx, VLFraction(0)};
for (VLChordList::const_iterator chord = chords.begin();
chord != chords.end();
++chord
) {
NSAttributedString * chordName = [self stringWithChord:*chord];
NSPoint chordLoc =
2011-09-11 02:03:22 +00:00
NSMakePoint([self noteXAt:at], kSystemY+kChordY);
[chordName drawAtPoint:chordLoc];
2011-09-11 02:03:22 +00:00
at.fAt = at.fAt+chord->fDuration;
2006-09-11 02:49:56 +00:00
}
}
}
2006-10-03 17:52:54 +00:00
- (void) editChord
{
2006-10-03 17:52:54 +00:00
VLEditable * e =
[[VLChordEditable alloc]
initWithView:self
song:[self song]
2011-09-11 02:03:22 +00:00
at:fCursorLocation];
[self setEditTarget:e];
[fFieldEditor selectText:self];
}
2011-09-11 02:03:22 +00:00
- (void) highlightChord:(VLLocation)at
{
const VLProperties & prop = [self song]->Properties(at.fMeasure);
2011-09-11 02:03:22 +00:00
const float kSystemY = [self systemY:fLayout->SystemForMeasure(at.fMeasure)];
2006-10-09 07:28:49 +00:00
NSRect r =
2011-09-11 02:03:22 +00:00
NSMakeRect([self noteXAt:at]-kNoteW*0.5f,
2006-10-09 07:28:49 +00:00
kSystemY+kChordY, prop.fDivisions*kNoteW, kChordH);
[[NSColor colorWithCalibratedWhite:0.8f alpha:1.0f] setFill];
NSRectFillUsingOperation(r, NSCompositePlusDarker);
2006-09-11 02:49:56 +00:00
}
@end