Tools proposal
==============

 - 2009-06-15

Tools are used to handle user actions, like moving a mouse pointer over the
screen and clicking on items in the canvas.

Tools are registered on the View. They have some internal state (e.g. when and
where a mouse button was pressed). Therefore tools can not be reused by
different views.

---- Thoughts - 2009-09-21 ----
What this may boil down to is that the events that can happen on an item need
to be defined.

Those are:
 - grabbed (button press on item)
    * handle is grabbed (let item figure this out ;).
    * center of line segment is grabbed (will cause segment to split)
 - ungrabbed (button release)
 - move (item is moved -> hover + grabbed)
 - item is hovered over
    * item is hovered over while another item is being moved
    * item is hovered over while dragging something else (DnD)
 - key is pressed
 - key is released
 - modifier is pressed (e.g. may cause mouse pointer to change, giving a hit
   about what a grab event will do.

The idea behind this is that we can define specific roles to the items,
depending on the role (state) we provide them with.

This may reduce the number of tools to at most a few: all logic is implemented
in the roles.

An approach described previously scatters the behaviour over a whole bunch of
tools. In this approach more fine grained tooling was proposed.

It's more important to separate the _What_ and the _How_.

The _What_ needs to be decided in a tool. Based on this the _How_ logic can be
applied to the item at hand. For example: if an item is clicked, it should mark
*itself* as the focused item. Same for dragging: if an item is dragged it should
update itself based on the event information. It may even apply this to all
other selected items.

This means that the number of tools may even be reduced. On the counter side,
it may very well be possible that programmers have to write their own tooling.

The advantage is that more complex behaviour can be composed. Since the
decision on what should happen is done in the tool, the Role which is then
given to the item ensures a certain behaviour is performed.

If this is done elegntly, those roles should be easely usable from the model
layer as well. This will (for example) fix the issues with handle connection
(for which a handle tool is needed).

For a start the following tools will be implemented:

1. Item tool (comprises old Hover, Item, Handle, connect and line segment tool)

2. Placement tool - For item placement

3. RubberbandTool - for rubberband selection

4. Pan tool - scroll the canvas over the screen

5. Zoom tool - deal with zoom-in/out events (key press)

6. ToolChain - The tool chain

Only the first tool will drastically change. The Item tool does some ``if ...
else ...`` logic and applies a Role to a certain item. This role will be used
to perform the actions required.

Also the Placement Tool no longer invokes a HandleTool. It will just apply
the required role to the item and get it executed.

The sequence of press-move-release should be considered an "atomic" action. No
explicit grabbing is required on this one. If a tool handles a press event, it
automatically receives all following move events and the release event.


Big changes from Gaphas 0.4 tool include:

 * Tools can contain state and should be used for one view only.
 * Grabbing is done automatically for press-move-release event sequence.
 * The _What_ is separated from the _How_, leaving less tools and less
   overhead (like finding the item under the mouse pointer).



Handle tool
-----------

Button press:
  for every item at pointer position:
    find a handle
    if a handle is found:
      select the item (focus) and the handle
      if constraints attached:
        disconnect constraints
      
Move the handle:
  change position
  find a port to glue to
  if port found:
    change position to port position

Button release:
  ungrab handle
  find port to glue to
  if port found:
    change position to port position
    if previously connected and new port is of another item:
      disconnect from previous item completely
    connect to port

