mirror of
https://github.com/microtherion/VocalEasel.git
synced 2024-12-22 11:14:00 +00:00
Extendable text selection
This commit is contained in:
parent
b831adb136
commit
7dc46ea1de
|
@ -100,7 +100,6 @@ enum VLCursorVisual {
|
||||||
int fHighlightEndMeasure;
|
int fHighlightEndMeasure;
|
||||||
VLFract fHighlightEndAt;
|
VLFract fHighlightEndAt;
|
||||||
size_t fHighlightStanza;
|
size_t fHighlightStanza;
|
||||||
bool fHighlightNow;
|
|
||||||
VLKeyValueUndo * fUndo;
|
VLKeyValueUndo * fUndo;
|
||||||
|
|
||||||
IBOutlet id fFieldEditor;
|
IBOutlet id fFieldEditor;
|
||||||
|
@ -153,6 +152,7 @@ enum VLCursorVisual {
|
||||||
|
|
||||||
- (VLEditable *) editTarget;
|
- (VLEditable *) editTarget;
|
||||||
- (void) setEditTarget:(VLEditable *)editable;
|
- (void) setEditTarget:(VLEditable *)editable;
|
||||||
|
- (void) updateEditTarget;
|
||||||
- (VLRegion) findRegionForEvent:(NSEvent *) event;
|
- (VLRegion) findRegionForEvent:(NSEvent *) event;
|
||||||
|
|
||||||
- (void) setGroove:(NSString *)groove;
|
- (void) setGroove:(NSString *)groove;
|
||||||
|
|
|
@ -148,6 +148,11 @@ static float sFlatPos[] = {
|
||||||
[[[self window] windowController] setEditTarget:editable];
|
[[[self window] windowController] setEditTarget:editable];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) updateEditTarget
|
||||||
|
{
|
||||||
|
[fFieldEditor takeStringValueFrom:[self editTarget]];
|
||||||
|
}
|
||||||
|
|
||||||
- (VLSong *) song
|
- (VLSong *) song
|
||||||
{
|
{
|
||||||
return [[self document] song];
|
return [[self document] song];
|
||||||
|
@ -837,21 +842,26 @@ const float kSemiFloor = -1.0f*kLineH;
|
||||||
|
|
||||||
- (void) mouseDown:(NSEvent *)event
|
- (void) mouseDown:(NSEvent *)event
|
||||||
{
|
{
|
||||||
|
BOOL extend = ([event modifierFlags] & NSShiftKeyMask) != 0;
|
||||||
switch ([self findRegionForEvent:event]) {
|
switch ([self findRegionForEvent:event]) {
|
||||||
case kRegionNote:
|
case kRegionNote:
|
||||||
fSelEnd = -1;
|
fSelEnd = -1;
|
||||||
[self addNoteAtCursor];
|
[self addNoteAtCursor];
|
||||||
break;
|
break;
|
||||||
case kRegionChord:
|
case kRegionChord:
|
||||||
fSelEnd = -1;
|
fSelEnd = -1;
|
||||||
[self editChord];
|
[self editChord];
|
||||||
break;
|
break;
|
||||||
case kRegionLyrics:
|
case kRegionLyrics:
|
||||||
fSelEnd = -1;
|
if (extend && [[self editTarget] canExtendSelection:kRegionLyrics]) {
|
||||||
[self editLyrics];
|
[[self editTarget] extendSelection:fCursorMeasure at:fCursorAt];
|
||||||
|
} else {
|
||||||
|
fSelEnd = -1;
|
||||||
|
[self editLyrics];
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case kRegionMeasure:
|
case kRegionMeasure:
|
||||||
[self editSelection:([event modifierFlags] & NSShiftKeyMask) != 0];
|
[self editSelection:extend];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fSelEnd = -1;
|
fSelEnd = -1;
|
||||||
|
@ -861,13 +871,14 @@ const float kSemiFloor = -1.0f*kLineH;
|
||||||
|
|
||||||
- (void) mouseDragged:(NSEvent *)event
|
- (void) mouseDragged:(NSEvent *)event
|
||||||
{
|
{
|
||||||
bool inMeasureSelection = fCursorRegion == kRegionMeasure;
|
VLRegion prevRegion = fCursorRegion;
|
||||||
|
|
||||||
if (!inMeasureSelection)
|
[super mouseDragged:event];
|
||||||
[super mouseDragged:event];
|
|
||||||
[self autoscroll:event];
|
[self autoscroll:event];
|
||||||
if (inMeasureSelection)
|
if (prevRegion == kRegionMeasure)
|
||||||
[self adjustSelection:event];
|
[self adjustSelection:event];
|
||||||
|
else if ([[self editTarget] canExtendSelection:[self findRegionForEvent:event]])
|
||||||
|
[[self editTarget] extendSelection:fCursorMeasure at:fCursorAt];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) keyDown:(NSEvent *)event
|
- (void) keyDown:(NSEvent *)event
|
||||||
|
@ -919,11 +930,9 @@ const float kSemiFloor = -1.0f*kLineH;
|
||||||
[editable moveToPrev];
|
[editable moveToPrev];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
[editable autorelease];
|
|
||||||
fHighlightStanza = 0xFFFFFFFF;
|
fHighlightStanza = 0xFFFFFFFF;
|
||||||
editable = nil;
|
editable = nil;
|
||||||
}
|
}
|
||||||
[self setEditTarget:editable];
|
|
||||||
if (editable)
|
if (editable)
|
||||||
[fFieldEditor selectText:self];
|
[fFieldEditor selectText:self];
|
||||||
else
|
else
|
||||||
|
|
|
@ -16,8 +16,11 @@
|
||||||
size_t fStanza;
|
size_t fStanza;
|
||||||
size_t fMeasure;
|
size_t fMeasure;
|
||||||
VLFract fAt;
|
VLFract fAt;
|
||||||
|
size_t fAnchorMeas;
|
||||||
|
VLFract fAnchorAt;
|
||||||
size_t fNextMeas;
|
size_t fNextMeas;
|
||||||
VLFract fNextAt;
|
VLFract fNextAt;
|
||||||
|
NSString * fText;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (VLLyricsEditable *)initWithView:(VLSheetView *)view
|
- (VLLyricsEditable *)initWithView:(VLSheetView *)view
|
||||||
|
|
|
@ -22,8 +22,11 @@
|
||||||
{
|
{
|
||||||
size_t endMeas = fMeasure;
|
size_t endMeas = fMeasure;
|
||||||
VLFraction endAt = fAt;
|
VLFraction endAt = fAt;
|
||||||
fSong->NextWord(fStanza, endMeas, endAt);
|
if (!fSong->NextWord(fStanza, endMeas, endAt))
|
||||||
|
endMeas = 1000;
|
||||||
[fView highlightTextInStanza:fStanza startMeasure:fMeasure at:fAt endMeasure:endMeas at:endAt];
|
[fView highlightTextInStanza:fStanza startMeasure:fMeasure at:fAt endMeasure:endMeas at:endAt];
|
||||||
|
std::string word = fSong->GetWord(fStanza, fMeasure, fAt);
|
||||||
|
fText = [[NSString alloc] initWithUTF8String:word.c_str()];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (VLLyricsEditable *)initWithView:(VLSheetView *)view
|
- (VLLyricsEditable *)initWithView:(VLSheetView *)view
|
||||||
|
@ -38,6 +41,8 @@
|
||||||
fStanza = stanza;
|
fStanza = stanza;
|
||||||
fMeasure = measure;
|
fMeasure = measure;
|
||||||
fAt = at;
|
fAt = at;
|
||||||
|
fAnchorMeas = measure;
|
||||||
|
fAnchorAt = at;
|
||||||
fNextMeas = fMeasure;
|
fNextMeas = fMeasure;
|
||||||
fNextAt = fAt;
|
fNextAt = fAt;
|
||||||
|
|
||||||
|
@ -49,10 +54,14 @@
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)dealloc
|
||||||
|
{
|
||||||
|
[fText release];
|
||||||
|
}
|
||||||
|
|
||||||
- (NSString *) stringValue
|
- (NSString *) stringValue
|
||||||
{
|
{
|
||||||
std::string word = fSong->GetWord(fStanza, fMeasure, fAt);
|
return fText;
|
||||||
return [NSString stringWithUTF8String:word.c_str()];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) setStringValue:(NSString *)val
|
- (void) setStringValue:(NSString *)val
|
||||||
|
@ -111,6 +120,51 @@
|
||||||
[fView highlightLyricsInStanza:fStanza measure:fMeasure at:fAt];
|
[fView highlightLyricsInStanza:fStanza measure:fMeasure at:fAt];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)canExtendSelection:(VLRegion)region
|
||||||
|
{
|
||||||
|
return region == kRegionLyrics;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)extendSelection:(size_t)measure at:(VLFract)At
|
||||||
|
{
|
||||||
|
VLFraction at = At;
|
||||||
|
if (!fSong->FindWord(fStanza, measure, at))
|
||||||
|
return;
|
||||||
|
if (measure < fAnchorMeas || (measure==fAnchorMeas && at < fAnchorAt)) {
|
||||||
|
//
|
||||||
|
// Backward from anchor
|
||||||
|
//
|
||||||
|
fMeasure = measure;
|
||||||
|
fAt = at;
|
||||||
|
measure = fAnchorMeas;
|
||||||
|
at = fAnchorAt;
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// Forward from anchor
|
||||||
|
//
|
||||||
|
fMeasure = fAnchorMeas;
|
||||||
|
at = fAnchorAt;
|
||||||
|
fSong->FindWord(fStanza, fMeasure, at);
|
||||||
|
fAt = at;
|
||||||
|
at = At;
|
||||||
|
}
|
||||||
|
if (!fSong->NextWord(fStanza, measure, at))
|
||||||
|
measure = 1000;
|
||||||
|
[fView highlightTextInStanza:fStanza startMeasure:fMeasure at:fAt endMeasure:measure at:at];
|
||||||
|
std::string text;
|
||||||
|
size_t textMeas = fMeasure;
|
||||||
|
VLFraction textAt = fAt;
|
||||||
|
while (textMeas < measure || (textMeas == measure && textAt < at)) {
|
||||||
|
if (text.size())
|
||||||
|
text += ' ';
|
||||||
|
text += fSong->GetWord(fStanza, textMeas, textAt);
|
||||||
|
fSong->NextWord(fStanza, textMeas, textAt);
|
||||||
|
}
|
||||||
|
[fText release];
|
||||||
|
fText = [[NSString alloc] initWithUTF8String:text.c_str()];
|
||||||
|
[fView updateEditTarget];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
class VLCocoaFontHandler : public VLFontHandler {
|
class VLCocoaFontHandler : public VLFontHandler {
|
||||||
|
@ -192,23 +246,17 @@ float VLCocoaFontHandler::Width(const char * utf8Text)
|
||||||
) {
|
) {
|
||||||
;
|
;
|
||||||
} else {
|
} else {
|
||||||
if (!fHighlightNow) {
|
bool highlight = stanza == fHighlightStanza
|
||||||
fHighlightNow = stanza == fHighlightStanza
|
&& (measIdx > fHighlightStartMeasure
|
||||||
&& measIdx == fHighlightStartMeasure
|
|| (measIdx == fHighlightStartMeasure && at >= fHighlightStartAt))
|
||||||
&& at == fHighlightStartAt;
|
&& (measIdx < fHighlightEndMeasure
|
||||||
if (fHighlightNow && !sHighlightColor)
|
|| (measIdx == fHighlightEndMeasure && at < fHighlightEndAt));
|
||||||
sHighlightColor =
|
if (highlight && !sHighlightColor)
|
||||||
[[self textBackgroundColorForSystem:system]
|
sHighlightColor = [[self textBackgroundColorForSystem:system] shadowWithLevel:0.2];
|
||||||
shadowWithLevel:0.2];
|
|
||||||
} else {
|
|
||||||
fHighlightNow = fHighlightNow && stanza == fHighlightStanza
|
|
||||||
&& (measIdx < fHighlightEndMeasure
|
|
||||||
||(measIdx == fHighlightEndMeasure && at < fHighlightEndAt));
|
|
||||||
}
|
|
||||||
|
|
||||||
text.AddSyllable(note->fLyrics[stanza-1],
|
text.AddSyllable(note->fLyrics[stanza-1],
|
||||||
[self noteXInMeasure:measIdx at:at],
|
[self noteXInMeasure:measIdx at:at],
|
||||||
fHighlightNow);
|
highlight);
|
||||||
}
|
}
|
||||||
at += note->fDuration;
|
at += note->fDuration;
|
||||||
}
|
}
|
||||||
|
@ -249,7 +297,7 @@ float VLCocoaFontHandler::Width(const char * utf8Text)
|
||||||
fHighlightStartAt = startAt;
|
fHighlightStartAt = startAt;
|
||||||
fHighlightEndMeasure = endMeasure;
|
fHighlightEndMeasure = endMeasure;
|
||||||
fHighlightEndAt = endAt;
|
fHighlightEndAt = endAt;
|
||||||
fHighlightNow = false;
|
[self setNeedsDisplay:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
#import <AudioToolbox/AudioToolbox.h>
|
#import <AudioToolbox/AudioToolbox.h>
|
||||||
|
#import "VLSheetView.h"
|
||||||
|
|
||||||
@interface VLEditable : NSObject
|
@interface VLEditable : NSObject
|
||||||
{
|
{
|
||||||
|
@ -21,6 +22,8 @@
|
||||||
- (void) moveToNext;
|
- (void) moveToNext;
|
||||||
- (void) moveToPrev;
|
- (void) moveToPrev;
|
||||||
- (void) highlightCursor;
|
- (void) highlightCursor;
|
||||||
|
- (BOOL) canExtendSelection:(VLRegion)region;
|
||||||
|
- (void) extendSelection:(size_t)measure at:(VLFract)at;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,15 @@
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)canExtendSelection:(VLRegion)region
|
||||||
|
{
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)extendSelection:(size_t)measure at:(VLFract)at
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation VLSheetWindow
|
@implementation VLSheetWindow
|
||||||
|
@ -82,6 +91,7 @@
|
||||||
|
|
||||||
- (void)setEditTarget:(VLEditable *)editable
|
- (void)setEditTarget:(VLEditable *)editable
|
||||||
{
|
{
|
||||||
|
[editTarget autorelease];
|
||||||
editTarget = editable;
|
editTarget = editable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user