NSTextView:如何禁用单击但仍允许选择复制和粘贴



我有基于 NSTextView 的组件,我想禁用对它的单击,以便它的插入点不受这些单击的影响,但仍然能够选择文本片段进行复制和粘贴工作:

  1. 单击不执行任何操作
  2. 可以复制和粘贴,不会影响插入点

我想要的正是我们在默认终端应用程序中拥有的:有插入点,无法通过鼠标单击更改它,但仍然可以选择文本进行复制和粘贴。

我尝试查看- (void)mouseDown:(NSEvent *)theEvent方法,但没有发现任何有用的东西。

我找到了实现这种行为的黑客解决方法。我已经创建了演示项目,那里的相关类是TerminalLikeTextView。这个解决方案运行良好,但我仍然希望有一个更好的解决方案:更少的黑客行为,更少依赖NSTextView的内部机制,所以如果有人有这样的,请分享。

关键步骤是:

1) 在鼠标按下

之前将鼠标向下标志设置为"是",在鼠标按下后设置为 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)];
}

相关内容

  • 没有找到相关文章

最新更新