通过适当的撤消管理创建持续更新的自定义控件

时间:2011-05-06 15:14:52

标签: objective-c cocoa cocoa-bindings nsundomanager

我正在整理一个自定义NSView,它通过绑定处理两个值。我正在Tom Dalling在问题Can you manually implement Cocoa bindings?中概述的更新时传播这些值。一切正常。

为了使控件不断更新,我更新并传播了-mouseDragged方法中的值。再次,这工作正常,但它将中间步骤注册到NSUndoManager,我不想要。因此,我尝试在disableUndoRegistration中发布-mouseDown,然后在enableUndoRegistration中发布mouseUp。当然,我会再次更新并传播结果。

根本没有注册撤消,我意识到这是因为如果值不变,我的set函数不会注册撤消:

- (void)setX:(double)newX {
    if (newX != x) {
        [[undoManager prepareWithInvocationTarget:self] setX:x];
        [self willChangeValueForKey:@"x"];
        x = newX;
        [self didChangeValueForKey:@"x"];
    }
}

由于-mouseDragged已经传播了该值,因此在-mouseUp中再次发送时它没有更改,因此从未记录撤消。我当然希望它撤消到初始-mouseDown之前的位置,所以让我说我通过将该值存储在控件中然后在-mouseUp中再次发送该值来执行此操作新的价值。当然,这仍然存在一个问题,即我可以看到它恢复到原来的价值。

我可以通过检查撤消管理器是否已启用并跟踪旧值来在-setX:方法中解决此问题。但是,我应该能够在控件内完成此操作,因为有控件具有这种确切的行为(就像NSSlider设置为连续)。

谢谢!

1 个答案:

答案 0 :(得分:2)

您不能只使用beginUndoGroupingendUndoGrouping吗?


P.S。如果你好奇Cocoa类是如何在内部工作的,那么检查GNUstep实现有时会有所帮助(NSUndoManager在GNUstep Base中,像NSS​​liderCell这样的AppKit类在GNUstep GUI中):

http://wwwmain.gnustep.org/resources/downloads.php?site=http%3A%2F%2Fftpmain.gnustep.org%2Fpub%2Fgnustep%2F#core