patterncsharpMinor
Drawing Tree Structures
Viewed 0 times
drawingstructurestree
Problem
I am developing a WinForm application that extracts data from our database and draws a tree like structure on the form. For the users to get a better idea of how the data is structured.
The database is designed in such a way, that data looks like tree structures. Based on that I can fetch the data and draw the tree structure.
I am using
Here is the Node class:
```
public class OINode
{
#region Const
public int NodeDiamenter = 55;
private string FontString = "Tahoma";
private FontFamily GPFont = new FontFamily("Tahoma");
private float GPFontSize = 11.0f;
#endregion
#region Graphics
private GraphicsPath GPNode;
private GraphicsPath GPLabels;
private Point TopLeft;
private Size NodeSize;
private Point _Top;
private Point _Bottom;
private bool Selected = false;
private bool didHit = false;
#endregion
#region Properties
private string _ID = "ID";
private string _Type = "Type";
private string _SubType = "SubType";
private string _KnownByID = "SubType";
private string _InternalStatus = "InternalStatus";
private Point _Location = new Point(0, 0);
private Color _NodePen = Color.Black;
private Color _NodeBrush = Color.White;
private Color _NodeSelectPen = Color.Yellow;
private Color _NodeSelectBrush = Color.WhiteSmoke;
private int _AssignedLevel = -1;
public string ID { get { return _ID; } set { _ID = value; } }
public string Type { get { return _Type; } set { _Type = value; } }
public string SubType { get { return _SubType; } set { _SubType = value; } }
public string KnownByID { get { return _KnownByID; } set { _KnownByID = value; } }
public string InternalStatus { get { return _InternalStatus; } set { _InternalStatus = value; } }
public Point Location { get { return _Location; } set { _Location = value; ConstuctNode(); } }
public Color Nod
The database is designed in such a way, that data looks like tree structures. Based on that I can fetch the data and draw the tree structure.
I am using
GraphicsPath objects to draw the nodes and the links between them, and to do hit testing.Here is the Node class:
```
public class OINode
{
#region Const
public int NodeDiamenter = 55;
private string FontString = "Tahoma";
private FontFamily GPFont = new FontFamily("Tahoma");
private float GPFontSize = 11.0f;
#endregion
#region Graphics
private GraphicsPath GPNode;
private GraphicsPath GPLabels;
private Point TopLeft;
private Size NodeSize;
private Point _Top;
private Point _Bottom;
private bool Selected = false;
private bool didHit = false;
#endregion
#region Properties
private string _ID = "ID";
private string _Type = "Type";
private string _SubType = "SubType";
private string _KnownByID = "SubType";
private string _InternalStatus = "InternalStatus";
private Point _Location = new Point(0, 0);
private Color _NodePen = Color.Black;
private Color _NodeBrush = Color.White;
private Color _NodeSelectPen = Color.Yellow;
private Color _NodeSelectBrush = Color.WhiteSmoke;
private int _AssignedLevel = -1;
public string ID { get { return _ID; } set { _ID = value; } }
public string Type { get { return _Type; } set { _Type = value; } }
public string SubType { get { return _SubType; } set { _SubType = value; } }
public string KnownByID { get { return _KnownByID; } set { _KnownByID = value; } }
public string InternalStatus { get { return _InternalStatus; } set { _InternalStatus = value; } }
public Point Location { get { return _Location; } set { _Location = value; ConstuctNode(); } }
public Color Nod
Solution
I am not going to look at the details of your code (Jeff did that already); rather, I want to make some comments on the architecture here.
Recently I had the task of drawing a tree structure (an organigram to be precise) starting with Excel data. I split my program into several components, each one of them responsible for one aspect of the task. The idea is to have a greater flexibility. E.g. the customer might want to retrieve the data from a database in future, instead of an Excel worksheet. In my case I had to change the graphics technology. I started by creating the organigram through Visio automation. I worked but was extremely slow. Now I am creating SVG graphics. This is much faster and the graphic can be opened in Visio. The change was easy to implement, thanks to my good architecture.
I split my logic into these tasks, each one of them realized as a separate component:
The point here is that the layouter does not need to know which technology is used for drawing the graphic. The layouter creates a list of shapes using technology independent shapes.
And so on. I have polygon shapes, text shapes, rectangle shapes and more. An important part is the shape factory. Concrete shape factories will produce technology dependent shapes like Visio shapes or SVG shapes.
The layouter creates the requested shapes through an
Recently I had the task of drawing a tree structure (an organigram to be precise) starting with Excel data. I split my program into several components, each one of them responsible for one aspect of the task. The idea is to have a greater flexibility. E.g. the customer might want to retrieve the data from a database in future, instead of an Excel worksheet. In my case I had to change the graphics technology. I started by creating the organigram through Visio automation. I worked but was extremely slow. Now I am creating SVG graphics. This is much faster and the graphic can be opened in Visio. The change was easy to implement, thanks to my good architecture.
I split my logic into these tasks, each one of them realized as a separate component:
- Read the data source
- Build a logical tree structure
- Layout the tree
- Draw the diagram
The point here is that the layouter does not need to know which technology is used for drawing the graphic. The layouter creates a list of shapes using technology independent shapes.
public interface IShape
{
double Top { get; }
double Left { get; }
double Height { get; }
double Width { get; }
// Calculated
double Right { get; }
double Bottom { get; }
void Render(); // This method does all the technology dependent stuff.
}
public interface ILine : IShape
{
LineOrientation Orientation { get; }
Color LineColor { get; }
double LineWidth { get; }
}And so on. I have polygon shapes, text shapes, rectangle shapes and more. An important part is the shape factory. Concrete shape factories will produce technology dependent shapes like Visio shapes or SVG shapes.
public interface IShapeFactory
{
IDiagram CreateDiagram(List shapes);
ILine CreateLine(PointD p0, PointD p1, Color lineColor, double lineWidth);
IPolygon CreatePolygon(List points, Color fillColor,
Color borderColor, double borderWidth);
IRectangle CreateRectangle(RectangleD rect, Color fillColor,
Color borderColor, double borderWidth,
double cornerRadius);
ISymbol CreateSymbol(RectangleD rect, IService service);
IText CreateText(RectangleD rect, string text, string fontName,
double pointSize, Color color, TextAlignment alignment,
TextStyle style, TextOrientation orientation);
}The layouter creates the requested shapes through an
IShapeFactory that is injected through its constructor and does not need to know which graphics system will be used.Code Snippets
public interface IShape
{
double Top { get; }
double Left { get; }
double Height { get; }
double Width { get; }
// Calculated
double Right { get; }
double Bottom { get; }
void Render(); // This method does all the technology dependent stuff.
}
public interface ILine : IShape
{
LineOrientation Orientation { get; }
Color LineColor { get; }
double LineWidth { get; }
}public interface IShapeFactory
{
IDiagram CreateDiagram(List<IShape> shapes);
ILine CreateLine(PointD p0, PointD p1, Color lineColor, double lineWidth);
IPolygon CreatePolygon(List<PointD> points, Color fillColor,
Color borderColor, double borderWidth);
IRectangle CreateRectangle(RectangleD rect, Color fillColor,
Color borderColor, double borderWidth,
double cornerRadius);
ISymbol CreateSymbol(RectangleD rect, IService<IDiagramNode> service);
IText CreateText(RectangleD rect, string text, string fontName,
double pointSize, Color color, TextAlignment alignment,
TextStyle style, TextOrientation orientation);
}Context
StackExchange Code Review Q#15406, answer score: 3
Revisions (0)
No revisions yet.