ikeough/Dynamo — pull request #531 by Benglin (2013-10-02 08:57:31+00:00)
Title: Implement WorkspaceViewModel.StateMachine

#### Background
This work is about the introduction of a StateMachine class to unify certain operations in workspace. Operations such as windows selection, node dragging and connector creation are ideal candidates that can be folded into a state machine.

One of the main goal of the state machine is to allow more centralized place for command recording, something that is very valuable for the proposed command framework. As it is today, these operations scattered around different objects (both views and view-models), when command recording is done only in WorkspaceViewModel.

The logical step is then to fold these operations into "WorkspaceViewModel.StateMachine" object, having them work more closely (and uniformly) with the command recording mechanism.

Relevant task: http://adsk-oss.myjetbrains.com/youtrack/issue/MAGN-133

#### Changes
- Implemented a private nested class "WorkspaceViewModel.StateMachine"
- Folded node dragging, window selection and connector creation logic into StateMachine
- Node dragging logic has been simplified
- Mouse handling responsibility of DragCanvas have been moved into StateMachine
- OffsetData has been made obsolete as node dragging is decoupled from selection set
- The notion of "active connector" (when connection is being made) is moved out of WorkspaceViewModel
- Unused methods (e.g. ElementClicked, MyHitTestResult, HasParentType) have been removed

#### Unit testing

All existing test cases passed: DynamoPythonTests, DynamoCoreTests, DSCoreNodesTests and DynamoCoreUITests.

Test case is written for a new data class "DraggedNode", but not StateMachine. StateMachine works with the WorkspaceViewModel it belongs, taking inputs from mouse handlers. As such, meaningful unit test cases cannot be written for StateMachine class. Also note that StateMachine does not introduce drastically different codes from the original counterparts, its functionality can be tested manually with the following use cases.

#### Test scenarios
- Connector operations should work as expected:
- Creating a new connector
- Creating a new connector and drop it without completion
- Taking an existing connector and reconnect it elsewhere
- Replacing an existing connector by dropping a connector on its port
- In-place node editing (in the text box) should work
- Commit changes by hitting key
- Commit changes by clicking on canvas
- Single or multiple nodes can be moved around in canvas with mouse
- Both cross and contain selection windows should continue to work as expected
- Undo/redo should continue to work for the above scenarios
- All of the above operations must be possible with zoomed/offseted canvas
- All of the above operations must be possible with a custom node workspace (e.g. *.dyf file)