2016-03-21 26 views
6

Ho un componente basato su NSTextView e vorrei disabilitare singoli clic su di esso, in modo che il suo punto di inserimento non sia influenzato da questi singoli clic, ma ancora essere in grado di selezionare parti di testo per il lavoro copia-incolla:NSTextView: come disabilitare i clic singoli, ma consentire comunque la selezione per copia e incolla?

  1. singoli scatti fanno nulla
  2. copia-e-incolla è possibile e non influisce punto di inserimento

quello che voglio è esattamente ciò che abbiamo in difetto Terminal app: non c'è punto di inserimento e non è possibile cambiarlo con un clic del mouse, ma è ancora possibile selezionare il testo per il copia e incolla possibile.

Ho provato a guardare il metodo - (void)mouseDown:(NSEvent *)theEvent ma non ho trovato nulla di utile.

+0

disposta la modificabile = NO, selezionabile = YES essere sufficiente? o hai bisogno di qualcosa di diverso? puoi chiarire? – Remizorrr

+0

Potrebbe essere sufficiente dato 'insertText: replacementRange:' funzionerebbe con 'editable = NO' ma non aggiunge alcun testo. –

+0

@StanislavPankevich potrebbe essere appena impostato modificabile su SÌ prima di incollare e quindi tornare a NO? – faviomob

risposta

1

Ho trovato una soluzione hacky per ottenere questo tipo di comportamento. Ho creato demo project, la classe rilevante è TerminalLikeTextView. Questa soluzione funziona perfettamente, ma mi piacerebbe comunque avere una soluzione migliore: meno hacky e meno dipendente dalla meccanica interna di NSTextView, quindi se qualcuno ne ha voglia, condividilo.

Le fasi principali sono:

1) Set mouseDownFlag YES prima mouse in basso a NO dopo:

@property (assign, nonatomic) BOOL mouseDownFlag; 

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

    [super mouseDown:theEvent]; 

    self.mouseDownFlag = NO; 
} 

2) Per impedire punto di inserimento di aggiornare ritorno anticipato da updateInsertionPointStateAndRestartTimer metodo:

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

    [super updateInsertionPointStateAndRestartTimer:flag]; 
} 

3) I primi due passaggi faranno sì che il punto di inserimento non si sposti con il mouse, tuttavia lo selectionRange verrà comunque modificato in modo da eed per tenere traccia di esso:

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) tenta di stampare utilizzando i tasti ripristina posizione se necessario:

- (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)]; 
}