NSTextView撤销/重做属性更改(当不是第一响应者时)



我正在构建一个具有自定义控件的基本文本编辑器。对于我的文本对齐控件,我需要覆盖两个用户场景:

  1. 文本视图是第一响应者-将段落属性更改为textView.rangesForUserParagraphAttributeChange

  2. 文本视图不是第一个响应器-将段落属性更改为全文范围

方法:

- (IBAction)changedTextAlignment:(NSSegmentedControl *)sender
{
    NSTextAlignment align;
    // ....
    NSRange fullRange = NSMakeRange(0, self.textView.textStorage.length);
    NSArray *changeRanges = [self.textView rangesForUserParagraphAttributeChange];
    if (![self.mainWindow.firstResponder isEqual:self.textView])
    {
        changeRanges = @[[NSValue valueWithRange:fullRange]];
    }
    [self.textView shouldChangeTextInRanges:changeRanges replacementStrings:nil];
    [self.textView.textStorage beginEditing];
    for (NSValue *r in changeRanges)
    {
        @try {
            NSDictionary *attrs = [self.textView.textStorage attributesAtIndex:r.rangeValue.location effectiveRange:NULL];
            NSMutableParagraphStyle *pStyle =  [attrs[NSParagraphStyleAttributeName] mutableCopy];
            if (!pStyle)
                pStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
            [pStyle setAlignment:align];
            [self.textView.textStorage addAttributes:@{NSParagraphStyleAttributeName: pStyle}
                                             range:r.rangeValue];
        }
        @catch (NSException *exception) {
            NSLog(@"%@", exception);
        }
    }
    [self.textView.textStorage endEditing];
    [self.textView didChangeText];
    // ....
    NSMutableDictionary *typingAttrs = [self.textView.typingAttributes mutableCopy];
    NSMutableParagraphStyle *pStyle =  typingAttrs[NSParagraphStyleAttributeName];
    if (!pStyle)
        pStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
    [pStyle setAlignment:align];
    [typingAttrs setObject:NSParagraphStyleAttributeName forKey:pStyle];
    self.textView.typingAttributes = typingAttrs;
}

所以这两种情况都很好…但是,当更改应用于"非第一响应者"场景时,撤销/重做不起作用。撤消管理器将某些东西推到其堆栈上(即撤消在编辑菜单中可用),但调用撤消不会改变文本。它所做的只是选择全文范围。

我如何适当地改变文本视图属性,使撤消/重做工作,无论视图是否是第一响应者?

提前感谢!

我不确定,但我有两个建议。首先,检查shouldChangeTextInRanges:...的返回值,因为可能文本系统拒绝了您提出的更改;无论如何,这是个好主意。第二,我会尽量让非第一反应者的情况更像第一反应者的情况以便让它起作用;特别是,您可以从选择整个范围开始,因此rangesForUserParagraphAttributeChange实际上是您更改属性的范围。在这个方向上的进一步步骤是,在你改变的持续时间内,让textview成为第一响应者。在这种情况下,我认为这两种情况应该是相同的。您可以在完成后立即恢复第一响应者。不是最优的,但似乎AppKit在幕后做了一些假设,你可能只需要工作。这是我所能提供的最好的方法,而不是试图重现这个问题。

问题是我在之后更新typingAttributes的代码中出现的错字。看这里:

//...
NSMutableParagraphStyle *pStyle =  typingAttrs[NSParagraphStyleAttributeName];
// ...

哎!需要真正可变…

//...
NSMutableParagraphStyle *pStyle =  [typingAttrs[NSParagraphStyleAttributeName] mutableCopy];
// ...

相关内容

  • 没有找到相关文章

最新更新