Basic Interaction

Introduction to Interaction

You can add interactivity to a graph control using input modes. Input modes are controlled by user interaction from mouse, keyboard, and touch events.

Input modes can be used to enable both navigation and editing. Navigation includes interaction such as panning and zooming, while editing includes element creation, clipboard operations, and more.

Using Pre-defined Input Modes

The library contains pre-defined input modes which you can use out-of-the-box or modify to fit your needs. You can also create your own custom input modes from scratch. Custom input modes can also be combined with pre-defined input modes.

The two main pre-defined input modes are GraphViewerInputMode for navigation, and GraphEditorInputMode which combines editing and navigation. Each of these combines multiple minor input modes which handle different specific tasks (e.g. MarqueeSelectionInputMode for rubber band selection).

Enabling Interactive Navigation

The GraphViewerInputMode allows panning and zooming using the mouse, keyboard, or touch events. You enable navigation by assigning an instance of GraphViewerInputMode to your GraphControl's InputMode property.

Example 3.15. How to add a GraphViewerInputMode to your GraphControl

// Assign a GraphViewerInputMode for graph navigation
graphControl.InputMode = new GraphViewerInputMode();

Enabling Interactive Editing

The GraphEditorInputMode allows the following operations:

  • creating and removing nodes, edges, bends, and labels
  • modifying elements, such as editing labels or resizing nodes
  • moving elements
  • navigation
  • selection
  • clipboard (cut/copy/paste)
  • undo/redo
  • grouping
  • collapsing and expanding groups

You enable interactive editing by assigning an instance of GraphEditorInputMode to your GraphControl's InputMode property.

Example 3.16. How to add a GraphEditorInputMode to your GraphControl

// Assign a GraphEditorInputMode for graph editing
graphControl.InputMode = new GraphEditorInputMode();

After setting your input mode, standard mouse and touch gestures and keyboard shortcuts will work for the above-listed operations.

Selectively Disabling Features of GraphEditorInputMode

By default, all of GraphEditorInputMode's features are enabled. Individual features can be disabled in order to prevent specific kinds of graph editing operations.

GraphEditorInputMode and its minor input modes offer the following properties for fine-tuning the available functionality:

Table 3.47. GraphEditorInputMode Properties

Property Description
NodeCreationAllowed Determines whether node creation using the click gesture is allowed.
EdgeCreationAllowed Determines whether edge creation is allowed.
BendCreationAllowed Determines whether bend creation is allowed.
LabelAddingAllowed Determines whether the label editor will be automatically invoked if the Shift+F2 key is pressed.
DeletableItems Determines which types of items may be deleted using the DeleteSelection() action.
MarqueeSelectableItems Determines which types of items should be selected during marquee selections.
ClickSelectableItems Determines which types of items should be selectable through mouse clicks.
ShowHandleItems Determines which kinds of handles are shown. This allows switching off specific kinds of operations using handles, e.g. resizing.
MoveInputMode. Enabled Enables or disables moving graph items.
MoveLabelInputMode. Enabled Enables or disables moving labels.
Getting Notified of User Actions

GraphEditorInputMode and its minor modes also provide events that are triggered upon user interactions. These events are neither repeated during undo/redo operations nor are they triggered by programmatic changes and graph I/O. They serve as callbacks to the programmer to react to user interaction, e.g. to update the underlying business data.

Table 3.48. GraphEditorInputMode Events

Event Description
NodeCreated Occurs when this mode has created a node in response to user interaction.
DeletedItem Occurs when an item has been deleted interactively by this mode.
SelectionModel. ItemSelected An event that will be triggered if an item changed its selection state from unselected to selected.
SelectionModel. ItemDeselected An event that will be triggered if an item changed its selection state from selected to unselected.
MoveInputMode. DragStarted Event that will be triggered once the drag is initialized and has started.
MoveInputMode. Dragging Event that will be triggered for every drag.
MoveInputMode. DragFinished Event that will be triggered once the drag has been finished.
MoveInputMode. DragCanceled Event that will be triggered when the drag has been canceled.
HandleInputMode. DragStarted Event that will be triggered once the drag is initialized and has started. Indicates a resize, bend move, etc. gesture, based on the type of handle.
HandleInputMode. Dragging Event that will be triggered for every drag. Indicates a resize, bend move, etc. gesture, based on the type of handle.
HandleInputMode. DragFinished Event that will be triggered once the drag has been finished. Indicates a resize, bend move, etc. gesture, based on the type of handle.
HandleInputMode. DragCanceled Event that will be triggered when the drag has been canceled. Indicates a resize, bend move, etc. gesture, based on the type of handle.
Creating Orthogonal Edges

