View Implementations

In terms of the Model-View-Controller (MVC) paradigm, the component that is used to display a graph (i.e., the "model") is a "view." It is responsible for presenting the model to the user and also for propagating events generated by the user to the proper controller classes that handle user interaction. In yFiles.NET, this view is provided by the graph control, an instance of type GraphControl.

Class GraphControl

Class GraphControl is a Windows Forms control that presents a graph model to the user. It is a direct descendant of class CanvasControl, which provides generic support for displaying arbitrary graphical objects (see description below). The graph control is also often simply referred to as the "canvas."

Figure 2.26, “GraphControl interrelations” depicts the GraphControl interrelations with yFiles.NET types.

Figure 2.26. GraphControl interrelations

GraphControl interrelations.

The graph model is an implementation of interface IGraph, which is the central graph structure type. It represents the "model" in MVC terminology and is registered with the graph control via the Graph property.

// 'gc' is of type yWorks.yFiles.UI.GraphControl.

// Set a new graph with this GraphControl.
gc.Graph = new DefaultGraph();
// Adjust the Selection property appropriately to reflect the new graph model.
gc.Selection = new GraphSelection(gc.Graph);

Similar to its base type, GraphControl does not provide any means for handling user interaction. In order to add support for user interaction, "controllers" can be conveniently registered with a GraphControl instance.

In yFiles.NET, a controller is a so-called input mode, an implementation of interface IInputMode. The InputModes property can be used to register input modes.

The most comprehensive controller type that provides support for handling user interaction is class GraphEditorInputMode, it is a perfect match for the graph control. GraphEditorInputMode is described in the section called “User Interaction”.

// 'gc' is of type yWorks.yFiles.UI.GraphControl.

// Add a GraphEditorInputMode to this control to handle user interaction.
gc.InputModes.Add(new GraphEditorInputMode());

General Features

Class GraphControl offers all the functionality exposed by CanvasControl, including, e.g.:

  • Anti-aliased rendering, zooming, and scroll bar support.
  • Clipping and content rectangle support.
  • The scene graph, a versatile infrastructure that holds so-called canvas objects which provide the actual rendering logic for graphical objects.
  • Convenient application-level support like printing and image export.

Additionally, it makes available comfortable graph model-specific functionality:

  • The FitGraphBounds method adds graph-specific clipping support for presenting the entire graph in the canvas.
  • Distinct canvas object groups in the scene graph into which the canvas objects for actual model items, background graphics, or temporary graphical decorations are installed. See the section called “Scene Graph Addendum”.
  • Advanced application-level support: Undo/Redo and clipboard (which are accessible via WPF-like command bindings, too), and also convenient reading and writing of graph structure data from/to GraphML file format. See the section called “Application-level Features”.
  • Support for querying and modifying the selection state of graph elements through an IGraphSelection object. The Selection property can be used to get and set this object.

Tutorial demo application GraphViewer shows how to use class GraphControl to display the visual representation of a graph structure. Using the GraphControl along with a GraphEditorInputMode that handles user interaction is presented in SimpleEditorForm and also in GraphEditorForm.

Command Support

GraphControl provides support for a number of WPF-like commands which rely on a commanding infrastructure very similar in concept and usage to that present in Windows Presentation Foundation. The classes that make up this support are CommandManager, CommandBinding, and RoutedCommand from the yWorks.Support.Windows namespace. Together, they realize the command pattern and the necessary command binding support for WPF-like commands in yFiles.NET.

Table 2.16, “Command support by class GraphControl” lists the commands supported by class GraphControl.

Table 2.16. Command support by class GraphControl

Command Type Commands
Application commands Clipboard support via Cut, Copy, and Paste. Undo support via Undo and Redo.

Scene Graph Addendum

The GraphControl prepares a set of canvas objects groups beneath the Root group in the scene graph that are designed to hold distinct sets of canvas objects:

  1. Background graphics can be placed into the BackgroundGroup.
  2. Actual canvas objects for model items are in the ContentGroup.
  3. Graphical decoration to indicate the selection state of model items should be placed into the SelectionGroup.
  4. Temporary graphical decoration that highlights special conditions of model items, in particular during a comprehensive mouse gesture, can be placed into the HighlightGroup.
  5. Temporary graphical decoration needed by input modes can be placed into the InputModeGroup.

