Good morning,
I’m implementing a floating document inspector for my document-based app, and
am having trouble getting undo/redo working reliably when the inspector is the
key window. Specifically, NSWindowDelegate’s -windowWillReturnUndoManager:
doesn’t seem to be doing the trick like everything else I’ve read on this topic
says it should — at least not reliably. I am developing with Xcode 5.0.2 on
Mavericks 10.9.1, targeting the Mountain Lion 10.8 SDK.
The inspector window is an NSPanel in its own XIB file. File’s Owner is an
NSWindowController subclass, MTInspectorPanelController. The controller is the
panel’s delegate. The controller tracks the current document by KVO observing
mainWindow.windowController.document on NSApp, the same way as is done in the
TextEdit sample app. This all seems to work just fine.
When I realized that my undo/redo menu items weren’t active when the inspector
panel was key, I went in search of a solution and found [NSWindowDelegate
windowWillReturnUndoManager:]. All signs pointed to implementing this function
in the inspector panel controller (the panel’s delegate) to return the undo
manager for the current document, so thats what I did:
- (NSUndoManager *)windowWillReturnUndoManager:(NSWindow *)window
{
if (window == [self window])
{
return [[self inspectedDocument] undoManager];
}
return nil;
}
Unfortunately, this only seems to partially work. There are two issues I’m
running into:
1. The application supports window restoration, and if the inspector panel was
open when the app last quit (and is thus restored when the app runs next) *and*
I have full keyboard access disabled (which causes one of the text fields in
the inspector panel to be first responder when the app launches), then the
undo/redo menu items will never be enabled when the inspector panel is key
(although they work just fine if the main document window is key). On the other
hand, if the inspector panel is closed when the app quits (and is thus not
restored on next run), *or* full keyboard access is enabled (which causes one
of the buttons in the NSSegmentedControl to be first responder in the inspector
panel when the app launches) then the undo/redo menu items will work when the
inspector panel is key (once it is reopened).
I suspect this has something to do with the fact that when the inspector is
being restored on app startup with full keyboard access disabled,
-windowWillReturnUndoManager: gets called on the inspector panel controller
early during window restoration when there is not yet an active document, and
thus the method returns nil. After that, windowWillReturnUndoManager: never
gets called again — not when the inspector becomes key, not when I open the
Edit menu, never. On the other hand, when the inspector panel is not open (and
thus not restored during app startup), or when full keyboard access is enabled,
-windowWillReturnUndoManager: doesn’t get called on the inspector panel
controller during app startup. In fact, it doesn’t get called until I either
open the Edit menu while the inspector panel is key, or one of the text fields
in the inspector panel becomes first responder. At that point all of the
application’s open documents have been fully loaded and the inspector knows
which one is active, so the method has an undo manager to return rather than
nil. It seems that if -windowWillReturnUndoManager: returns nil, then the
method never gets called again.
2. In the case where the inspector was *not* open when the app launches or full
keyboard access is enabled and thus undo/redo is working when the inspector is
key, it sometimes does not correctly switch to the undo manager for the current
document. For example, if I have multiple clean documents open and then make
several undoable edits in one document and then switch to a different (clean)
document and then make the inspector key, occasionally — and this only happens
sometimes and I can’t seem to reliably replicate it — the Edit menu will still
show the Undo/Redo menu items corresponding to the initial dirty document. I
can even execute those menu items and watch the changes take place in the
document window for the dirty document, even though it is not the main window
and the inspector (which is key) is correctly tracking the document whose
window is main. If I make the main (clean) document’s window key, the undo/redo
menu items go back to being disabled (which is correct since there are no
actions on the undo/redo stack for that document). With a log statement in
windowWillReturnUndoManager:, I can see that on the occasions when this
happens, windowWillReturnUndoManager: is not getting called when the Edit menu
is opened, as it usually does.
I’ve verified that both of these behaviors exist on a coworker’s machine as
well, which is running Xcode 5.0.2 on Mountain Lion 10.8.5.
Any clues? Both of these sound like bugs to me, but I’m open to whatever
suggestions for workarounds or troubleshooting anyone may have before I log a
radar.
Thanks!
Matt
_______________________________________________
Cocoa-dev mailing list ([email protected])
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com
This email sent to [email protected]