Legacy Documentclose button

Important: The information in this document is obsolete and should not be used for new development.

Previous Book Contents Book Index Next

Inside Macintosh: Programmer's Guide to MacApp / Part 1 - MacApp Theory and Architecture
Chapter 5 - Events and Commands


Dispatching Events

A MacApp application receives numerous Toolbox events from the operating system, including mouse-up and mouse-down events, key-up and key-down events, disk events, and high-level events. The application object processes Toolbox events by calling its HandleToolboxEvent method, with the following results:

  1. If any enabled behavior objects are attached to the application, each in turn gets a chance to handle the event until one of the objects handles the event.
  2. If no behavior object handles the event, the Standard Mail Package gets a chance to handle the event (if the application object is based on the TMailingApplication class).
  3. If the event still hasn't been handled, it is dispatched by the application object's DispatchEvent method.

The DispatchEvent method calls another application method to dispatch the event. The method it calls depends on the type of event. For example, DispatchEvent calls HandleMouseDown for a mouse-down event, HandleActivateEvent for an activate event, and so on.

The application dispatches events by one of four mechanisms:

These mechanisms are described in the following sections.

Direct Dispatching

The application object handles disk insertion and operating system events directly.

For update and activate events, the application dispatches the event directly to the object that should handle it.

View Hierarchy Dispatching

The application object dispatches mouse-up and mouse-down events in a window's content area to the window's view hierarchy (described on page 207) to be handled by the window or one of its views. The event is dispatched first to the window object. If the window doesn't handle the event itself, it passes the event to its subviews. Typically the event is passed down to the most deeply nested subview that contains the mouse-up or mouse-down event and wishes to respond to it.

Figure 5-2 shows how MacApp handles various mouse-down and key-down events. Dispatching of mouse-down and mouse-up events is described in the following sections. Dispatching of key-down and key-up events uses the target chain dispatching mechanism, described on page 107.

Figure 5-2 How MacApp handles mouse-down and key-down events

Mouse-Down Events

To dispatch a mouse-down event, the application object's DispatchEvent method calls the application's HandleMouseDown method. What happens next depends on the location of the mouse-down event.

For a mouse-down event in the menu bar, the application's HandleMouseDown method calls the Toolbox routine MenuSelect to get a user menu choice, then passes the result to the application's MenuEvent method. If the menu choice is from the Apple menu, MenuEvent attempts to open the chosen item or perform the specified operation. If the menu choice is from an application menu, MenuEvent calls the HandleMenuCommand method of the current target object, passing the chosen menu command number. The operation of HandleMenuCommand is described in "Target Chain Dispatching," beginning on page 107.

For a mouse-down event in a system window, the application's HandleMouseDown method calls the Toolbox routine SystemClick to pass the event on to the system window.

For a mouse-down event in an application window, the application's HandleMouseDown method calls the HandleMouseDown method of the window where the event occurred. What happens next is determined by the location of the event.

To respond to mouse-down events that are part of drawing, selecting, and similar operations, you typically override DoMouseCommand in a view, window, or behavior class. To respond to mouse-down events that initiate drag and drop operations, you override various view methods--see Chapter 9, "Drag and Drop," for a full description.

Mouse-Up Events

To dispatch a mouse-up event, the application object's DispatchEvent method calls the application's HandleMouseUp method. As with mouse-down events, what happens next depends on the location of the mouse-up event, although there are fewer options.

The HandleMouseUp method ignores a mouse-up event in a system window.

For a mouse-up event in an application window, the application object's HandleMouseUp method calls the HandleMouseUp method of the window where the event occurred. This results in execution of the TView::HandleMouseUp method.

The TView::HandleMouseUp method calls HandleMouseUp recursively for each of the window's subviews. A subview can handle the event itself in its DoMouseUp method, or an attached behavior can handle the event in its DoMouseUp method. If no subview or subview behavior handles the event, each behavior attached to the window itself gets a chance to handle the event.

If the event isn't handled by a subview, it may be handled by the window itself if you have overridden the window's DoMouseUp method. If no view or window handles the event, the application's DispatchEvent method calls HandleAlienEvent to handle the event as an alien event.

To respond to mouse-up events, an application typically overrides DoMouseUp in a view, window, or behavior class.

Target Chain Dispatching

There are usually a number of objects in an application that can handle a keystroke or menu event. They include the application object, as well as any document, window, or view objects that are currently active. Each of these objects is accessible through the application object--the application has a list of documents, each document has a list of windows, each window has a list of views, and each view may have a list of subviews (including control views such as buttons).

The target chain is a linked list of event-handler objects that can handle the current event. It typically extends from the frontmost visible object, an active view, all the way to the application. The object at the head of the chain is called the current target object. The current target object is pointed to by the application object's fTarget field, which is accessed through the GetTarget and SetTarget methods. For example, in a window that has multiple views that can handle keystrokes, the currently selected view is normally the target.

Figure 1-5 on page 14 shows a typical target chain. The current target object is a view and the next object in the chain is the view's superview, followed by its window, its document, and the application object. The next handler for the application object is usually NULL.

MacApp handles menu choices and keystrokes by calling a method of the current target object. The target object either handles the event or sends it to the next object in the chain. As part of the process, behavior objects attached to the target object get a chance to handle the event. The process continues until either the event is handled or the end of the target chain is reached.

Behaviors and the Target Chain

MacApp allows behaviors to handle events by wrapping each event-processing method in its own special handling method. For example, the HandleMenuCommand method is a wrapper for the DoMenuCommand method.
(The operation of HandleMenuCommand and DoMenuCommand is described in the
next section.)

