// // VLSheetViewChords.mm // Vocalese // // Created by Matthias Neeracher on 1/4/06. // Copyright 2006 __MyCompanyName__. All rights reserved. // #import "VLSheetView.h" #import "VLSheetViewChords.h" #import "VLSheetViewInternal.h" #import "VLModel.h" #import "VLSoundOut.h" @implementation VLSheetView (Chords) - (NSAttributedString *) attributedStringWithCppString:(const std::string &)s attributes:(NSDictionary *)a { return [[[NSAttributedString alloc] initWithString:[NSString stringWithUTF8String:s.c_str()] attributes: a] autorelease]; } - (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: [self attributedStringWithCppString: name attributes: sBigFont]]; [s appendAttributedString: [self attributedStringWithCppString: ext.size() ? ext : " " attributes: sSuperFont]]; if (root.size()) [s appendAttributedString: [self attributedStringWithCppString: "/" + root attributes: sBigFont]]; return s; } - (void) setupChords { const VLSong * song = [self song]; const VLProperties & prop = song->fProperties.front(); NSView * chordView = [chords contentView]; // // Delete old list of chord boxes // for (NSEnumerator * e = [[chordView subviews] objectEnumerator]; NSView * subview = [e nextObject]; ) [subview removeFromSuperview]; // // Build new list // NSView * prevKeyView = nil; NSFont * chordFont = [NSFont controlContentFontOfSize: 14]; int beatsPerGroup = quarterBeats / groups; for (int m = 0; mfMeasures[measure].fChords.begin(); VLChordList::const_iterator cEnd = song->fMeasures[measure].fChords.end(); VLFraction at(0); for (int beat = 0; beatfDuration; if (cCur != cEnd && at == VLFraction(beat, 4) && cCur->fPitch != VLNote::kNoPitch) [chord setAttributedStringValue: [self stringWithChord:*cCur]]; [chord release]; } } [chords setNeedsDisplay: YES]; } - (IBAction) editChord:(id)sender { VLSong * song = [self song]; std::string chordName = (const char *)[[[sender stringValue] lowercaseString] UTF8String]; // // Normalize # and b // for (;;) { size_t found; found = chordName.find("\xE2\x99\xAF", 0, 3); if (found != std::string::npos) { chordName.replace(found, 3, 1, '#'); continue; } found = chordName.find("\xE2\x99\xAD", 0, 3); if (found != std::string::npos) { chordName.replace(found, 3, 1, 'b'); continue; } found = chordName.find(" ", 0, 1); if (found != std::string::npos) { chordName.erase(found); continue; } break; } // // Check for valid chord // VLChord chord(chordName); if (!chordName.size()) { [sender setTextColor: [NSColor blackColor]]; } else if (chord.fPitch == VLChord::kNoPitch) { if (chordName.size()) { NSBeep(); [sender setTextColor: [NSColor redColor]]; } int tag = [sender tag]; song->DelChord(tag >> 8, VLFraction(tag & 0xFF, 4)); } else { NSAttributedString * s = [self stringWithChord:chord]; [sender setAttributedStringValue: s]; [sender setTextColor: [NSColor blackColor]]; NSSize sz = [sender frame].size; sz.width = [s size].width+10.0; [sender setFrameSize: sz]; VLSoundOut::Instance()->PlayChord(chord); int tag = [sender tag]; song->AddChord(chord, tag >> 8, VLFraction(tag & 0xFF, 4)); } } @end