MouseInteractors

MouseInteractors is a sample program that illustrates how to use TInteractors with mouseevents. It introduces a sample interactor TPolygonInteractor and a sample view TGraphicView. The interactor is used to draw a polygon in the view. It stops when the mouse is double-clicked, or the mousedown is outside the view. In the first case the polygon is closed; in the second case the polygon is erased.

An interactor is needed here because the view only receives mouse-down events when the mouse is clicked in the view, and you want to know when the mouse is clicked outside the view so that you can stop the polygon.

This example is for illustration only. You might want to use the Tools framework or similar interactors provided by GrafEdit to accomplish this functionality in a real program.

The KeyInteractors sample also illustrates use of interactors, except with key events.

Running the sample

Execute MouseInteractorsSApp. Click the mouse in the view to start the interactor. Each time you click in the view, another point is added to the polygon. When you double-click in the view, the polygon is closed and the interactor will complete. If you click outside the view, the interactor terminates and immediately resumes normal event dispatching (so, for instance, a drag in the window's title bar is processed normally). Click Close to quit.

Files and classes

TGraphicView is defined in GraphicView.h and GraphicView.C. It is basically the same as TMouseInputView in MouseEventsInViews, except that it overrides MouseButtonDown to create and start the TPolygonInteractor. It also provides AdoptGraphic and Add/RemoveInteractor protocol for the interactor to use. The view maintains a reference to the interactor so it can pass activate and deactivate events to the interactor. See under "Notes" below for more details.

TPolygonInteractor is defined in PolygonInteractor.h and PolygonInteractor.C. It derives from TInteractor for interactor protocol, and MMouseEventHandler so that it can handle events. It calls SetCoordinateView in its constructor so that events are sent to it in that view's coordinate system. As it receives mouse down events, it adds points to the list of points it maintains, and then creates a graphic from this list, which the view then adopts and displays.

Notes:

The interactor will be told when the mouse is clicked in any view sharing the same event receiver, but not when the mouse is clicked elsewhere. This means if you want to stop the interactor when the mouse is clicked in a different application window (which you do), some other mechanism must be used. Clicking the mouse in a different window causes that window to activate, and yours to deactivate. Views in your window will have HandleDeactivate called on them, and thus have an opportunity to stop the interactor.

This means, however, that your view must keep a reference to the interactor while the interactor exists, in order to inform it when the view activates and deactivates. In this example, the interactor maintains this reference, calling the methods AddInteractor and RemoveInteractor to set your view's reference to the interactor when it is created, and clear your view's reference to it when it is destroyed. Your view overrides HandleDeactivate to stop the interactor when there is one. This is essentially the same mechanism used in KeyInteractors.

It is not sufficient for HandleDeactivate to merely deactivate the interactor. This would cause it to stop dispatching events to itself, but also block the device from dispatching events to the view. Instead, you call SetDone(TRUE) on the interactor, and the next time the device tries to send the event to the interactor, it will delete it and then dispatch the event normally, which is what you want.

When the mouse is clicked in any view that does share the same event receiver, the interactor is called. The window itself is one such view, so the interactor can be called when the mouse is clicked in the title bar. To allow the window to handle this click, the interactor must 1) call SetDone(true) to tell the device it is finished and must be deleted, and 2) return false from MouseButtonDown to tell the device to continue dispatching the event. The window then receives the event and handles it as usual.


Click the icon to mail questions or corrections about this material to Taligent personnel.
Copyright©1995 Taligent,Inc. All rights reserved.