Extendable text selection

This commit is contained in:
Matthias Neeracher 2011-09-11 01:15:21 +02:00
parent b831adb136
commit 7dc46ea1de
6 changed files with 104 additions and 31 deletions

View File

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

View File

@ -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,6 +842,7 @@ 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;
@ -847,11 +853,15 @@ const float kSemiFloor = -1.0f*kLineH;
[self editChord]; [self editChord];
break; break;
case kRegionLyrics: case kRegionLyrics:
if (extend && [[self editTarget] canExtendSelection:kRegionLyrics]) {
[[self editTarget] extendSelection:fCursorMeasure at:fCursorAt];
} else {
fSelEnd = -1; fSelEnd = -1;
[self editLyrics]; [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

View File

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

View File

@ -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;
if (fHighlightNow && !sHighlightColor)
sHighlightColor =
[[self textBackgroundColorForSystem:system]
shadowWithLevel:0.2];
} else {
fHighlightNow = fHighlightNow && stanza == fHighlightStanza
&& (measIdx < fHighlightEndMeasure && (measIdx < fHighlightEndMeasure
|| (measIdx == fHighlightEndMeasure && at < fHighlightEndAt)); || (measIdx == fHighlightEndMeasure && at < fHighlightEndAt));
} if (highlight && !sHighlightColor)
sHighlightColor = [[self textBackgroundColorForSystem:system] shadowWithLevel:0.2];
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

View File

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

View File

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