Diagram Graphs and Pins
The wxArt2D library has fundamental ingredients for making complex graph drawings which are editable. A graph here is a set of canvas objects, which are connected directly or using wires. It has bin setup as flexible we could think of. So things like several flows in one drawing using classes of pins which are connect able to each other and not to others, is part of the design. Same for the tools which are used to edit a graph. Like the standard dragging tool, it is fully aware that objects can be part of a graph. And it makes sure that connected objects do stay connected, or that unconnected objects become connected at the right moment. This functionality of course has complicated the design of wxArt2D, but when not implementing it at the very base of the library in all aspects, it would have bin useless.
As always in wxArt2D, the objects are derived from a2dCanvasObject's, and for the wires the same applies, it is just a specialized a2dCanvasObject. The way to define how a canvas object is connected to a wire or other object, is by using a pin (a2dPin) at the position where the wire should connect to the canvas object. The pin is a child of the canvas object which is connected to the wire, and the wire has a pin child too, at the same position. Internal in the two pins the connection of the one pin to the other is made. This is no more then a pointer from the pin to the other and visa versa. Any canvas object can have pins as childs, and pins can connect, so all canvas objects can connect with each other directly or using a wire to indicate that two are more objects are connected. A wire like canvas object behaves differently in many occasions.
(picture object pin pin wire pin pin object and result next to it )
The main implementation of a wire object is currently in a2dCanvasWirePolylineL, but if needed other types of wires can be implented. Most easily by deriving from it, but you may also implement your own. As the name suggest, the wire is a a2dCanvasPolylineL derived object. The difference from a polyline with pins added as childs, is in the way it treats those pins and what happens if connected objects are dragged around. If for instance two non wire objects are dragged apart, automatically a wire will be created in between. There are several ways to reroute a wire when the object are dragged. The most simple one just make a straight wire between the new position of the begin and end pin, the more complex routing uses an algorithm, to make a new polyline which has 90 degree angles and routes as much as possible around existing other wires and objects.
(picture routing)
Hierarchy in the form of grouped objects which can be itself grouped objects, is done by adding a2dCanvasObject's as children to a parent a2dCanvasObject. The top of this hierarchy is always the m_rootobject of a a2dCanvasDocument. So a2dPin's which are added to a parent a2dCanvasObject, is in principle no more then a simple hierarchy. You can add any other a2dCanvasObject as a child to the same parent. When the parent is a plain a2dCanvasObject, all that is rendered, are the children and pins. To make sure the pins are displayed on top of the other child objects, a flag is set to a pin, which results in rendering it later then the other children. The pin object itself is/can be rendered differently depending on it being connected or not. There are special feedback functions, which are used by (editing) tools, to change the mode of pin rendering depending on the possible connections at the point where the cursor position is. For instance when trying to create a new wire and connect it to an existing object, the object will give feedback by changing the rendering as long as the cursor is on top or near the pin on that object. Even if the object has no pins, like a standard rectangle, it can automatically create pins on the object. This we call dynamic pins. When connection is eventually made, the pin will remain in the object, else it will automatically be released. For most basic objects, this type of feedback is implemented, and for your own objects you can do the same. Still in case of a special designed library of connect able objects, one would mainly encounter pins at fixed positions within the objects. The CVG file format supports this, while dynamically created pins can only be implemented via a virtual function in C++ for that a2dCanvasObject. But as soon as dynamic pins are connected, they will be saved to CVG.
All the above is sufficient for creating simple graphs, like flows for programs, are any other graph where there are only connected objects, and all objects can connect to each other without restriction. In several situations more is needed. One might need a control and at the same time a data flow on the objects in the drawing, or certain types of objects can be connected while others can not. This functionality is achieved by adding a2dPinClass objects to a a2dPin. Certain pin classes may connect to each other while others may not, a2dConnectionGenerator implements a basic mechanism using an array of a2dPinClassMap's. But all its functions are virtual, so you can define any other ways of connecting objects. The a2dConnectionGenerator is asked to perform a specific task related to connecting objects, e.g to supply a new wire or a template for a new wire, given the object and the two pins which need to be connected by that wire. If NULL is returned, it is clear that those pin can not be connected. Those function are used within the library to automatically created new wires, and also by the tools to know which type of wire can start on which object etc. Interactive Feedback functions called from editing tools towards a2dCanvasObject's in the drawing, normally also use the a2dConnectionGenerator to find out if a connection is possible, and if the answer is positive, it while change its rendering mode accordingly. As said, a2dConnectionGenerator is generating new wires, therefore the way to make an application use different wire classes then the default a2dWirePolylineL, is by setting different wire templates to it.
