(AppKit) NSTextBlock 内的 Tab 插入

2024-06-22

我正在使用 AppKit 为 macOS 开发一个 Markdown 编辑器,并且已经掌握了所有基础知识并可以正常工作。我在用着NS文本块 https://developer.apple.com/documentation/appkit/nstextblock对于代码块。

然而,我遇到的一个问题是,在 NSTextBlock 内键入制表符会导致插入符号向下移动到下一段,而不是插入制表符空白。期望的结果是用户能够在 NSTextBlock 内插入选项卡。

我创建了一个示例项目来演示这种行为GitHub https://github.com/MQumairi/SimpleEditorForTabBug/tree/main/SimpleEditor.

要快速浏览示例项目:

这是一个简单的 AppKit 应用程序。我已将可编辑、可滚动文本视图添加到 Main.storyboard 中的默认 ViewController。 textView 通过 IBOutlet 连接到 ViewController 类。

在自动生成的 viewDidLoad() 方法内部,我调用insertText函数,我编写该函数的目的是在 NSTextView 中插入一行文本,后跟两个使用 NSTextBlocks 样式的段落。

  func insertText(textStorage: NSTextStorage) {

    //Insert first line of regular text
    var attributes: [NSAttributedString.Key: Any] = [
        .font: NSFont.systemFont(ofSize: 24),
        .foregroundColor: NSColor.textColor,
        .backgroundColor: NSColor.clear
    ]
    let attributedString1: NSAttributedString = NSAttributedString(string: "Test\n", attributes: attributes)
    textStorage.append(attributedString1)
    
    //Insert the blue block holdig text
    attributes[.foregroundColor] = NSColor.white
    attributes[.paragraphStyle] = ParagraphStyle(bgColor: NSColor.systemBlue).paragraphStyle
    let attributedBlock1 = NSAttributedString(string: "Hello, I'm the blue block\n", attributes: attributes)
    textStorage.append(attributedBlock1)

    //Insert the pink block holdig text
    attributes[.foregroundColor] = NSColor.black
    attributes[.paragraphStyle] = ParagraphStyle(bgColor: NSColor.systemPink).paragraphStyle
    let attributedBlock2 = NSAttributedString(string: "Hello, I'm the pink block\n", attributes: attributes)
    textStorage.append(attributedBlock2)
}

这样做的效果是:

如果您启动应用程序并尝试在脱字号位于第一段开头时插入制表符,则制表符空白将按预期添加到该段落的开头。但是,如果您尝试对使用 NSTextBlocks 样式的段落执行相同的操作,插入符号只会向下移动到下一个段落,并且不会插入制表符空白。

我为示例项目编写的另外两个类是 ParagraphStyle 和 CustomTextBlock。

For the ParagraphStyle类,保存用于蓝色和粉色块的属性的段落样式:

class ParagraphStyle {

let bgColor: NSColor
let paragraphStyle: NSParagraphStyle

init(bgColor: NSColor) {
    self.bgColor = bgColor
    //Set paragraph style
    self.paragraphStyle = {
        let mutableParagraphStyle = NSMutableParagraphStyle()
        let specialBlock = CustomTextBlock(bgColor: bgColor)
        mutableParagraphStyle.textBlocks.append(specialBlock)
        let style = mutableParagraphStyle as NSParagraphStyle
        return style
    }()
}}

For the CustomTextBlock类,继承自NSTextBlock,我定义块的颜色和尺寸:

class CustomTextBlock: NSTextBlock {
        
init(bgColor: NSColor) {
    super.init()
    //Control the BG color of the text block
    self.backgroundColor = bgColor
    //Control dimensions of the text block
    self.setValue(100, type: NSTextBlock.ValueType.percentageValueType, for: NSTextBlock.Dimension.width)
    self.setValue(50, type: NSTextBlock.ValueType.absoluteValueType, for: NSTextBlock.Dimension.minimumHeight)
}

required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}}

我尝试过的

  1. Adding NSTextTabs https://developer.apple.com/documentation/uikit/nstexttab to the .tabStops https://developer.apple.com/documentation/uikit/nsmutableparagraphstyle/1531988-tabstops初始化段落样式属性值时的数组ParagraphStyle class.
  2. 通过添加 NSTextTab添加制表位 https://developer.apple.com/documentation/uikit/nsmutableparagraphstyle/1525051-addtabstop method.
  3. 将值设置为默认制表符间隔 https://developer.apple.com/documentation/uikit/nsmutableparagraphstyle/1529861-defaulttabinterval
  4. 设置textView的nextKeyView and nextResponder to nil.

剩下的唯一一件事(我能想到的)是当文本视图是第一响应者时监听用户按下 Tab 键。当事件发生时,我会以编程方式在用户插入符所在的位置插入制表符空白,然后以编程方式将插入符移回其应在的位置。然而,这是解决这个看似简单问题的极其迂回的方法,这就是为什么我相信我可能错过了一些明显的东西。希望这里更有经验的开发人员能够提出其他建议!

先感谢您!


显然,文本块中的选项卡会将插入点移动到下一个文本块,这在表格中是有意义的。解决方法:子类化NSTextView, 覆盖insertTab并插入一个选项卡。

override func insertTab(_ sender: Any?) {
    insertText("\t", replacementRange: selectedRange())
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

(AppKit) NSTextBlock 内的 Tab 插入 的相关文章

随机推荐