Dragging Cables with the State Pattern

The custom interaction mode plugin is rather complex because the behavior of the plugin changes as the user moves from one interaction step to another. The state pattern is a behavioral design pattern that removes the complexity from the plugin code and distributes it over state objects.

The interaction mode plugin acts like a finite state machine. These are the states the plugin can be in:
  1. It starts with the initial state.
  2. As soon as the mouse moves the state become “Moving Empty” where the plugin will be scanning for a cable near.
  3. When a cable is found the state becomes “Moving”.
    1. When the user moves away from a cable, the state revert to “Moving Empty”.
  4. When the user presses down the mouse, the state moves to Start Drag.
  5. When the user moves the mouse while pressing down the mouse button the state moves to Dragging.
  6. When the use releases the mouse the state becomes End Drag and the cable is transformed.
  7. The state then moves to the initial state again.

If at any moment the interaction is aborted the state moves to the initial state.

The design is like this:


The event handler method now looks like this:

_pragma(classify_level=basic, topic={demo})
_method custom_interaction_mode_plugin.handle_drag_action(action,start_coord,
    ## the master method that is invoked on every event once the
    ## the mode has started. Return :event_handled to indicate that
    ## that no other modes need to do anything anymore.
    _local meth << write_string("handle_", action, "_action()").as_symbol()
    .state << .state.perform(meth, action, start_coord, end_coord, a_window)
    _if .state.handled?
        _return :event_handled
        _return _unset 

The action is send to the state object. The state object will execute its action and return either the next state in the transition or itself again if it is not finished yet. The plugin is now a lean object with little sourcecode. The state object will each handle their small part of the interaction.
The sourcecode is attached here. Enjoy!
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License