tags:

views:

59

answers:

1

I'm trying to implement a view controller for a custom NSOpenGLView based view (this is Cocoa, not Cocoa Touch).

The view is contained within a NIB loaded window but it does not have its own NIB. In fact the window contains multiple instances of the view.

I want to route mouse events to the controller instead of to the view. I would like for this to happen as soon as the user clicks within the corresponding view.

So how can this be done ?

I've tried having the view's becomeFirstResponder method call makeFirstResponder with the controller as argument. However that doesn't seem to work, the view still receives the mouse events instead of the controller if NSView::becomeFirstResponder returns YES. If it returns NO then neither of my classes receive the mouse events.

Of course I could implement the mouse event handling methods in the view and explicitly forward them to the controller but it seems like there should be a better way to handle this.

+1  A: 

For general "first responder" status, I recommend Charles Parnot's MTViewController, an NSViewController subclass that uses KVO to make certain the controller is in the responder chain with no extra effort on your part.

However, in your case, you want mouse events too. There's really no way around this - your view will need to translate mouse events into controller interactions.

Joshua Nozzi
OK, I was hoping Cocoa provided a mechanism to get events to a controller.
tgflynn
You mean like the target/action pattern or the delegate pattern?
Joshua Nozzi
Well I was thinking more of plain MVC where the controller is supposed to handle user interaction. To do that it needs to get UI events somehow. I'm pretty new to Cocoa so I guess I was thinking the event handling architecture was more flexible than it is. It seems like makeFirstResponder could do the trick if there were a way to have it called at the right moment (ie. not embedded in somebody else's call to the same method).
tgflynn
Views handle mouse events. Consider a button: it takes a target and an action (a selector). Typically the target is an instance of some controller and the action is a selector of that controller. Your view should behave in much the same way.
Joshua Nozzi
That clearly makes sense for a simple UI element like a button whose only role is to receive and pass on user events but if you think of a view that's implementing something complex (like say a CAD model viewer) it seems like it might make sense to separate the display logic (view) from the user interaction logic (controller).
tgflynn
Not for mouse events in Cocoa. Your view (NSResponder->NSView->( NSControl or some other subclass)) translates the mouse interaction into discreet user actions that are sent to the controller, in addition to displaying the current state. For a more complex example, consider NSTableView's use of a data protocol. Consider also the Sketch example project from Apple.
Joshua Nozzi
"In a typical Cocoa MVC design, when users enter a value or indicate a choice through a view object, that value or choice is communicated to a controller object. The controller object might interpret the user input in some application-specific way..." from http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaDesignPatterns/CocoaDesignPatterns.html
Joshua Nozzi