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)];
}
Czy można edytować = NIE, wybierane = TAK wystarczy? czy potrzebujesz czegoś innego? możesz wyjaśnić? – Remizorrr
Może to wystarczyć pod warunkiem, że 'insertText: replacementRange:' zadziała z 'editable = NO', ale nie doda żadnego tekstu. –
@StanislavPankevich można po prostu ustawić edytowalne na TAK tuż przed wklejeniem, a następnie powrócić do NIE? – faviomob