2015-10-13 52 views
1

我建设有自定义控件一个基本的文本编辑器。对于我的文字对齐控制,我需要支付两个用户场景: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; 

} 

所以这两种情况下正常工作......但撤销/重做时的变化在“不先响应”方案应用于不起作用。撤销管理器将某些东西压入堆栈(即在编辑菜单中可以使用撤消),但调用撤消不会改变文本。它所做的只是显示全文的范围。

如何适当地改变文本视图属性,以便撤销/重做的作品,无论视图是否是第一reponder与否?

预先感谢您!

回答

0

我不知道,但我有两个建议。一,检查shouldChangeTextInRanges:...的返回值,因为文本系统可能拒绝你提出的改变;无论如何,这是一个好主意。第二,我试图让非首先响应者的案例更像第一响应者案例,以试图使其起作用;特别是,你可能会选择全范围开始,这样rangesForUserParagraphAttributeChange是那么实际上你改变属性的范围内。在这个方向上的另一个步骤是在改变的过程中实际上使textview成为第一响应者。在这种情况下,我认为这两种情况应该完全相同。完成后,您可以立即恢复第一个响应者。不是最优的,但AppKit似乎在幕后做了一些假设,你可能只需要解决。没有试图重现问题,并与它一起玩,这是最好的,我可以提供...

+1

谢谢@bhaller。我尝试了你的建议,但结果相同。最终,这似乎是在之后改变'typingAttributes'的对齐方式的问题(请参阅我的答案)。真的很感谢你的见解! –

+0

有趣。键入属性 - 我没有看到即将到来的。 : - > – bhaller

+0

Lolz,我刚刚发现它是我的代码中的一个错字。不是bug! –

0

问题是我的代码中的错字,更新typingAttributes事后。看这里:

//... 

NSMutableParagraphStyle *pStyle = typingAttrs[NSParagraphStyleAttributeName]; 

// ... 

Doh!需要真正可变...

//... 

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

// ...