Figure 2.27, “Canvas object groups prepared by the GraphControl” depicts the initial order of these groups in the scene graph. The background group is the first child of the Root group, the input mode group is the last child. Consequently, any temporary decorations installed by input modes will be rendered frontmost while background graphics will be rendered behind all other canvas content.

Figure 2.27. Canvas object groups prepared by the GraphControl

Canvas object groups prepared by the GraphControl.

The tutorial demo application ImageExportForm shows how to use the BackgroundGroup to install background graphics.

Application-level Features

Class GraphControl provides convenient application-level functionality including clipboard and Undo/Redo support, which, in particular, is accessible via WPF-like command bindings, too. Printing the content of the canvas and exporting it to a variety of graphics file formats is supported as well. Also, the graph model can be read from and written to the GraphML graph structure exchange file format easily.

Note that the support for printing and exporting the content of the canvas is already provided in the context of class CanvasControl. (See the description in CanvasControl's Application-level Features.) GraphControl's file I/O methods that can be used to read and write a graph to GraphML file format are listed in API Excerpt 2.21, “Methods for reading and writing the graph structure”.

API Excerpt 2.21. Methods for reading and writing the graph structure

// Reading in the graph model from GraphML.
void ImportFromGraphML(string fileName)
void ImportFromGraphML(Stream stream)
void ImportFromGraphML(TextReader reader)

// Writing out the graph model to GraphML.
void ExportToGraphML(string fileName)
void ExportToGraphML(Stream stream)
void ExportToGraphML(TextWriter writer)

By means of a GraphClipboard instance that is associated with a GraphControl, default clipboard support covering Cut, Copy, and Paste actions is provided. For further control, this instance can be obtained via the Clipboard property.

Using the clipboard is shown in the tutorial demo application GraphClipboardForm.

The methods listed in API Excerpt 2.22, “Clipboard-related methods” are also conveniently accessible via WPF-like command bindings.

API Excerpt 2.22. Clipboard-related methods

void Cut()
void Copy()
void Paste()

Class GraphControl offers convenient access to the Undo/Redo functionality provided by the UndoEngine that is bound to the graph. API Excerpt 2.23, “Undo/Redo-related methods” lists the methods that can be used.

Using the graph's Undo/Redo support through the convenience methods provided by the graph control is demonstrated in tutorial demo application GraphUndoForm.

The Undo and Redo methods listed in API Excerpt 2.23, “Undo/Redo-related methods” are also conveniently accessible via WPF-like command bindings.

API Excerpt 2.23. Undo/Redo-related methods

// Obtaining the UndoEngine instance bound to the graph.
UndoEngine GetUndoEngine()

bool CanUndo()
void Undo()
bool CanRedo()
void Redo()

Class CanvasControl

Class CanvasControl is a Windows Forms control that can be used to render arbitrary graphical objects in an efficient manner. It provides a versatile supporting infrastructure that allows to conveniently create a model consisting of such objects and modify it freely. CanvasControl also supports high-performance panning and zooming of graphical content.

Figure 2.28. CanvasControl interrelations

CanvasControl interrelations.

CanvasControl is a "view" in MVC terminology, and as such displays a "model." It does not provide any means for handling user interaction. In order to add support for user interaction, "controllers" can be conveniently registered with a CanvasControl instance.

In yFiles.NET, a controller is a so-called input mode, an implementation of interface IInputMode. To install an input mode, CanvasControl's InputModes property can be used as shown in Example 2.25, “Installing multiple input modes”.

The controller types that provide support for handling user interaction are described in the section called “User Interaction”.

Example 2.25. Installing multiple input modes

// 'canvasControl' is of type yWorks.Canvas.CanvasControl.

// Concurrently installs two input modes with the canvas.
canvasControl.InputModes.Add(new ContextMenuInputMode());
canvasControl.InputModes.Add(new MyInputMode());

General Features

Out-of-the-box, class CanvasControl already supports a wide variety of useful features that can be conveniently enabled/disabled and customized. Included is, for example:

Command Support

CanvasControl provides support for a number of WPF-like commands which rely on a commanding infrastructure very similar in concept and usage to that present in Windows Presentation Foundation. The classes that make up this support are CommandManager, CommandBinding, and RoutedCommand from the yWorks.Support.Windows namespace. Together, they realize the command pattern and the necessary command binding support for WPF-like commands in yFiles.NET.

Table 2.17, “Command support by class CanvasControl” lists the commands supported by class CanvasControl.

Table 2.17. Command support by class CanvasControl

Command Type Commands
Application commands Printing support via Print and PrintPreview
Component commands ScrollPageUp, ScrollPageDown, ScrollPageLeft, ScrollPageRight
Navigation commands IncreaseZoom, DecreaseZoom

In addition, it makes available further commands that can be used for WPF-like command binding, too. Table 2.18, “CanvasControl commands” lists the commands provided by class CanvasControl.

Table 2.18. CanvasControl commands

Command Name Description
FitContentCommand Adjusts the viewport so that the entire content rectangle is visible.

World and View Coordinates

There are different coordinate spaces used for the model itself and for its presentation in the canvas, the so-called "world coordinates" and the view coordinates.

The common thing to both world and view coordinate space is the way coordinates increase with each direction. Coordinates on computer screens most commonly increase from left to right and from top to bottom. Note that this is diametrical to the normal Cartesian coordinate system known from school where coordinates increase from left to right and from bottom to top.

The view coordinates always start with (0,0) for the upper left corner and increase to the right and to the bottom. The coordinates of the lower right corner accordingly equals to (view_width-1, view_height-1), i.e., the view coordinates directly reflect the viewport's size. (Note that the canvas is also referred to as "the viewport" here. This term is most notably used whenever the dimensions of the canvas are of particular importance or the clipping is discussed, i.e., the visible part of the model.)

The world coordinates, in contrast, are those valid in the model, i.e., they denote the proper locations that are set for a node's upper-left corner or the control points of an edge.

Note

One characteristic of world coordinates is that they can have negative values, while view coordinates are always positive.

The mapping from one coordinate space to the other happens automatically and is achieved using the notion of the so-called "view point" and scaling. The view point determines the world coordinates that get directly mapped to the upper-left corner of the viewport, i.e., it defines where the view's origin lies in the world coordinates's two-dimensional space. The ViewPoint property can be used to control the view point.

An additional scaling factor that can be applied to the world coordinates determines the zoom level with which the canvas scales the model's presentation. To control the zoom level, CanvasControl provides the Zoom property.

API Excerpt 2.24, “Coordinate conversion methods” lists the methods that can be used when explicit coordinate conversion is required.

API Excerpt 2.24. Coordinate conversion methods

// From world to view coordinates...
PointD ToViewCoordinates(PointD worldPoint)

// ...and vice-versa.
PointD ToWorldCoordinates(PointD viewPoint)

Example 2.26, “Coordinate conversion in detail” presents the instructions for coordinate conversion in detail.

Example 2.26. Coordinate conversion in detail

// From world to view coordinates...
viewPoint = (worldPoint - gc.ViewPoint) * zoom;

// ...and vice-versa.
worldPoint = viewPoint/zoom + gc.ViewPoint;

Content Rectangle and Viewport

The intention of the content rectangle is to specify an "area of interest" within the world coordinate space. This area can then be used by the canvas to determine the actual part of the model to be displayed in response to a call to FitContent, most notably.

The content rectangle can be conveniently specified and modified using the methods listed in API Excerpt 2.25, “Content rectangle-related methods”. Note that CanvasControl also provides the ContentRect property to control the content rectangle.

API Excerpt 2.25. Content rectangle-related methods

void GrowContentRect(RectD boundsToInclude)
void UpdateContentRect()

The actual clipping of the world coordinate space that is displayed in the canvas can furthermore be modified using the methods shown in API Excerpt 2.26, “Methods that affect the viewport”. CanvasControl also provides the Zoom property to control the scaling factor used by the canvas. Additionally, the Viewport property can be used to obtain the dimensions of the currently visible part of the model.

API Excerpt 2.26. Methods that affect the viewport

void FitContent()
void ZoomTo(PointD center, double zoom)
void ZoomTo(RectD bounds)

Commands to increase, respectively decrease the zoom factor are also accessible via WPF-like command bindings.

Hit-testing

To test whether a canvas object lies at a given coordinate, or to collect all canvas objects at a given coordinate, CanvasControl provides the methods listed in API Excerpt 2.27, “Methods for collecting hit elements”.

Note that hit-testing relies on the availability of an IHitTestable implementation for a canvas object. Normally, such an implementation is returned by a canvas object's descriptor. "Simple" canvas objects, i.e., implementations of interface IPaintable, however, do not provide a descriptor and hence do not support hit-testing.

API Excerpt 2.27. Methods for collecting hit elements

bool IsHit(ICanvasObject canvasObject, PointD point)

ICanvasObject GetCanvasObject(PointD location)
IList<ICanvasObject> GetCanvasObject(PointD location)

IEnumerator<ICanvasObject> EnumerateHits(PointD location)
IEnumerator<ICanvasObject> EnumerateHits(PointD location, 
                                         ICanvasObjectGroup root)
IEnumerator<ICanvasObject> EnumerateHits(PointD location, 
                                         ICanvasObjectGroup root, 
                                         Predicate<ICanvasObject> filter)

The HitTestRadius property of class CanvasControl can be used to control the hit-testing sensitivity that is used when mouse click events are processed. Note that the value for this property is given in view coordinates rather than world coordinates, which enables precise testing behavior especially with small zoom levels.

Canvas Redraw

To trigger redraw operations in the canvas, class CanvasControl provides the methods listed in API Excerpt 2.28, “Invalidation methods”.

API Excerpt 2.28. Invalidation methods

// Invalidates the entire canvas.
void Invalidate()

// Selective invalidation in world coordinate space.
void Invalidate(ICanvasObject canvasObject)

Application-level Features

Class CanvasControl provides convenient application-level functionality for printing the content of the canvas, or for exporting it to a variety of graphics file formats. The printing methods listed in API Excerpt 2.29, “Canvas content printing methods” enable both instant printing to a system's default printer as well as using the full-blown printing user interface.

API Excerpt 2.29. Canvas content printing methods

// Printing the canvas content.
void Print()
bool Print(RectD worldRect,
           bool showPrintDialog, bool showPageSetupDialog, bool showPreview)

Note that the Print and additionally the PrintPreview command are also accessible via WPF-like command bindings for application commands.

Using further printing options, like scaling or poster printing, is described in the section called “Scaling and Poster Printing”.

API Excerpt 2.30, “Canvas content image export methods” lists the methods that support the export of the canvas's content to a graphics file format. The available graphics file formats are discussed in the section called “Exporting the Canvas's Content”.

API Excerpt 2.30. Canvas content image export methods

// Exporting the canvas content to bitmap-based graphics file formats.
void ExportToBitmap(string file, string format)
void ExportToBitmap(Stream stream, string format, RectD worldRect)

// Exporting the canvas content to vector-based graphics file format EMF.
void ExportToEmf(string emfFile)
void ExportToEmf(string emfFile, RectD worldRect)
void ExportToEmf(Stream stream)
void ExportToEmf(Stream stream, RectD worldRect)

Scene Graph and Canvas Objects

Central to the services that CanvasControl provides is the so-called "scene graph," the supporting infrastructure that holds the model of graphical objects.

The scene graph is a data structure maintained by a CanvasControl object. It is used to hold "canvas objects," elements that provide the logic for rendering graphical objects in the canvas, and also to determine the actual rendering order of these objects.

The scene graph most often is a tree-like structure that consists of inner nodes and leaf nodes. The leaf nodes are always actual canvas objects, which are implementations of interface ICanvasObject. The inner nodes are so-called groups that can be used to partition the set of canvas objects in any suitable manner. Groups are implementations of interface ICanvasObjectGroup. A scene graph has at least one group, the root group, which cannot be removed. It is accessible via the Root property.

Figure 2.29. ICanvasObject and related types

ICanvasObject and related types.

An ICanvasObject bundles a custom so-called user object and an ICanvasObjectDescriptor. The intention of the former is to hold any data specific to a given graphical object, like, e.g. its size and its location in the canvas. The latter is used by the CanvasControl to obtain the actual logic related to all rendering and interaction aspects for the corresponding canvas object.

CanvasControl also supports "simple" canvas objects that provide the rendering logic themselves and can do without an explicit descriptor. These canvas objects consist of an IPaintable implementation.

API Excerpt 2.31, “Methods for adding canvas objects to the scene graph” lists the CanvasControl methods that can be used to add canvas objects to the scene graph. To remove a canvas object from the scene graph, the Remove method can be used.

Note

The order in which canvas objects are added to a group (or the root group, when no explicit group is specified) directly influences their rendering order: canvas objects that are added later are rendered in front of those added earlier.

API Excerpt 2.31. Methods for adding canvas objects to the scene graph

// Adding canvas objects which consist of user object and descriptor.
ICanvasObject Add(Object userObject, ICanvasObjectDescriptor descriptor)
ICanvasObject Add(Object userObject, ICanvasObjectDescriptor descriptor, 
                  ICanvasObjectGroup group)

// Adding IPaintable implementations (simple canvas objects).
ICanvasObject Add(IPaintable paintable)
ICanvasObject Add(IPaintable paintable, ICanvasObjectGroup group)

To add further groups to the scene graph, the CanvasControl methods listed in API Excerpt 2.32, “Methods for adding groups to the scene graph” can be used. To remove a group from the scene graph, the Remove method can be used.

Note

The order in which groups are added to another group (or the root group, when no explicit group is specified) directly influences the rendering order: the content of groups that are added later is rendered in front of the content of those added earlier.

API Excerpt 2.32. Methods for adding groups to the scene graph

// Adding to the root group of the scene graph.
ICanvasObjectGroup AddGroup()

// Adding to another group of the scene graph.
ICanvasObjectGroup AddGroupToGroup(ICanvasObjectGroup group)

The scene graph is also used to determine the rendering order of graphical objects. To this end, it is traversed in depth-first manner when a redraw is requested. The rendering of canvas objects is done in the order they are traversed, i.e., objects that are traversed later are drawn in front of earlier traversed ones.

Initially, the rendering order can be determined by the order in which canvas objects are added to a group and the order in which groups are added to another group. Once groups and canvas objects are in the scene graph, the methods listed in API Excerpt 2.33, “Methods from ICanvasObjects for changing the rendering order of canvas objects” can be used to change the rendering order easily.

API Excerpt 2.33. Methods from ICanvasObjects for changing the rendering order of canvas objects

// Changing a canvas object's "position" within the group it resides in.
ICanvasObject ToFront()
ICanvasObject ToBack()
ICanvasObject Raise()
ICanvasObject Lower()

// When 'reference' is in another group, the canvas object is moved there.
ICanvasObject After(ICanvasObject reference)
ICanvasObject Before(ICanvasObject reference)

Class GraphOverviewControl

Class GraphOverviewControl is a Windows Forms control that presents an overview of the graph model to the user, that always shows the graph model in its entirety. Typically, it has a GraphControl instance associated and displays the same graph as this instance. The GraphControl instance can be either set at creation time or via the GraphControl property.

Superposed on the presentation of the overview is a visual feedback for the current clipping area of the associated GraphControl instance. This superposed rectangle can be moved using the mouse, thereby moving the clipping area accordingly. GraphOverviewControl also supports mouse wheel zooming and propagates the new zoom to the GraphControl instance it has associated.

Note

To reduce drawing complexity, GraphOverviewControl does not display the graph in the same manner as the associated GraphControl instance. Instead, the graph is displayed with less details: labels are omitted, there are no arrows at the ends of edges and nodes are always drawn as rectangles.

The tutorial demo applications SimpleEditorForm and GraphEditorForm demonstrate how a GraphOverviewControl can be instantiated.