[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8. Event handling

The way events are handled and passed between objects in GNUstep requires special treatment. It is relatively simple, but generally not well documented as to how it works, and how it is used by default in GNUstep. Before reading this chapter, you may wish to reaquaint yourself with views (see The view concept).

Event handling can be very complex, or very simple, depending on what your trying to handle and to what extent you’re using customised components. We will try to cover some of the basic concepts you may come across in this manual, as well as give a better guide to working with NSResponder and NSEvent.

We start with the target/action paridigm (which is used to implement outlets/actions in interface files), and then explain the AppKit’s underlying event handling model, which is far more powerful and of interest if you are implementing your own views. It’s also relevant to understanding how events are passed around in GNUstep (and a recommended read).


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.1 The Responder Chain

A responder is an object inheriting from NSResponder. It defines methods that are overrided by subclasses for receiving events, from simple things such as mouse clicks and keyboard presses, to more abstract events such as text selection or text modification. NSView inherits from NSResponder (and in turn NSControl inherits from NSView) so in effect, all views and controls can respond to events.

Responders are linked together in a chain, whereby a top-level graphical element (usually a window) receives an event, and if it doesn’t understand it, it passes it on to higher-level graphical elements, namely views. As views can be placed inside each other, a low-level superview may pass on higher-level events to it’s more abstract children. The responder chain is the programmatic linkage between different objects. It is usually setup by GNUstep, but can be modified by the programmer.

The object at the top of the focus stack in a window is usually the first responder, meaning that any events will be forwarded to it first, and then along the chain if necessary. You can retrieve the first responder in a window by calling -firstResponder against the NSWindow object.(11).

More than responder chain may exist, but only one may be active at a time. It is called a chain, due to the way event messages are passed through successive calls to each consecutive object in the chain.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.2 Being a responder

A responder inherits the NSResponder class. As NSView inherits from this, all high-level graphical elements, including all controls and views are considered to be "responders". This class contains a number of methods for maintaining the the responder chain and default methods for handling certain types of events, such as keyboard, mouse and "text" events (for text-processing classes such as NSText).

The first method to override is -acceptsFirstResponder, which returns a boolean indicating whether your class will accept first responder status. You can also override -becomeFirstResponder and -resignFirstResponder to be notified of when your class gains and loses the first responder status (respectively).

The next thing to do is override the different event messages that are predefined in NSResponder, such as -keyDown:, -mouseDragged:, -helpRequested:, etc. What all these have in common is that they take a single NSEvent object argument, which contains information about the event.

Action messages are messages that have a predefined syntax i.e. they take one object as a parameter, but the name of the method that implements them defines the message. These are passed along the responder chain until a responder implementing that action message is found. This is aided via the -tryToPerform:with: method, which is used by GNUstep to traverse the responder chain and find an object that can perform the anAction selector with anObject as a parameter.

Some of the common ones include:

You can also pass your own custom selectors along responder chains, trying to find the first object that responds to a particular method name. Given an object and a selector, call -tryToPerform:with: on an object in the responder chain, and this method will be tried on each successive responder until one can be found that responds to the selector. If a method cannot be method, it returns NO.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

8.3 Target/Action Paridgm

Controls use the target/action paridgm for simple events, which only have a sender and a target.(12) The target object is the object notified of an event. It is like a sink in OLE/COM programming and is referred to as the receiver. The action is an event being performed, and takes the form of a selector. The sender is the object generating the action. An action is passed along the responder chain until it is processed or until the end of the responder chain is reached, in which case the message is returned to the sender indicating it couldn’t be processed. Messages that are passed as such events are known as action messages, and these events are known as action events.

Let us explain with a simple example. We create a button on a form as an NSButton that we want to inform our AppController object instance when it is clicked. The button object is the sender and the AppController object is the target. We tell the button object to call our target object using the selector -browseForServer:.(13) This selector is the action.

Many of these actions are predefined in the NSResponder class which is implemented by all views.

On the other hand, things such as menu items define a number of custom such as -save: or -print:, which many, but not all AppKit classes respond to. You can define your own actions for things such as menu buttons.

Using the above example of a target, sender (which we will call myButton) and action, we could manually setup a link between the objects as follows:

 
AppController* appCont;
NSButton* myButton;

// Initialisation of button and target objects

[myButton setAction:@selector(browserForServer:)];
[myButton setTarget:appCont];

In the above example, whenever myButton is clicked, it will call the invoke: method on the MyButtonTarget instance. What you see above is what Gorm.app does when you connect an action and a target.

This paradigm is used for simple event handling in classes that derive from NSControl. See see Basic Controls and see Interface Files for more information as to how this fits together.


[ << ] [ >> ]           [Top] [Contents] [Index] [ ? ]

This document was generated by Adam Fedor on December 24, 2013 using texi2html 1.82.