Class GraphEditorInputMode
is a full-featured controller that makes available the functionality of a set
of specialized input modes.
It covers all aspects of user interaction with an IGraph instance displayed in
a GraphCanvasComponent.
GraphEditorInputMode provides convenient support for creating, modifying, and interacting with graph elements in an IGraph instance.
GraphEditorInputMode also provides convenient support for hierarchically organized graphs, which includes, for example, grouping and ungrouping of nodes as well as re-parenting.
Upon initialization, GraphEditorInputMode creates and installs the input modes listed in Table 2.15, “Input modes used by GraphEditorInputMode (sorted by input mode priority)” as concurrent input modes. Note that the input modes are sorted according to their priority (see also the section called “Input Mode Priorities”).
Table 2.15. Input modes used by GraphEditorInputMode (sorted by input mode priority)
| Type Name | Description |
|---|---|
| HandleInputMode |
Manages the dragging of "handles," including the detection of beginning and ending of a drag, and canceling a drag. Also provides the visual feedback for handles when dragged. |
| KeyboardInputMode |
Recognizes key events. |
| ClickInputMode |
Recognizes mouse clicks. |
| MoveLabelInputMode |
Specialized instance that handles moving of labels to label candidate positions. |
| MoveInputMode |
Handles moving of canvas objects. |
| CreateBendInputMode |
Governs the creation of additional bends in edge paths. |
| CreateEdgeInputMode |
Governs the creation of edges in an IGraph. |
| MarqueeSelectionInputMode |
Provides the visual feedback for a rectangular selection box in the canvas. |
| ContextMenuInputMode |
Displays a context menu. |
| MouseHoverInputMode |
Displays a tooltip when the mouse rests in the canvas. |
| TextEditorInputMode |
Handles label editing. |
Each of the input modes can be obtained or replaced using a like named property
defined by GraphEditorInputMode.
Also, a sorted list of input modes can be obtained via the
sortedModes
method.
Graph element creation functionality is provided directly by
GraphEditorInputMode as well as the input modes CreateBendInputMode and
CreateEdgeInputMode.
The former uses the method shown in
API Excerpt 2.23, “Mouse gesture node creation method” whenever a node is created in
the canvas by means of a mouse click gesture.
Using the
nodeCreationAllowed
and
nodeCreator
properties, the actual node creation behavior can be easily customized.
Bend and edge creation is governed by their respective input modes.
However, CreateEdgeInputMode exposes convenient bend-related customization
capabilities.
For example, the
bendCreationAllowed
property can be used to disallow bend creation in the canvas.
Class GraphEditorInputMode provides various properties and callbacks that allow
for fine-grained control of the editing functionality by restricting the set of
graph items the input mode may act upon to a subset of the available graph item
types.
Most of these configuration properties can be set using a combination of the
graph item type constants defined in class
GraphItemTypes
.
The available customization properties of class GraphEditorInputMode are listed in Table 2.16, “GraphEditorInputMode customization”.
Table 2.16. GraphEditorInputMode customization
| Name | Purpose |
|---|---|
| labelEditingAllowed |
Whether interactive label editing is allowed. If set to true, label editing is triggered by the F2 key by default. |
| nodeCreationAllowed |
Whether the user is allowed to create nodes. |
| selectableItems |
A combination of GraphItemTypes that specifies the set of graph items that can be selected by the user. |
| marqueeSelectableItems |
A combination of GraphItemTypes that specifies the set of graph items that can be selected using the marquee selection tool. |
| clickSelectableItems |
A combination of GraphItemTypes that specifies the set of graph items that can be selected by mouse clicks. |
| showHandleItems |
A combination of GraphItemTypes that specifies the set of graph items that should show resize handles when selected. |
| shouldShowHandles |
Callback that determines whether resize handles should be shown for the given item. |
| deletableItems |
A combination of GraphItemTypes that specifies the set of graph items that will be deleted when the Delete key is pressed. |
| shouldBeDeleted |
Callback that determines whether the given item may be deleted. |
| movableItems |
A combination of GraphItemTypes that specifies the set of graph items that can be moved by the user. |
| shouldBeMovable |
Callback that determines whether the given item may be moved. |
Example 2.20, “Using the GraphItemTypes constants” shows how to use the GraphItemTypes constants to customize a GraphEditorInputMode instance.
Example 2.20. Using the GraphItemTypes constants
// don't show resize handles for any graph items geim.showHandleItems = GraphItemTypes.NONE; // only allow deletion of edges and nodes geim.deletableItems = GraphItemTypes.EDGE | GraphItemTypes.NODE;
Class MainInputMode defines a powerful basis for controller implementations that need to handle a broad range of user gestures happening in the view. It makes available the functionality of a set of specialized input modes that are installed concurrently with the canvas.
The direct base type of class MainInputMode is
MultiplexingInputMode
, an input
mode that enables input modes to be installed with the canvas and be executed
concurrently.
As part of the concurrency amongst these input modes, MultiplexingInputMode can
grant an input mode exclusive control over all canvas interaction.
Input modes that support concurrency are of type
IConcurrentInputMode
and are
also referred to as "concurrent input modes."
They can be added to the set of input modes that are managed by
MultiplexingInputMode by means of the methods listed in
API Excerpt 2.24, “Methods for adding concurrent input modes”.
API Excerpt 2.24. Methods for adding concurrent input modes
// Adding concurrent input modes to a MultiplexingInputMode's concurrency // controller. addConcurrent(inputMode:IConcurrentInputMode, priority:int):void
MultiplexingInputMode also introduces the notion of priority with the input modes it installs into the canvas. The priority value of an input mode determines when it is installed, which in turn defines its position in the queue of input modes that are delivered user events. A low priority value means that an input mode comes early in this queue and thus processes an event prior to other input modes with a higher priority value that are also registered with that event.
Upon initialization, MainInputMode creates and installs the input modes listed in Table 2.17, “Input modes used by MainInputMode (sorted by input mode priority)” as concurrent input modes. Note that the input modes are sorted according to their priority.
Table 2.17. Input modes used by MainInputMode (sorted by input mode priority)
| Type Name | Description |
|---|---|
| HandleInputMode |
Manages the dragging of "handles," including the detection of beginning and ending of a drag, and canceling a drag. Also provides the visual feedback for handles when dragged. |
| KeyboardInputMode |
Recognizes key events. |
| ClickInputMode |
Recognizes mouse clicks. |
| MoveInputMode |
Handles moving of canvas objects. |
| MarqueeSelectionInputMode |
Provides the visual feedback for a rectangular selection box in the canvas. |
| ContextMenuInputMode |
Displays a context menu. |
| MouseHoverInputMode |
Displays a tooltip when the mouse rests in the canvas. |
Each of the input modes can be obtained and changed using a like named property
defined by class MainInputMode.
Also, a sorted list of input modes can be obtained by means of the
sortedModes
method.
Class MoveViewportInputMode
enables moving of the viewport by means of a simple mouse move gesture.
The behavior of input modes can be easily customized by means of their properties, using custom callback methods, or by replacing specialized input modes by customized implementations thereof.
For example, to customize the text of the tooltip that is displayed by
MouseHoverInputMode, an appropriate callback method can be registered with the
input mode's
textProvider
property.
Example 2.21, “Setting text providers for the tooltips displayed by concurrent MouseHoverInputMode instances” presents this scheme in the context of two
concurrent MouseHoverInputModes.
Example 2.21. Setting text providers for the tooltips displayed by concurrent MouseHoverInputMode instances
// 'mainInputMode' is of type com.yworks.canvas.input.MainInputMode.
var nodeTextProvider:Function =
TooltipTextProviders.getGraphItemMapperTextProvider(
INode, "node-description");
var nodeHoverMode:MouseHoverInputMode =
new MouseHoverInputMode(new ToolTip(), nodeTextProvider);
nodeHoverMode.showEffect = fadeIn;
nodeHoverMode.hideEffect = fadeOut;
mainInputMode.addConcurrent(nodeHoverMode, 120);
var edgeTextProvider:Function =
TooltipTextProviders.getGraphItemMapperTextProvider(
IEdge, "edge-description");
var edgeHoverMode:MouseHoverInputMode =
new MouseHoverInputMode(new ToolTip(), edgeTextProvider);
edgeHoverMode.showEffect = fadeIn;
edgeHoverMode.hideEffect = fadeOut;
mainInputMode.addConcurrent(edgeHoverMode, 120);
The context menu that is displayed by ContextMenuInputMode can be specified as
a whole using the
menu
property.
Input modes that handle specific mouse gestures when a user interacts with the graph elements often either directly or indirectly use the look-up mechanism to query additional information in relation to the respective gesture. This information generally also affects the look and feel of the elements. Consequently, the look and feel of an application, i.e., the rendering and the behavior of graph elements whenever a user is interacting with them, can be conveniently customized by decorating their look-up. For instance, the selection decoration of nodes can be customized, or their resizing behavior can be changed to obey only discrete steps, simply by adding appropriate interface implementations to the look-up mechanism.
Example 2.22, “Decorating the look-up for nodes” shows how the look-up for nodes is decorated using the ILookupDecorator returned by the graph. A custom look-up chain link, which replaces the default look-up logic for nodes, is added to the look-up chain that is maintained by the graph. Whenever a node gets selected, the new logic then returns a custom ISelectionPaintable implementation.
More information on the look-up support provided by the graph structure implementation can be found in the section called “Look-up Support”.
Example 2.22. Decorating the look-up for nodes
// 'graph' is of type com.yworks.graph.model.IGraph.
// Decorate the look-up for nodes to change their default behavior.
var decorator:ILookupDecorator =
graph.lookup(ILookupDecorator) as ILookupDecorator;
if (decorator != null) {
if (decorator.canDecorate(INode)) {
decorator.addLookup(INode,
Lookups.addingLookupChainLink(ISelectionPaintable,
new MyCustomSelectionPaintable()));
}
}
Table 2.18, “User gestures and interfaces implementations in the look-up” gives an overview on the interface implementations that are queried when certain user gestures are handled.
Table 2.18. User gestures and interfaces implementations in the look-up
| Gesture | Type Name | Description |
|---|---|---|
| Edge creation | IPortCandidateProvider |
Returns collections of ports that an edge can connect to.
When a new edge is created, CreateEdgeInputMode queries the look-up of the
source node and the target node for implementations of this interface.
Implementations of this interface include:
EmptyPortsCandidateProvider
Also, abstract class
AbstractPortCandidateProvider |
| Resizing | IReshapeHandleProvider |
Offers control over the resize behavior for a model item that is displayed in
the canvas.
When a model item (INode) gets resized, HandleInputMode queries the item's
look-up for implementations of this interface.
Class ReshapeableHandles |
| ISizeConstraintProvider |
Enables definition of minimum and maximum size constraints for items of
arbitrary type.
In a hierarchically organized graph, the size of group nodes is affected by
implementations of this interface.
Class
SizeConstraintProvider |
|
| Selecting | ISelectionPaintable |
Allows to install any number of
ICanvasObject
Implementations of this interface include:
OrientedRectangleSelectionPaintable |
| Edge reconnecting, port relocating | IEdgePortCandidateProvider |
Returns collections of ports that an edge can connect to.
When either end of an edge gets relocated, the look-up of the edge is queried
for implementations of this interface.
Implementations of this interface include:
DefaultEdgePortsCandidateProvider |
| Moving | IPositionHandler |
Provides callback methods that allow to control all parts of a mouse drag
gesture.
When a model item (INode, IPort, IBend, ILabel) gets moved, MoveInputMode and
MoveLabelInputMode query the item's look-up for implementations of this
interface.
Class
DefaultPositionHandler |
Customization of the re-parenting gesture in a hierarchically organized graph,
which can be controlled using interface
IReparentNodeHandler
, is
described in the section called “Class GraphEditorInputMode”.
Example 2.23, “Customizing the way a selected node is rendered” presents a custom implementation for interface ISelectionPaintable that draws a dotted rectangle around a selected node.
Example 2.23. Customizing the way a selected node is rendered
public class MyCustomSelectionPaintable extends ISelectionPaintable {
override public function installSelectionPaintables(
userObject:Object, canvas:CanvasComponent,
selectionGroup:ICanvasObjectGroup):Array {
var n:INode = INode(userObject);
var rect:ShapePaintable =
ShapePaintable.createViewRectangle(new DecoratedRectangle(n.layout, 3));
rect.stroke = new Pen(Brushes.DarkGray);
rect.stroke.weight = 2;
return new ICanvasObject[]{
canvas.add(rect, CanvasObjectDescriptor.Instance, selectionGroup) };
}
public class DecoratedRectangle extends IRectangle {
private var box:IRectangle;
private var borderWidth:Number;
public DecoratedRectangle(box:IRectangle, borderWidth:Number) {
this.box = box;
this.borderWidth = borderWidth;
}
override public function get x():Number {
return box.x - borderWidth;
}
override public function get y():Number {
return box.y - borderWidth;
}
override public function get width():Number {
return box.width + 2 * borderWidth;
}
override public function get height():Number {
return box.height + 2 * borderWidth;
}
}
}
|
Copyright ©2007-2008, yWorks GmbH. All rights reserved. |