Normally, when you create an edge, its segments are straight lines between their source and target ports and optionally bends in between. Orthogonal edge editing automatically inserts and moves bends on the fly so that all edge segments are constrained to being either vertical or horizontal.

Figure 3.13. Orthogonal Edge Editing

Orthogonal Edge Editing
Orthogonal Edge Editing
Non-Orthogonal Edges Orthogonal Edges

To enable this feature, you first need to set the GraphEditorInputMode's OrthogonalEdgeEditingContext property to an instance of an OrthogonalEdgeEditingContext.

Then, set OrthogonalEdgeCreation to true.

Example 3.17. Enabling Orthogonal Edge Creation

GraphEditorInputMode inputMode = GetMyGraphEditorInputMode();

// Assign an orthogonal edge editing context
inputMode.OrthogonalEdgeEditingContext = new OrthogonalEdgeEditingContext();
// Enable orthogonal edge creation
inputMode.CreateEdgeInputMode.OrthogonalEdgeCreation = true;
Snapping Elements to Each Other

When moving elements interactively, you can snap them to a grid or to other elements. Snapping helps to align and evenly distribute elements.

Figure 3.14. Snapping

Snapping

Snapping is a feature of the GraphEditorInputMode and has to be enabled before it can be used.

To enable snapping to other graph elements, an instance of LabelSnapContext must be set to the property SnapContext of the GraphEditorInputMode.

In addition to this general snapping, some label models support snapping of a label to the node bounds or edge path of the label's owner, respectively. To enable this label snapping, an instance of LabelSnapContext must be set to the property LabelSnapContext of the GraphEditorInputMode.

Example 3.18. Enabling Snapping

GraphEditorInputMode inputMode = GetMyGraphEditorInputMode();

// Enable the snapping feature
inputMode.SnapContext = new GraphSnapContext();
Snapping Elements to a Grid

Snapping elements to a grid also begins with setting the GraphEditorInputMode's SnapContext to an instance of a GraphSnapContext.

Example 3.19. Setting a Snap Context

GraphEditorInputMode inputMode = GetMyGraphEditorInputMode();

// Enable the snapping feature
inputMode.SnapContext = new GraphSnapContext();
// Enable the label snapping feature
inputMode.LabelSnapContext = new LabelSnapContext();

Next, we create a GridInfo with basic information about the spacing of the grid.

Example 3.20. Creating the GridInfo

// initialize gridinfo with basic information about the grid
GridInfo gridInfo = new GridInfo { HorizontalSpacing = 50, 
                                   VerticalSpacing = 50 };

Then we tell the SnapContext to snap nodes and bends to the grid, by assigning grid constraint providers. For this, use the properties NodeGridConstraintProvider and BendGridConstraintProvider.

Example 3.21. Setting Contraint Providers

GraphSnapContext snapContext = GetMyGraphSnapContext();
GridInfo gridInfo = GetMyGridInfo();

// add contraint providers so that elements snap to the grid
snapContext.NodeGridConstraintProvider = 
    new SimpleGridConstraintProvider<INode>(gridInfo);
snapContext.BendGridConstraintProvider = 
    new SimpleGridConstraintProvider<IBend>(gridInfo);
Visualizing the Grid

If you want the grid to be visible, you also need to create a visualization of the grid, and add it to the GraphControl. The GridVisualCreator is the default visualization of the grid; you can also use your own visualization instead.

Example 3.22. Visualizing the Grid

GridInfo gridInfo = GetMyGridInfo();

// visualize the grid and add it to the graph control
GridVisualCreator grid = new GridVisualCreator(gridInfo);
graphControl.Add(grid, CanvasObjectDescriptor.Instance, 
                 graphControl.BackgroundGroup);