Я нашел хакерский обходной путь для достижения такого поведения. Я создал демонстрационный проект, соответствующий класс есть TerminalLikeTextView. Это решение работает отлично, но я все же хотел бы иметь лучшее решение: менее хакерское и менее зависимое от внутренней механики NSTextView, поэтому, если у кого-то есть такое, поделитесь.
Ключевые шаги:
1) Установите для mouseDownFlag значение YES до нажатия кнопки мыши и значение NO после:
@property (assign, nonatomic) BOOL mouseDownFlag;
- (void)mouseDown:(NSEvent *)theEvent {
self.mouseDownFlag = YES;
[super mouseDown:theEvent];
self.mouseDownFlag = NO;
}
2) Чтобы точка вставки не обновляла возврат раньше из метода updateInsertionPointStateAndRestartTimer
:
- (void)updateInsertionPointStateAndRestartTimer:(BOOL)flag {
if (self.mouseDownFlag) {
return;
}
[super updateInsertionPointStateAndRestartTimer:flag];
}
3) Первые два шага заставят точку вставки не перемещаться с помощью мыши, однако selectionRange
все равно будет изменено, поэтому нам нужно следить за этим:
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) Попытка печати с помощью ключей восстанавливает местоположение, если это необходимо:
- (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)];
}
person
Stanislav Pankevich
schedule
22.03.2016
insertText:replacementRange:
будет работать сeditable = NO
, но не добавляет никакого текста. - person Stanislav Pankevich   schedule 21.03.2016