12
votes

I have an application which allows for multiple NSDocuments to be open. In this application is a single utility window that contains some functionality that I want to apply to the frontmost document.

I am trying to use bindings here, so the trick is how to cleanly bind the user interface of the utility window to the frontmost document. The goal is that then switching the frontmost document window will update the view in the utility window; controls that are bound to properties of the frontmost document's model would be updated appropriately when state changes in the document's model, etc.

For sending actions from such a window, it's easy to just use first responder; the document object can intercept actions via the responder chain. But I want more than this, and of course you can't bind to the first responder.

A few ideas that I have:

  • put an object controller in my nib for the shared window. When a document window changes frontmost status, change the content of that binding. A disadvantage of this is that if I were to have another kind of utility window, I'd have to remember to hook up the bindings from the document window to that utility window too!
  • Make an accessor in the application delegate that gets the frontmost document window by traversing the window list. My utility window would just bind through the application delegate's method. A disadvantage here is that it's not KVO compliant
  • Have a getter and setter in the application delegate to determine (and perhaps set to be KVO-compliant? would that make sense?) the frontmost document. Perhaps use window notifications set an ivar to the appropriate value when a window loses main status. Update: I'm using this for now, and it actually seems pretty clean. I set the value from the windowDidBecomeMain notification of my doc window and clear it (if it's the current value) in windowWillClose. Unless there is any major objection, this is probably the approach I'll use.
  • One idea was to bind to mainWindow.windowController.document ... this comes close, except that when my shared window becomes main, then this binding goes away. So really I need to find the frontmost document window's controller (and of the right class).

None of these seem quite right. Is there a better way to do this that I'm missing?

5

5 Answers

4
votes

I’ve always bound through Shared Application, mainWindow.document, which works fine. if you have windows w/o documents, you may want to add a mainYourKindOfWindow key that is implemented by watching mainWindow and updating the value based on some filter criteria.

3
votes

Leopard's TextEdit does this for its inspector. Check it out in file:///Developer/Examples/AppKit/TextEdit.

0
votes
  • put an object controller in my nib for the shared window. When a document window changes frontmost status, change the content of that binding.

That makes the most sense to me. You'd change the content to the document instance ([NSDocumentController currentDocument]).

A disadvantage of this is that if I were to have another kind of utility window, I'd have to remember to hook up the bindings from the document window to that utility window too!

Huh? I don't understand this.

0
votes

Leopard's TextEdit does this for its inspector. Check it out in >file:///Developer/Examples/AppKit/TextEdit.

In TextEdit, inspector values are bound via an intermediate object controller. The controller content object is bound to the shared application mainWindow.

You may bind the content to mainWindow.firstResponder and uncheck "Raises for not applicable keys".

0
votes

Use the key window, not the main window. KVO might not be supported for NSApplication's keyWindow property, but you can still use NSNotifications if it doesn't work. The reason for this is that NSDocumentController's currentDocument uses the keyWindow, so it better represents the built in functionality. Also, panels can be set to avoid becoming key window.