Features Help Download

Lomse Hacking Guide

4.2. Task objects

4.2.1. Interactors and Tasks

Lomse uses the ‘taskmaster’ architecture, described in [1]. In this architecture, to decide on the appropriate action, the Interactor delegates on a Task that is chosen by using the State pattern: The Task is an abstract object and the real object receiving the user event depends on the Interactor‘s state. Each derivative of Task encapsulates an interaction with the user and eventually communicates with the document. The appropriate derivative of Task is selected by a menu command or click on a palette item, etc.

All Task derivatives are finite state machines. The events that drive the finite state machine are the mouse and keyboard events that are delegated by the Interactor to the Task. Indeed, the Task class consists of little more than a set of pure virtual functions representing these events.

The Task responsibility is to decide on the appropriate action for an event or sequence of events.

4.2.2. Task switching

A tasks will be associated with a View as a result of invoking method Interactor::select_task(). The user application must invoke this method as a result of some kind of user action; perhaps a menu choice, a keyboard shortcut, or a click in the appropriate button of a palette or toolbar.

Once associated with the view, the task will continue to collect events and communicate with the Document class until its lifecycle ends. This may be as a result of completing its job, or because it was somehow cancelled. Then another task will replace it.

Thus, the current task within a View represents the global state of that View. It defines how the View will react to events.

In order to implement this, a suite of other interfaces are required within Task. These interfaces provide for task cancellation, task restart, backstepping, pausing, etc.

When a View object is created, its associated Interactor will be initialized with an instace o class SelectionTask.

4.2.3. Task isolation

Each task is isolated from the associated view and document classes. The tasks can be changed without affecting any other part of the system. Indeed, the interactions can be reused in other applications that have different document and view classes. Also the document and view classes can be reused in systems that have different interactions.

4.2.4. Task model and operation

All Task are finite state machines. The events that drive the finite state machine are the mouse and keyboard events that are delegated by the Interactor to the Task. Indeed, the Task class consists of little more than a set of pure virtual functions representing these events. To implement the finite state machine representing a task I prefer to use nested switch-case statements. This type of implementation is more compact and it is easy to understand and follow the finite state machine without relying on state transition diagrams or tables.

The operation of this state machine is quite simple. When the task is associated with the view, its method ini_task() is invoked and it places the task in its initial state and kicks everything off. When, finally, it arrives to the ‘Done’ state, it remains there forever unless the task is re-started (by invoking init_task again).

In following transition tables:

  • The initial state is always the first one in table.
  • Events that do no change current state and do not trigger any action are not listed in the tables.

4.2.4.1. TaskDragView class

Purpose:
To move (scroll, drag) the view
State Transition Table:
The task is defined by the following trasition table:
Current State Event Next State Action
WaitingForFirstPoint left_down WaitingForSecondPoint start_scroll
WaitingForSecondPoint move_mouse WaitingForSecondPoint do_scroll
left_up WaitingForFirstPoint end_scroll
Remarks:
If start point is equal to end point, user just clicked on a point. In this case a “select object” action could be issued, for more flexibility. [Not implemented]

4.2.4.2. TaskSelection class

Purpose:
To select objects. Default task when no specific user action. User can move mouse, select objects and click on them. Left click on one object generates on-click event. Right click, shows contextual menu. Track rectagle with left button select objects. And Track rectagle with right button does nothing.
State Transition Table:
The task is defined by the following trasition table:
Current State Event Next State Action
WaitingForFirstPoint left_down WaitingForPoint2Left record_first_point
right_down WaitingForPoint2Right record_first_point
move_mouse WaitingForFirstPoint mouse_in_out
WaitingForPoint2Left move_mouse WaitingForPoint2Left track_sel_rectangle
left_up WaitingForFirstPoint select_objects_or_click
WaitingForPoint2Right right_up WaitingForFirstPoint select_object_at_first_point, show_contextual_menu
Remarks:
Note that the action of selecting an object by single click on it is implemented by right click. Left click does not select the object but sends an on-click event.

4.2.5. References

[1]“TASKMASTER: An Architecture Pattern for GUI Applications”, Robert C. Martin, James W. Newkirk & Bhama Rao. Available at http://www.objectmentor.com/resources/articles/taskmast.pdf