views:

382

answers:

5

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?

A: 

This is idle thinking aloud and I haven't tested it, but when the frontmost document changes, this changes the orderedDocuments collection. Does that send out change notifications?

Graham Lee
+3  A: 

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.

Ben Stiglitz
The problem is that when the utility window is main. I want the frontmost document window under the utility window.
danwood
In that case, you can’t use this or Peter’s suggestion of watching the -[NSDocumentController currentDocument]. Observe your app’s main window and set some NSApplication property, excepting the case where your utility window becomes front.
Ben Stiglitz
That being said, is there any reason you don’t use an NSPanel here?
Ben Stiglitz
A: 
  • 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.

Peter Hosey
To clarify : if I added *another* shared window, much like the one I'm working with, then I would need to set up another binding in the document to that new window too. It just seems to add a layer of complexity.
danwood
Why do you need a binding in the document to the utility window? What does the document need to talk to the utility window for?
Peter Hosey
+2  A: 

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

Ken
A: 

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".