2016-03-21 21 views
6

Mam komponent oparty na NSTextView i chciałbym wyłączyć pojedyncze kliknięcia, aby te pojedyncze kliknięcia nie miały wpływu na punkt wstawiania, ale nadal można wybrać fragmenty tekstu do kopiowania i wklejania:NSTextView: jak wyłączyć pojedyncze kliknięcia, ale nadal można wybrać opcję kopiowania i wklejania?

  1. pojedyncze kliknięcie zrobić nic
  2. kopiowania i wklejania jest możliwe i nie wpływa na punkt wstawiania

Co chcę jest dokładnie to, co mamy w domyślnej aplikacji Terminal: istnieje punkt wstawiania i nie można go zmienić za pomocą kliknięcia myszą, ale nadal zaznacza się tekst do kopiowania i wklejania możliwy.

Próbowałem, patrząc na metodę - (void)mouseDown:(NSEvent *)theEvent, ale nie znalazłem nic przydatnego.

+0

Czy można edytować = NIE, wybierane = TAK wystarczy? czy potrzebujesz czegoś innego? możesz wyjaśnić? – Remizorrr

+0

Może to wystarczyć pod warunkiem, że 'insertText: replacementRange:' zadziała z 'editable = NO', ale nie doda żadnego tekstu. –

+0

@StanislavPankevich można po prostu ustawić edytowalne na TAK tuż przed wklejeniem, a następnie powrócić do NIE? – faviomob

Odpowiedz

1

Znalazłem hacky obejście, aby osiągnąć tego rodzaju zachowanie. Stworzyłem demo project, odpowiednią klasą jest TerminalLikeTextView. To rozwiązanie działa idealnie, ale nadal chciałbym mieć lepsze rozwiązanie: mniej hacky i mniej zależne od wewnętrznej mechaniki NSTextView, więc jeśli ktoś ma takie proszę, udostępnij.

kluczowe etapy są następujące:

1) Zestaw mouseDownFlag YES przed myszy i NO, po:

@property (assign, nonatomic) BOOL mouseDownFlag; 

- (void)mouseDown:(NSEvent *)theEvent { 
    self.mouseDownFlag = YES; 

    [super mouseDown:theEvent]; 

    self.mouseDownFlag = NO; 
} 

2) Aby zapobiec kursor na aktualizację powrotu na początku od updateInsertionPointStateAndRestartTimer sposobem:

- (void)updateInsertionPointStateAndRestartTimer:(BOOL)flag { 
    if (self.mouseDownFlag) { 
     return; 
    } 

    [super updateInsertionPointStateAndRestartTimer:flag]; 
} 

3) Pierwsze dwa kroki sprawią, że punkt wstawiania nie będzie się poruszał za pomocą myszy, ale selectionRange będzie nadal zmieniony, więc my n Potrzeba, aby śledzić go:

static const NSUInteger kCursorLocationSnapshotNotExists = NSUIntegerMax; 
@property (assign, nonatomic) NSUInteger cursorLocationSnapshot; 

#pragma mark - <NSTextViewDelegate> 

- (NSRange)textView:(NSTextView *)textView willChangeSelectionFromCharacterRange:(NSRange)oldSelectedCharRange toCharacterRange:(NSRange)newSelectedCharRange { 

    if (self.mouseDownFlag && self.cursorLocationSnapshot == kCursorLocationSnapshotNotExists) { 
     self.cursorLocationSnapshot = oldSelectedCharRange.location; 
    } 

    return newSelectedCharRange; 
} 

4) Próba wydrukowania za pomocą przycisków przywraca lokalizację, jeśli potrzebne:

- (void)keyDown:(NSEvent *)event { 
    NSString *characters = event.characters; 

    [self insertTextToCurrentPosition:characters]; 
} 

- (void)insertTextToCurrentPosition:(NSString *)text { 
    if (self.cursorLocationSnapshot != kCursorLocationSnapshotNotExists) { 
     self.selectedRange = NSMakeRange(self.cursorLocationSnapshot, 0); 
     self.cursorLocationSnapshot = kCursorLocationSnapshotNotExists; 
    } 

    [self insertText:text replacementRange:NSMakeRange(self.selectedRange.location, 0)]; 
}