MacApp sends an event to the target object by calling one of these handler methods. If the target object has no enabled behavior attached to it, the handler method calls the method of the target object (for example, DoMenuCommand); otherwise, it calls the same method of the first enabled behavior. If the behavior has a next enabled behavior, it passes the method call on to its next behavior; otherwise it calls the same method for its owner, the target object.

In this way, any enabled behavior attached to the target object gets a chance to handle the event before the object itself. If no behavior handles the event, the target object either processes the event itself, or passes it on to the next event handler in the target chain. Figure 5-3 shows this process. Each event-handler object in the target chain may have one or more behavior objects attached to it.

Figure 5-3 Behaviors on the target chain

A behavior object can point to another behavior object with its fNextBehavior field, making it possible to have a linked list of behaviors attached to an event-handler object. Each behavior in the list can be enabled or disabled.

Note
MacApp's use of the HandleMenuCommand method and other event-handling methods is designed to allow behaviors to intervene in the event-handling process. You don't normally override these handling methods.
Behaviors can also handle events that are not dispatched through the target chain. For example, a mouse-down event is dispatched to the window in which it occurs or to a view within that window (page 105). If the window or view has any behavior objects attached to it, they are given the opportunity to handle the mouse-down event in their DoMouseDown methods.

Menu Commands

When a user chooses a menu command, MacApp calls the HandleMenuCommand method of the current target object, passing a value that identifies the chosen command. Figure 5-4 shows how the HandleMenuCommand method gives each object in the target chain a chance to handle the menu command.

The HandleMenuCommand method dispatches the menu command as follows:

  1. It gives each enabled behavior object attached to the current target object a chance to handle the menu command.
  2. If no behavior object handles the menu command, HandleMenuCommand calls the current target object's DoMenuCommand method.
  3. In the TEventHandler class, the DoMenuCommand method calls the HandleMenuCommand method of the next event handler in the target chain, if there is one (see Figure 5-3).
  4. If no object in the chain handles the command, the command is ignored.

You typically handle a menu command by overriding the DoMenuCommand method in an application, document, window, view, or behavior class.

Each event-handler object in the target chain may contain multiple definitions of DoMenuCommand in its class hierarchy. Suppose, for example, the TYourDocument class is a subclass of TFileBasedDocument that overrides the DoMenuCommand method. As shown in Figure 5-5, there are four versions of DoMenuCommand in the object's class hierarchy: one version in TYourDocument, one in TDocument, one in TCommandHandler, and one in TEventHandler.

Figure 5-4 Objects in the target chain responding to a menu command

When MacApp calls DoMenuCommand on an instance of TYourDocument, the TYourDocument version of DoMenuCommand checks to see if it can handle the menu command. If it can't, it calls Inherited::DoMenuCommand. If no inherited DoMenuCommand method handles the menu command, the DoMenuCommand method of the TEventHandler class passes the menu command to the next event-handler object in the target chain, if there is one, by calling the object's HandleMenuCommand method.

Key-Down Events

To dispatch a key-down event, the application object's DispatchEvent method calls the application's HandleKeyDownEvent method.

Figure 5-5 Calling the DoMenuCommand method of a document object

To respond to key-down events, an application typically overrides the DoCommandKeyEvent method or the DoKeyEvent method in an application, document, view, window, or behavior class.

For more information on handling key-down events, see Chapter 20, "Working With the Keyboard."

Receiving Key-Up Events

Because most applications don't need key-up events, your application will never see one unless you change MacApp's default behavior. MacApp uses the fWantKeyUpEvents field of the TApplication class to control access to key-up events. The application's Run method contains code to modify the system event mask based on fWantKeyUpEvents:

if (fWantKeyUpEvents)
   ::SetEventMask(everyEvent); // Allows us to get key-up events too.
The constructor for TApplication sets the fWantKeyUpEvents field to FALSE. If you want to receive key-up events, set fWantKeyUpEvents to TRUE in the constructor for your application subclass.

Dispatching Key-Up Events

To dispatch a key-up event, the application object's DispatchEvent method calls the application's HandleKeyUpEvent method. Since applications are rarely concerned with key-up events, MacApp's mechanism for handling these events is relatively simple. The HandleKeyUpEvent method calls the HandleKeyUp method of the current target object. The HandleKeyUp method in TEventHandler gives each enabled behavior object and each event-handling object in the target chain a chance to handle the key-up event in its DoKeyUp method, until an object handles the event. If no object handles the event, it is ignored.

Several MacApp classes override the DoKeyUp method:

Alien Events

An alien event is one that MacApp doesn't anticipate handling. That includes network events, driver events, null events, and any other events MacApp doesn't recognize, such as events defined by your application.

The application object's DispatchEvent method calls the application's HandleAlienEvent method to handle alien events. The HandleAlienEvent method gives each cohandler in the application's cohandler chain a chance to handle the alien event. Cohandler chains are described in "The Cohandler Chain," beginning on page 134.

Dispatching High-Level Events

For high-level events (those with identifier kHighLevelEvent), the application object's DispatchEvent method calls the application's HandleHighLevelEvent method. The HandleHighLevelEvent method in turn calls the Apple Event Manager routine AEProcessAppleEvent. MacApp uses a global Apple event dispatcher object to handle callbacks from the Apple Event Manager and to communicate with the Object Support Library to determine the object specified by the Apple event.

Dispatching of Apple events is described in detail in Chapter 6, "Scripting."


Previous Book Contents Book Index Next

© Apple Computer, Inc.
25 JUL 1996