DotNet 4.8.1 build of DotNetBar

This commit is contained in:
2025-02-07 10:35:23 -05:00
parent 33439b63a0
commit 6b0a5d60f4
2609 changed files with 989814 additions and 7 deletions

View File

@@ -0,0 +1,171 @@
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace DevComponents.Tree.Display
{
/// <summary>
/// Represents cell display class.
/// </summary>
internal class CellDisplay
{
public CellDisplay()
{
}
public static void PaintCell(NodeCellRendererEventArgs ci)
{
if(ci.Cell.CheckBoxVisible)
CellDisplay.PaintCellCheckBox(ci);
if(!ci.Cell.Images.LargestImageSize.IsEmpty)
CellDisplay.PaintCellImage(ci);
CellDisplay.PaintText(ci);
}
public static void PaintCellCheckBox(NodeCellRendererEventArgs ci)
{
if(!ci.Cell.CheckBoxVisible)
return;
Rectangle r=ci.Cell.CheckBoxBoundsRelative;
r.Offset(ci.CellOffset);
System.Windows.Forms.ButtonState state=System.Windows.Forms.ButtonState.Normal;
if(ci.Cell.Checked)
state=System.Windows.Forms.ButtonState.Checked;
System.Windows.Forms.ControlPaint.DrawCheckBox(ci.Graphics,r,state);
}
public static void PaintCellImage(NodeCellRendererEventArgs ci)
{
if(ci.Cell.Images.LargestImageSize.IsEmpty)
return;
Rectangle r=ci.Cell.ImageBoundsRelative;
r.Offset(ci.CellOffset);
Image image = CellDisplay.GetCellImage(ci.Cell);
if(image!=null)
{
Size imageSize = Dpi.Size(image.Size);
ci.Graphics.DrawImage(image,r.X+(r.Width-imageSize.Width)/2,
r.Y+(r.Height-imageSize.Height)/2, imageSize.Width, imageSize.Height);
}
}
public static void PaintText(NodeCellRendererEventArgs ci)
{
Cell cell=ci.Cell;
if(cell.HostedControl==null && (cell.Text=="" || ci.Style.TextColor.IsEmpty) || cell.TextContentBounds.IsEmpty )
return;
Rectangle bounds=ci.Cell.TextContentBounds;
bounds.Offset(ci.CellOffset);
if(cell.HostedControl!=null)
{
// if(ci.Graphics.Transform!=null)
// {
// Point[] p=new Point[] {new Point(bounds.X, bounds.Y), new Point(bounds.Right, bounds.Bottom)};
// ci.Graphics.Transform.TransformPoints(p);
// bounds = new Rectangle(p[0].X, p[0].Y, p[1].X-p[0].X, p[1].Y-p[0].Y);
// }
// if(cell.HostedControl.Bounds!=bounds)
// {
// cell.IgnoreHostedControlSizeChange = true;
// cell.HostedControl.Bounds=bounds;
// cell.IgnoreHostedControlSizeChange = false;
// }
if(!cell.HostedControl.Visible)
cell.HostedControl.Visible = true;
return;
}
Font font=ci.Style.Font;
bounds.Inflate(1,1);
if (cell.TextMarkupBody == null)
TextDrawing.DrawString(ci.Graphics , cell.Text, font, ci.Style.TextColor, bounds, ci.Style.TextFormat);
else
{
TextMarkup.MarkupDrawContext d = new TextMarkup.MarkupDrawContext(ci.Graphics, font, ci.Style.TextColor, false);
d.HotKeyPrefixVisible = !((ci.Style.TextFormat & eTextFormat.HidePrefix) == eTextFormat.HidePrefix);
Rectangle mr = new Rectangle(bounds.X, bounds.Y + (bounds.Height - cell.TextMarkupBody.Bounds.Height) / 2, cell.TextMarkupBody.Bounds.Width, cell.TextMarkupBody.Bounds.Height);
mr.Offset((bounds.Width - mr.Width) / 2, 0);
cell.TextMarkupBody.Bounds = mr;
cell.TextMarkupBody.Render(d);
}
}
private static Image GetCellImage(Cell cell)
{
Image img=cell.Images.Image;
if(img==null && cell.Images.ImageIndex>=0)
img=cell.Images.GetImageByIndex(cell.Images.ImageIndex);
if(cell.IsMouseOver && (cell.Images.ImageMouseOver!=null || cell.Images.ImageMouseOverIndex>=0))
{
if(cell.Images.ImageMouseOver!=null)
img=cell.Images.ImageMouseOver;
else
img=cell.Images.GetImageByIndex(cell.Images.ImageMouseOverIndex);
}
else if(cell.Parent.Expanded && (cell.Images.ImageExpanded!=null || cell.Images.ImageExpandedIndex>=0))
{
if(cell.Images.ImageExpanded!=null)
img=cell.Images.ImageExpanded;
else
img=cell.Images.GetImageByIndex(cell.Images.ImageExpandedIndex);
}
return img;
}
public static Font GetCellFont(TreeGX tree, Cell cell)
{
Font font=tree.Font;
ElementStyle style=null;
if(cell.StyleNormal!=null)
{
style=cell.StyleNormal;
}
else
{
if(tree.NodeStyle!=null)
style=tree.NodeStyle;
else
style=new ElementStyle();
if(tree.CellStyleDefault!=null)
style=tree.CellStyleDefault;
else
style=ElementStyle.GetDefaultCellStyle(style);
}
if(style!=null && style.Font!=null)
font=style.Font;
return font;
}
}
/// <summary>
/// Represents information neccessary to paint the cell on canvas.
/// </summary>
internal class CellDisplayInfo
{
public ElementStyle Style=null;
public System.Drawing.Graphics Graphics=null;
public Cell ContextCell=null;
public Point CellOffset=Point.Empty;
public CellDisplayInfo()
{
}
public CellDisplayInfo(ElementStyle style, System.Drawing.Graphics g, Cell cell, Point cellOffset)
{
this.Style=style;
this.Graphics=g;
this.ContextCell=cell;
this.CellOffset=cellOffset;
}
}
}

View File

@@ -0,0 +1,52 @@
using System;
using System.Drawing;
namespace DevComponents.Tree.Display
{
/// <summary>
/// Represents helper class for node connector display.
/// </summary>
public class ConnectorRendererEventArgs:EventArgs
{
/// <summary>
/// From node reference.
/// </summary>
public Node FromNode=null;
/// <summary>
/// From node style reference.
/// </summary>
public ElementStyle StyleFromNode=null;
/// <summary>
/// To node reference.
/// </summary>
public Node ToNode=null;
/// <summary>
/// To node style reference.
/// </summary>
public ElementStyle StyleToNode=null;
/// <summary>
/// Graphics object used for drawing.
/// </summary>
public System.Drawing.Graphics Graphics=null;
/// <summary>
/// Node offset since some node coordinates are relative.
/// </summary>
public Point Offset=Point.Empty;
/// <summary>
/// Indicates whether from node is a root node.
/// </summary>
public bool IsRootNode=false;
/// <summary>
/// Reference to node connector object that describes connector type.
/// </summary>
public NodeConnector NodeConnector=null;
/// <summary>
/// Gets or sets whether connector is link connector.
/// </summary>
public bool LinkConnector=false;
/// <summary>
/// Reference to the collection of the connector path points. Default value is null indicating there are no path points.
/// </summary>
public ConnectorPointsCollection ConnectorPoints=null;
}
}

View File

@@ -0,0 +1,141 @@
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace DevComponents.Tree.Display
{
/// <summary>
/// Represents the connector display for map type.
/// </summary>
public class CurveConnectorDisplay:NodeConnectorDisplay
{
/// <summary>
/// Draws connector line between two nodes.
/// </summary>
/// <param name="info">Connector context information.</param>
public override void DrawConnector(ConnectorRendererEventArgs info)
{
if(info.NodeConnector.LineColor.IsEmpty || info.NodeConnector.LineWidth<=0)
return;
DrawCurveConnector(info);
}
private void DrawCurveConnector(ConnectorRendererEventArgs info)
{
Point pStart=this.GetStartPoint(info);
Point[] parr=this.GetEndPoint(info);
Point pEnd=parr[0];
Point pEndUnderLine=parr[1];
int lineWidth=info.NodeConnector.LineWidth;
int xMulti=1, yMulti=1;
// used for direction control
if(pStart.X>pEnd.X)
xMulti=-1;
if(pStart.Y>pEnd.Y)
yMulti=-1;
if(info.ConnectorPoints==null || info.ConnectorPoints.Count == 0)
{
// Determine whether curve can be drawn
if(Math.Abs(pStart.X-pEnd.X)<=6 || Math.Abs(pStart.Y-pEnd.Y)<=10)
{
DrawLineConnector(info,pStart,pEnd,pEndUnderLine);
}
else
{
// Create two points in between the start and end point
Point[] p=new Point[4];
p[1].X=pStart.X+(int)(Math.Abs(pStart.X-pEnd.X)*.15f*xMulti);
p[1].Y=pStart.Y+(int)(Math.Abs(pStart.Y-pEnd.Y)*.15f*yMulti);
p[2].X=pStart.X+(int)(Math.Abs(pStart.X-pEnd.X)*.5f*xMulti);
p[2].Y=pEnd.Y-(int)(yMulti*(Math.Abs(pStart.Y-pEnd.Y)*.15f));
p[0]=pStart;
p[3]=pEnd;
if(lineWidth>1)
{
GraphicsPath path=new GraphicsPath();
path.AddCurve(p,.5f);
// Check whether pStart is starting from left or right side
Rectangle fromNodeRect=info.FromNode.BoundsRelative;
fromNodeRect.Offset(info.Offset);
fromNodeRect.Inflate(-1,-1);
// if(pStart.Y>fromNodeRect.Y && pStart.Y<fromNodeRect.Bottom && pStart.X>=fromNodeRect.Right)
// {
// path.AddLine(pStart.X, pStart.Y-lineWidth*xMulti, pStart.X, pStart.Y);
// }
path.AddLine(p[0].X,p[0].Y,p[0].X+lineWidth*xMulti,p[0].Y);
if(pStart.Y>fromNodeRect.Y && pStart.Y<fromNodeRect.Bottom && pStart.X>=fromNodeRect.Right && info.IsRootNode)
{
path.AddLine(p[0].X-1,p[0].Y,p[0].X-1,p[0].Y+lineWidth*yMulti);
p[0].Y -= lineWidth*yMulti;
}
else if(pStart.Y>fromNodeRect.Y && pStart.Y<fromNodeRect.Bottom && pStart.X<=fromNodeRect.Left && info.IsRootNode)
{
path.AddLine(p[0].X+1,p[0].Y,p[0].X+1,p[0].Y+lineWidth*yMulti);
p[0].Y -= lineWidth*yMulti;
}
else
p[0].X+=(lineWidth*xMulti);
p[1].X+=(lineWidth*xMulti);
p[2].X+=(lineWidth*xMulti);
p[3].Y-=yMulti;
path.AddCurve(p,.5f);
path.AddLine(p[3].X,p[3].Y,p[3].X,p[3].Y+yMulti);
path.CloseAllFigures();
using(Brush brush=this.GetLineBrush(info))
{
info.Graphics.FillPath(brush,path);
}
}
else
{
using(Pen pen=this.GetLinePen(info))
{
info.Graphics.DrawCurve(pen,p,.5f);
}
}
}
}
else
{
ConnectorPointInfo pointInfo=GetConnectorPointInfo(info,pStart,pEnd);
if(pointInfo.Points2==null)
{
using(Pen pen=this.GetLinePen(info))
{
info.Graphics.DrawCurve(pen,pointInfo.Points1,.5f);
}
}
else
{
using(GraphicsPath path=new GraphicsPath())
{
path.AddCurve(pointInfo.Points1,.5f);
path.AddCurve(pointInfo.Points2,.5f);
path.CloseAllFigures();
using(Brush brush=this.GetLineBrush(info))
{
info.Graphics.FillPath(brush,path);
}
}
}
}
DrawEndLine(info,pStart,pEnd,pEndUnderLine);
}
}
}

View File

@@ -0,0 +1,97 @@
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using DevComponents.Tree.Display;
namespace DevComponents.Tree.Display
{
/// <summary>
/// Represents the line connector display class.
/// </summary>
public class LineConnectorDisplay:NodeConnectorDisplay
{
/// <summary>
/// Draws connector line between two nodes.
/// </summary>
/// <param name="info">Connector context information.</param>
public override void DrawConnector(ConnectorRendererEventArgs info)
{
if(info.NodeConnector.LineColor.IsEmpty || info.NodeConnector.LineWidth<=0)
return;
DrawStarConnector(info);
}
private void DrawStarConnector(ConnectorRendererEventArgs info)
{
Point pStart=this.GetStartPoint(info);
Point[] parr=this.GetEndPoint(info);
Point pEnd=parr[0];
Point pEndUnderLine=parr[1];
if(info.ConnectorPoints==null)
{
// Determine whether curve can be drawn
if(Math.Abs(pStart.X-pEnd.X)<=6 || Math.Abs(pStart.Y-pEnd.Y)<=10)
{
DrawLineConnector(info,pStart,pEnd,pEndUnderLine);
}
else
{
Point pBottom=new Point();
Point pTop=new Point();
if(pEnd.X<pStart.X)
{
pBottom.X=pStart.X-info.NodeConnector.LineWidth;
pTop.X=pEnd.X+1;
}
else
{
pBottom.X=pStart.X+info.NodeConnector.LineWidth;
pTop.X=pEnd.X-1;
}
pBottom.Y=pStart.Y;
pTop.Y=pEnd.Y;
GraphicsPath path=new GraphicsPath();
path.AddLine(pStart,pBottom);
path.AddLine(pBottom,pEnd);
path.AddLine(pEnd,pTop);
path.AddLine(pTop,pStart);
path.CloseAllFigures();
using(Brush brush=this.GetLineBrush(info))
info.Graphics.FillPath(brush,path);
}
}
else
{
ConnectorPointInfo pointInfo=GetConnectorPointInfo(info,pStart,pEnd);
if(pointInfo.Points2==null)
{
using(Pen pen=this.GetLinePen(info))
{
info.Graphics.DrawLines(pen,pointInfo.Points1);
}
}
else
{
using(GraphicsPath path=new GraphicsPath())
{
path.AddLines(pointInfo.Points1);
path.AddLines(pointInfo.Points2);
path.CloseAllFigures();
using(Brush brush=this.GetLineBrush(info))
{
info.Graphics.FillPath(brush,path);
}
}
}
}
DrawEndLine(info,pStart,pEnd,pEndUnderLine);
}
}
}

View File

@@ -0,0 +1,53 @@
using System;
using System.Drawing;
namespace DevComponents.Tree.Display
{
/// <summary>
/// Provides information for cell rendering methods and events.
/// </summary>
public class NodeCellRendererEventArgs:NodeRendererEventArgs
{
/// <summary>
/// Gets or sets the cell being rendered.
/// </summary>
public Cell Cell=null;
/// <summary>
/// Gets or sets absolute cell bounds.
/// </summary>
public Rectangle CellBounds=Rectangle.Empty;
/// <summary>
/// Gets or sets absolute bounds for cell text.
/// </summary>
public Rectangle CellTextBounds = Rectangle.Empty;
/// <summary>
/// Gets or sets the internal cell offset.
/// </summary>
internal Point CellOffset=Point.Empty;
/// <summary>
/// Creates new instance of the class.
/// </summary>
public NodeCellRendererEventArgs():base(null,null,Rectangle.Empty,null)
{
}
/// <summary>
/// Creates new instance of the class and initializes it with default values.
/// </summary>
/// <param name="g">Reference to graphics object.</param>
/// <param name="node">Reference to context node.</param>
/// <param name="bounds">Reference to node bounds</param>
/// <param name="style">Reference to cell style</param>
/// <param name="cell">Reference to cell</param>
/// <param name="cellBounds">Reference to cell bounds</param>
public NodeCellRendererEventArgs(Graphics g, Node node, Rectangle bounds, ElementStyle style, Cell cell, Rectangle cellBounds):base(g,node,bounds,style)
{
this.Cell = cell;
this.CellBounds = cellBounds;
}
}
}

View File

@@ -0,0 +1,78 @@
using System.Drawing;
using System.Drawing.Drawing2D;
namespace DevComponents.Tree.Display
{
/// <summary>
/// Paints node command button.
/// </summary>
internal class NodeCommandDisplay
{
public virtual void DrawCommandButton(NodeCommandPartRendererEventArgs info)
{
bool mouseOver = (info.Node.MouseOverNodePart == eMouseOverNodePart.Command);
CommandColors c=new CommandColors();
if(mouseOver)
{
c.BackColor = info.MouseOverBackColor;
c.BackColor2 = info.MouseOverBackColor2;
c.BackColorGradientAngle = info.MouseOverBackColorGradientAngle;
c.ForeColor = info.MouseOverForeColor;
}
else
{
c.BackColor = info.BackColor;
c.BackColor2 = info.BackColor2;
c.BackColorGradientAngle = info.BackColorGradientAngle;
c.ForeColor = info.ForeColor;
}
Rectangle fillBounds = info.CommandPartBounds;
fillBounds.Width--;
fillBounds.Height--;
Region oldRegion = info.Graphics.Clip.Clone() as Region;
info.Graphics.SetClip(fillBounds,CombineMode.Intersect);
if(c.BackColor2.IsEmpty)
{
if(!c.BackColor.IsEmpty)
{
using(SolidBrush brush=new SolidBrush(c.BackColor))
info.Graphics.FillRectangle(brush,fillBounds);
}
}
else
{
using(LinearGradientBrush brush=DisplayHelp.CreateLinearGradientBrush(info.CommandPartBounds, c.BackColor, c.BackColor2, c.BackColorGradientAngle))
info.Graphics.FillRectangle(brush,fillBounds);
}
if(c.ForeColor.IsEmpty) return;
int width=6;
int height=3;
GraphicsPath path=new GraphicsPath();
Point p=new Point(info.CommandPartBounds.X+(info.CommandPartBounds.Width-width)/2,info.CommandPartBounds.Y+(info.CommandPartBounds.Height-height)/2);
path.AddLine(p.X, p.Y, p.X+width,p.Y);
path.AddLine(p.X+width,p.Y,p.X+width/2,p.Y+height);
path.AddLine(p.X, p.Y,p.X+width/2,p.Y+height);
path.CloseAllFigures();
using(SolidBrush brush=new SolidBrush(c.ForeColor))
info.Graphics.FillPath(brush,path);
path.Dispose();
info.Graphics.Clip = oldRegion;
}
private class CommandColors
{
public Color BackColor=Color.Empty;
public Color BackColor2=Color.Empty;
public Color ForeColor=Color.Empty;
public int BackColorGradientAngle=0;
}
}
}

View File

@@ -0,0 +1,64 @@
using System;
using System.Drawing;
namespace DevComponents.Tree.Display
{
/// <summary>
/// Summary description for NodeCommandPartRendererEventArgs.
/// </summary>
public class NodeCommandPartRendererEventArgs:EventArgs
{
/// <summary>
/// Gets or sets reference to Graphics object, canvas node is rendered on.
/// </summary>
public System.Drawing.Graphics Graphics=null;
/// <summary>
/// Gets or sets the reference to Node object being rendered.
/// </summary>
public DevComponents.Tree.Node Node=null;
/// <summary>
/// Gets or sets command part absolute bounds.
/// </summary>
public Rectangle CommandPartBounds=Rectangle.Empty;
/// <summary>
/// Gets or sets command part back color.
/// </summary>
public Color BackColor=Color.Empty;
/// <summary>
/// Gets or sets command part end gradient color.
/// </summary>
public Color BackColor2=Color.Empty;
/// <summary>
/// Gets or sets command part text color.
/// </summary>
public Color ForeColor=Color.Empty;
/// <summary>
/// Gets or sets gradient angle.
/// </summary>
public int BackColorGradientAngle=0;
/// <summary>
/// Gets or sets command part back color when mouse is over the part.
/// </summary>
public Color MouseOverBackColor=Color.Empty;
/// <summary>
/// Gets or sets command part end gradient back color when mouse is over the part.
/// </summary>
public Color MouseOverBackColor2=Color.Empty;
/// <summary>
/// Gets or sets text color when mouse is over the part.
/// </summary>
public Color MouseOverForeColor=Color.Empty;
/// <summary>
/// Gets or sets gradient angle.
/// </summary>
public int MouseOverBackColorGradientAngle=0;
/// <summary>
/// Creates new instance of the class.
/// </summary>
/// <param name="g"></param>
public NodeCommandPartRendererEventArgs(Graphics g)
{
}
}
}

View File

@@ -0,0 +1,487 @@
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace DevComponents.Tree
{
namespace Display
{
/// <summary>
/// Base class for drawing node connectors.
/// </summary>
public abstract class NodeConnectorDisplay
{
//private bool m_RootNode=false;
//private bool m_DrawRootAllLevels=false;
private bool m_EndCap=true;
//private bool m_DrawConnectorUnderNodes=true;
/// <summary>
/// Creates new instance of the object.
/// </summary>
public NodeConnectorDisplay()
{
}
/// <summary>
/// Draws connector line between two nodes.
/// </summary>
/// <param name="info">Connector context information.</param>
public virtual void DrawConnector(ConnectorRendererEventArgs info){}
/// <summary>
/// Returns the connector starting coordinates.
/// </summary>
/// <param name="info">Connector display information.</param>
/// <returns>Point object.</returns>
protected Point GetStartPoint(ConnectorRendererEventArgs info)
{
Point p=Point.Empty;
if(info.IsRootNode)
{
//int toMidPoint=info.ToNode.Bounds.Top+info.ToNode.Bounds.Height/2;
//if(info.FromNode.Bounds.Top>toMidPoint)
if(IsAbove(info.FromNode,info.ToNode))
p=new Point(info.FromNode.BoundsRelative.Left+info.FromNode.BoundsRelative.Width/2,info.FromNode.BoundsRelative.Top);
//else if(info.FromNode.Bounds.Bottom<toMidPoint)
else if(IsBelow(info.FromNode,info.ToNode))
p=new Point(info.FromNode.BoundsRelative.Left+info.FromNode.BoundsRelative.Width/2,info.FromNode.BoundsRelative.Bottom-1);
}
if(p.IsEmpty)
{
// To element to the Left
if(this.IsOnLeftSide(info.FromNode,info.ToNode))
p=new Point(info.FromNode.BoundsRelative.Left,info.FromNode.BoundsRelative.Top+info.FromNode.BoundsRelative.Height/2);
else
{
p=new Point(info.FromNode.BoundsRelative.Right,info.FromNode.BoundsRelative.Top+info.FromNode.BoundsRelative.Height/2);
if(info.IsRootNode)
p.X--;
if(!NodeDisplay.DrawExpandPart(info.FromNode) && info.FromNode.ExpandVisibility==eNodeExpandVisibility.Auto)
p.X-=(info.FromNode.BoundsRelative.Width-info.FromNode.ContentBounds.Width);
}
}
if(!p.IsEmpty)
p.Offset(info.Offset.X,info.Offset.Y);
return p;
}
/// <summary>
/// Returns true if fromNode is above the toNode.
/// </summary>
/// <param name="fromNode">From Node object.</param>
/// <param name="toNode">To Node object</param>
/// <returns>True if fromNode is above toNode.</returns>
protected bool IsAbove(Node fromNode, Node toNode)
{
//int toMidPoint=toNode.Bounds.Top+toNode.Bounds.Height/2;
//if(fromNode.Bounds.Top>toMidPoint)
if(fromNode.BoundsRelative.Top>=toNode.BoundsRelative.Bottom)
return true;
return false;
}
/// <summary>
/// Returns true if fromNode is below toNode.
/// </summary>
/// <param name="fromNode">From Node object.</param>
/// <param name="toNode">To Node object.</param>
/// <returns>True if fromNode is below toNode.</returns>
protected bool IsBelow(Node fromNode, Node toNode)
{
int toMidPoint=toNode.BoundsRelative.Top+toNode.BoundsRelative.Height/2;
if(fromNode.BoundsRelative.Bottom<toMidPoint)
return true;
return false;
}
/// <summary>
/// Returns whether connector is extended to underline the node.
/// </summary>
/// <param name="nodeStyle">Refernce to Node style.</param>
/// <returns>True if node should be underlined by connector.</returns>
protected bool UnderlineNode(ElementStyle nodeStyle)
{
if(!nodeStyle.PaintBottomBorder && !nodeStyle.PaintTopBorder &&
!nodeStyle.PaintLeftBorder && !nodeStyle.PaintRightBorder)
return true;
return false;
}
/// <summary>
/// Returns the connector end point. The array of end points. Two valid points will be returned if node needs to be underlined by connector.
/// </summary>
/// <param name="info">Connector display info.</param>
/// <returns>Array of point objects.</returns>
protected Point[] GetEndPoint(ConnectorRendererEventArgs info)
{
// If to element is to the right of the from node and has left border end point is the vertical mid-point
// If to element is to the left of the from node and has right border end point is the vertical mid-point
// If there is no border end point is text bottom
// If this is link connector the end point is the middle bottom or top point of the node
Point p=Point.Empty;
Point pLineEnd=Point.Empty;
int capWidthOffset=GetCapWidthOffset(info.NodeConnector.EndCap,info.NodeConnector.EndCapSize);
bool leftSide=this.IsOnLeftSide(info.FromNode,info.ToNode);
if(info.LinkConnector && info.FromNode.BoundsRelative.Top>info.ToNode.BoundsRelative.Bottom)
p=new Point(info.ToNode.BoundsRelative.X+info.ToNode.BoundsRelative.Width/2+(leftSide?capWidthOffset:-capWidthOffset),info.ToNode.BoundsRelative.Bottom+1);
else if(info.LinkConnector && info.FromNode.BoundsRelative.Bottom<info.ToNode.BoundsRelative.Top)
p=new Point(info.ToNode.BoundsRelative.X+info.ToNode.BoundsRelative.Width/2+(leftSide?capWidthOffset:-capWidthOffset),info.ToNode.BoundsRelative.Top-info.NodeConnector.EndCapSize.Height);
else
{
if(leftSide)
{
// To element is to the left of from node
Rectangle r=info.ToNode.BoundsRelative;
if(info.StyleToNode==null || UnderlineNode(info.StyleToNode))
{
p=new Point(r.Right,r.Bottom);
if(m_EndCap)
p.X+=capWidthOffset;
if(info.NodeConnector.UnderlineNoBorderNode)
{
Rectangle rc=NodeDisplay.GetNodeRectangle(eNodeRectanglePart.NodeContentBounds,info.ToNode,Point.Empty);
pLineEnd=new Point(rc.Left+1,r.Bottom);
}
}
else
{
p=new Point(r.Right,r.Y+r.Height/2);
if(m_EndCap)
p.X+=capWidthOffset;
}
}
else
{
// To element to the right of from node
Rectangle r=info.ToNode.BoundsRelative;
if(info.StyleToNode==null || UnderlineNode(info.StyleToNode))
{
//r=NodeDisplay.GetCellRectangle(eCellRectanglePart.TextBounds,info.ToNode.Cells[0],Point.Empty);
//r=info.ToNode.Cells[0].TextContentBounds;
p=new Point(r.X,r.Bottom);
if(m_EndCap)
p.X-=capWidthOffset;
if(info.NodeConnector.UnderlineNoBorderNode)
{
Rectangle rc=NodeDisplay.GetNodeRectangle(eNodeRectanglePart.NodeContentBounds,info.ToNode,Point.Empty);
pLineEnd=new Point(rc.Right-1,r.Bottom);
}
}
else
{
p=new Point(r.X,r.Y+r.Height/2);
if(m_EndCap)
p.X-=capWidthOffset;
}
}
}
if(!p.IsEmpty)
p.Offset(info.Offset.X,info.Offset.Y);
if(!pLineEnd.IsEmpty)
pLineEnd.Offset(info.Offset.X,info.Offset.Y);
return new Point[] {p,pLineEnd};
}
/// <summary>
/// Returns the offest for the node connector cap.
/// </summary>
/// <param name="cap">Cap type.</param>
/// <param name="size">Cap size.</param>
/// <returns></returns>
protected int GetCapWidthOffset(eConnectorCap cap,Size size)
{
int capWidthOffset=0;
switch(cap)
{
case eConnectorCap.Arrow:
capWidthOffset=size.Width+1;
break;
case eConnectorCap.Ellipse:
capWidthOffset=size.Width;
break;
}
return capWidthOffset;
}
/// <summary>
/// Returns true if source node is on the left side of the target node.
/// </summary>
/// <param name="source">Reference to source node.</param>
/// <param name="target">Reference to target node.</param>
/// <returns>True if source is on the left side of target.</returns>
protected bool IsOnLeftSide(Node source, Node target)
{
if((source.BoundsRelative.Left+source.BoundsRelative.Width/2)>target.BoundsRelative.Left)
return true;
return false;
}
/// <summary>
/// Returns new instance of pen object for node connector line. Caller is responsible for
/// disposing of this object.
/// </summary>
/// <param name="info">Node connector display info.</param>
/// <returns>New instance of Pen object.</returns>
protected Pen GetLinePen(ConnectorRendererEventArgs info)
{
return new Pen(info.NodeConnector.LineColor,info.NodeConnector.LineWidth);
}
/// <summary>
/// Returns new instance of pen object for the end node connector line. Caller is responsible for
/// disposing of this object.
/// </summary>
/// <param name="info">Node connector display info.</param>
/// <returns>New instance of Pen object.</returns>
protected Pen GetEndLinePen(ConnectorRendererEventArgs info)
{
return new Pen(info.NodeConnector.LineColor,EndLineWidth);
}
/// <summary>
/// Returns new instance of pen object for the node underline line. Caller is responsible for
/// disposing of this object.
/// </summary>
/// <param name="info">Node connector display info.</param>
/// <returns>New instance of Pen object.</returns>
protected Pen GetEndUnderlinePen(ConnectorRendererEventArgs info)
{
return new Pen(info.NodeConnector.LineColor,EndLineWidth);
}
private int EndLineWidth
{
get {return 1;}
}
/// <summary>
/// Draws straight line connector between start and end point.
/// </summary>
/// <param name="info">Node connector display info.</param>
/// <param name="pStart">Start point.</param>
/// <param name="pEnd">End point.</param>
/// <param name="pEndUnderLine">Underline end point if any.</param>
protected void DrawLineConnector(ConnectorRendererEventArgs info,Point pStart,Point pEnd, Point pEndUnderLine)
{
if(info.NodeConnector.LineWidth>1)
{
// Merge lines nicely by filling and creating path...
int rootLineWidth=this.EndLineWidth;
int lineWidth=info.NodeConnector.LineWidth;
using(Brush brush=GetLineBrush(info))
{
GraphicsPath path=GetConnectingPath(pStart,pEnd,lineWidth,rootLineWidth,info.IsRootNode,!(IsAbove(info.FromNode,info.ToNode) || IsBelow(info.FromNode,info.ToNode)));
info.Graphics.FillPath(brush,path);
}
}
else
{
using(Pen pen=this.GetLinePen(info))
{
info.Graphics.DrawLine(pen,pStart,pEnd);
}
}
if(!pEndUnderLine.IsEmpty)
{
using(Pen pen=this.GetEndUnderlinePen(info))
{
info.Graphics.DrawLine(pen,pEnd,pEndUnderLine);
}
}
}
private GraphicsPath GetConnectingPath(Point pStart, Point pEnd, int lineStartWidth, int lineEndWidth, bool bRoot, bool bRootSide)
{
int direction=1;
if(pStart.X>pEnd.X)
direction=-1;
lineStartWidth++;
lineEndWidth++;
GraphicsPath path=new GraphicsPath();
if(bRoot && !bRootSide)
{
path.AddLine(pStart.X,pStart.Y,pStart.X+lineStartWidth*direction,pStart.Y);
// if(direction>0)
// path.AddLine(pEnd.X+lineEndWidth*direction,pEnd.Y,pEnd.X,pEnd.Y);
// else
// path.AddLine(pEnd.X,pEnd.Y,pEnd.X+lineEndWidth*direction,pEnd.Y);
if(direction>0)
{
path.AddLine(pStart.X+lineStartWidth*direction,pStart.Y, pEnd.X, pEnd.Y);
path.AddLine(pEnd.X, pEnd.Y, pEnd.X, pEnd.Y + lineEndWidth*direction);
path.AddLine(pEnd.X, pEnd.Y + lineEndWidth*direction, pStart.X, pStart.Y);
}
else
path.AddLine(pEnd.X, pEnd.Y, pEnd.X, pEnd.Y + lineEndWidth*direction);
path.CloseAllFigures();
// if(Math.Abs(pEnd.Y-pStart.Y)<=8)
// path.Widen(SystemPens.Highlight);
}
else
{
int offsetStart=lineStartWidth/2;
int offsetEnd=lineEndWidth/2;
path.AddLine(pStart.X,pStart.Y-offsetStart,pStart.X,pStart.Y+offsetStart);
path.AddLine(pEnd.X,pEnd.Y+offsetEnd,pEnd.X,pEnd.Y-offsetEnd);
path.AddLine(pEnd.X,pEnd.Y-offsetEnd,pStart.X,pStart.Y-offsetStart);
path.CloseAllFigures();
}
return path;
}
protected Brush GetLineBrush(ConnectorRendererEventArgs info)
{
return new SolidBrush(info.NodeConnector.LineColor);
}
protected void DrawEndLine(ConnectorRendererEventArgs info,Point pStart,Point pEnd,Point pEndUnderLine)
{
if(pEndUnderLine.IsEmpty)
{
switch(info.NodeConnector.EndCap)
{
case eConnectorCap.Ellipse:
{
using(Pen pen=this.GetEndLinePen(info))
{
Size endCapSize=info.NodeConnector.EndCapSize;
if(pStart.X<pEnd.X)
info.Graphics.DrawEllipse(pen,pEnd.X-1,pEnd.Y-endCapSize.Height/2,endCapSize.Width,endCapSize.Height);
else
info.Graphics.DrawEllipse(pen,pEnd.X-endCapSize.Width,pEnd.Y-endCapSize.Height/2,endCapSize.Width,endCapSize.Height);
}
break;
}
case eConnectorCap.Arrow:
{
using(Pen pen=this.GetEndLinePen(info))
{
// Connects connector line to arrow
int direction=1;
if(pStart.X>pEnd.X)
direction=-1;
info.Graphics.DrawLine(pen,pEnd,new Point(pEnd.X+info.NodeConnector.EndCapSize.Width/3*direction,pEnd.Y));
Size endCapSize=info.NodeConnector.EndCapSize;
GraphicsPath arrow=GetArrowPath(endCapSize,pStart,pEnd);
info.Graphics.DrawPath(pen,arrow);
}
break;
}
}
}
else
{
using(Pen pen=this.GetEndUnderlinePen(info))
{
info.Graphics.DrawLine(pen,pEnd,pEndUnderLine);
// Connect underline to expand part
if(NodeDisplay.DrawExpandPart(info.ToNode))
{
Rectangle re=NodeDisplay.GetNodeRectangle(eNodeRectanglePart.ExpandBounds,info.ToNode,info.Offset);
if (re.IsEmpty) return;
Point p2=new Point((re.X>pEndUnderLine.X?re.X:re.Right)+(re.Width/2*(re.X>pEndUnderLine.X?1:-1)),re.Bottom);
Point p1=new Point(p2.X,pEndUnderLine.Y+(pEndUnderLine.Y>p2.Y?(p2.Y-pEndUnderLine.Y)/2:-(p2.Y-pEndUnderLine.Y)/2));
info.Graphics.DrawCurve(pen,new Point[]{pEndUnderLine,p1,p2},.5f);
}
}
}
}
private GraphicsPath GetArrowPath(Size capSize,Point pStart,Point pEnd)
{
GraphicsPath path=new GraphicsPath();
int direction=1;
if(pStart.X>pEnd.X)
direction=-1;
pEnd.X+=(GetCapWidthOffset(eConnectorCap.Arrow,capSize)*direction);
path.AddLine(pEnd.X,pEnd.Y,pEnd.X-capSize.Width*direction,pEnd.Y-capSize.Height/2);
path.AddLine(pEnd.X-(2*capSize.Width/3*direction),pEnd.Y,pEnd.X-capSize.Width*direction,pEnd.Y+capSize.Height/2);
path.CloseAllFigures();
return path;
}
internal virtual ConnectorPointInfo GetConnectorPointInfo(ConnectorRendererEventArgs info, Point pStart, Point pEnd)
{
ConnectorPointInfo pointInfo=new ConnectorPointInfo();
int xMulti=1/*, yMulti=1*/;
int lineWidth=info.NodeConnector.LineWidth;
// used for direction control
if(pStart.X>pEnd.X)
xMulti=-1;
//if(pStart.Y>pEnd.Y)
// yMulti=-1;
if(info.ConnectorPoints!=null)
{
Point connPointsOffset=info.ToNode.BoundsRelative.Location;
connPointsOffset.Offset(info.Offset.X,info.Offset.Y);
GraphicsPath path=new GraphicsPath();
pointInfo.Points1=new Point[info.ConnectorPoints.Count+2];
pointInfo.Points1[0]=pStart;
pointInfo.Points1[pointInfo.Points1.Length-1]=pEnd;
if(lineWidth>1)
{
pointInfo.Points2=new Point[info.ConnectorPoints.Count+2];
pointInfo.Points2[pointInfo.Points2.Length-1]=pStart;
pointInfo.Points2[0]=pEnd;
int i=pointInfo.Points1.Length-2;
int k=1;
foreach(Point pcp in info.ConnectorPoints)
{
pointInfo.Points1[i]=pcp;
pointInfo.Points1[i].Offset(connPointsOffset.X,connPointsOffset.Y);
pointInfo.Points2[k]=new Point(pcp.X+lineWidth*xMulti,pcp.Y);
pointInfo.Points2[k].Offset(connPointsOffset.X,connPointsOffset.Y);
k++;
i--;
}
}
else
{
int i=pointInfo.Points1.Length-2;
foreach(Point pcp in info.ConnectorPoints)
{
pointInfo.Points1[i]=pcp;
pointInfo.Points1[i].Offset(connPointsOffset.X,connPointsOffset.Y);
i--;
}
}
}
return pointInfo;
}
}
}
/// <summary>
/// Represents custom connector path info.
/// </summary>
internal class ConnectorPointInfo
{
public Point[] Points1=null;
public Point[] Points2=null;
}
}

View File

@@ -0,0 +1,334 @@
using System;
using System.Drawing;
using DevComponents.Tree.Layout;
namespace DevComponents.Tree.Display
{
/// <summary>
/// Summary description for NodeDisplay.
/// </summary>
public class NodeDisplay
{
#region Private Variables
private Point m_Offset=Point.Empty;
private Point m_LockedOffset=Point.Empty;
private TreeGX m_Tree=null;
#if !TRIAL
internal static bool keyInvalid=false;
#endif
#endregion
/// <summary>Creates new instance of the class</summary>
/// <param name="tree">Object to initialize class with.</param>
public NodeDisplay(TreeGX tree)
{
m_Tree=tree;
}
/// <summary>
/// Paints the layout on canvas.
/// </summary>
public virtual void Paint(Graphics g, Rectangle clipRectangle)
{
}
/// <summary>
/// Gets or sets the offset of the tree content relative to the size of the container control.
/// </summary>
public virtual Point Offset
{
get
{
if(!m_LockedOffset.IsEmpty)
return m_LockedOffset;
Node displayNode=m_Tree.GetDisplayRootNode();
if(displayNode==null)
return Point.Empty;;
Size nodesSize = m_Tree.GetScreenSize(new Size(m_Tree.NodeLayout.Width, m_Tree.NodeLayout.Height));
// Must change offset value since map layout assumes that root node is in the center
// of container control.
if(m_Tree.NodeLayout is NodeMapLayout && m_Tree.AutoScroll)
{
Point p=m_Offset;
Point displayNodeChildLocation =
new Point(Math.Abs((int)(displayNode.ChildNodesBounds.Left * m_Tree.Zoom)), Math.Abs((int)(displayNode.ChildNodesBounds.Top * m_Tree.Zoom)));
p.Offset(displayNodeChildLocation.X, displayNodeChildLocation.Y);
int offsetX=0, offsetY=0;
if(m_Tree.CenterContent && m_Tree.Height>nodesSize.Height)
{
offsetY=(m_Tree.Height-nodesSize.Height)/2;
}
if(m_Tree.CenterContent && m_Tree.Width>nodesSize.Width)
{
offsetX=(m_Tree.Width-nodesSize.Width)/2;
}
p.Offset(offsetX,offsetY);
return m_Tree.GetLayoutPosition(p);
}
else if(m_Tree.NodeLayout is Layout.NodeDiagramLayout && m_Tree.AutoScroll)
{
Point p=m_Offset;
int offsetX=0, offsetY=0;
if(m_Tree.CenterContent && m_Tree.Height>nodesSize.Height)
offsetY=(m_Tree.Height-nodesSize.Height)/2;
if(m_Tree.CenterContent && m_Tree.Width>nodesSize.Width)
offsetX=(m_Tree.Width-nodesSize.Width)/2;
p.Offset(offsetX,offsetY);
return m_Tree.GetLayoutPosition(p);
}
else
return m_Offset;
}
set {m_Offset=value;}
}
/// <summary>Gets or sets whether offset is locked, i.e. cannot be changed.</summary>
public bool LockOffset
{
get {return (!m_LockedOffset.IsEmpty);}
set
{
if(value)
m_LockedOffset=this.Offset;
else
m_LockedOffset=Point.Empty;
}
}
/// <summary>
/// Sets locked offset to specific value. Point.Empty means there is no locked offset set.
/// </summary>
/// <param name="p">New locked offset.</param>
public void SetLockedOffset(Point p)
{
m_LockedOffset=p;
}
/// <summary>
///
/// </summary>
/// <returns></returns>
public Point GetLockedOffset()
{
return m_LockedOffset;
}
/// <summary>
/// Returns the default offset for the tree content relative to the size of the container.
/// </summary>
public virtual Point DefaultOffset
{
get
{
Node displayNode=m_Tree.GetDisplayRootNode();
if(displayNode==null)
return Point.Empty;;
if(m_Tree.NodeLayout is NodeMapLayout && m_Tree.Nodes.Count>0)
{
if(!m_Tree.CenterContent)
return new Point(Math.Abs(displayNode.ChildNodesBounds.Left),Math.Abs(displayNode.ChildNodesBounds.Top));
else
return new Point(m_Tree.SelectionBoxSize+(m_Tree.Width - m_Tree.SelectionBoxSize * 2 - m_Tree.NodeLayout.Width) / 2 + Math.Abs(displayNode.ChildNodesBounds.Left),
m_Tree.SelectionBoxSize + (m_Tree.Height - m_Tree.SelectionBoxSize * 2 - m_Tree.NodeLayout.Height) / 2 + Math.Abs(displayNode.ChildNodesBounds.Top));
}
if(m_Tree.NodeLayout is Layout.NodeDiagramLayout)
{
if(!m_Tree.CenterContent)
return m_Tree.ClientRectangle.Location;
else
return new Point((m_Tree.Width-m_Tree.NodeLayout.Width)/2,(m_Tree.Height-m_Tree.NodeLayout.Height)/2);
}
else
return m_Tree.ClientRectangle.Location;
}
}
/// <summary>
/// Gets or sets the reference to the tree control managed by display class.
/// </summary>
protected virtual TreeGX Tree
{
get {return m_Tree;}
set {m_Tree=value;}
}
internal static Rectangle GetNodeRectangle(eNodeRectanglePart part, Node node, Point offset)
{
Rectangle r=Rectangle.Empty;
if(part==eNodeRectanglePart.CellsBounds)
{
r=node.CellsBoundsRelative;
if(!r.IsEmpty)
{
r.Offset(offset);
r.Offset(node.BoundsRelative.Location);
}
}
else if(part==eNodeRectanglePart.ExpandBounds)
{
r=node.ExpandPartRectangleRelative;
if(!r.IsEmpty)
{
r.Offset(offset);
r.Offset(node.BoundsRelative.Location);
}
}
else if(part==eNodeRectanglePart.CommandBounds)
{
r=node.CommandBoundsRelative;
if(!r.IsEmpty)
{
r.Offset(offset);
r.Offset(node.BoundsRelative.Location);
}
}
else if(part==eNodeRectanglePart.NodeContentBounds)
{
r=node.ContentBounds;
if(!r.IsEmpty)
{
r.Offset(offset);
r.Offset(node.BoundsRelative.Location);
}
}
else if(part==eNodeRectanglePart.NodeBounds)
{
r=node.BoundsRelative;
if(!r.IsEmpty)
r.Offset(offset);
}
else if(part==eNodeRectanglePart.ChildNodeBounds)
{
r=node.ChildNodesBounds;
if(!r.IsEmpty)
{
//r.Offset(node.Bounds.Location);
r.Offset(offset);
}
}
return r;
}
internal static Rectangle GetCellRectangle(eCellRectanglePart part, Cell cell, Point offset)
{
Rectangle r=Rectangle.Empty;
// If cell parent is not assigned rectangle cannot be returned.
if(cell.Parent==null)
return r;
if(part==eCellRectanglePart.CheckBoxBounds)
{
r=cell.CheckBoxBoundsRelative;
if(!r.IsEmpty)
{
r.Offset(offset);
r.Offset(cell.Parent.BoundsRelative.Location);
}
}
else if(part==eCellRectanglePart.ImageBounds)
{
r=cell.ImageBoundsRelative;
if(!r.IsEmpty)
{
r.Offset(offset);
r.Offset(cell.Parent.BoundsRelative.Location);
}
}
else if(part==eCellRectanglePart.TextBounds)
{
r=cell.TextContentBounds;
if(!r.IsEmpty)
{
r.Offset(offset);
r.Offset(cell.Parent.BoundsRelative.Location);
}
}
else if(part==eCellRectanglePart.CellBounds)
{
r=cell.BoundsRelative;
if(!r.IsEmpty)
{
r.Offset(offset);
}
}
return r;
}
internal static bool DrawExpandPart(Node node)
{
if(node.Nodes.Count>0 && node.ExpandVisibility!=eNodeExpandVisibility.Hidden || node.ExpandVisibility==eNodeExpandVisibility.Visible)
return true;
return false;
}
protected NodeExpandDisplay GetExpandDisplay(eExpandButtonType e)
{
NodeExpandDisplay d=null;
switch(e)
{
case eExpandButtonType.Ellipse:
d=new NodeExpandEllipseDisplay();
break;
case eExpandButtonType.Rectangle:
d=new NodeExpandRectDisplay();
break;
case eExpandButtonType.Image:
d=new NodeExpandImageDisplay();
break;
}
return d;
}
protected bool IsRootNode(Node node)
{
return NodeOperations.IsRootNode(m_Tree,node);
}
protected ElementStyle GetDefaultNodeStyle()
{
ElementStyle style=new ElementStyle();
style.TextColorSchemePart=eColorSchemePart.ItemText;
return style;
}
public void MoveHostedControls()
{
Point offset=this.Offset;
float zoom = this.Tree.Zoom;
foreach(Cell cell in this.Tree.HostedControlCells)
{
Rectangle bounds = NodeDisplay.GetCellRectangle(eCellRectanglePart.TextBounds, cell, offset);
Rectangle screenBounds=this.Tree.GetScreenRectangle(bounds);
if(!bounds.IsEmpty && cell.HostedControl.Bounds!=screenBounds)
{
if(zoom!=1)
{
cell.HostedControlSize = bounds.Size;
cell.IgnoreHostedControlSizeChange = true;
}
else
{
cell.HostedControlSize = Size.Empty;
}
cell.HostedControl.Bounds=screenBounds;
if(zoom!=1)
cell.IgnoreHostedControlSizeChange = false;
if(cell.Parent!=null)
{
bool visible = NodeOperations.GetIsNodeVisible(cell.Parent);
if(visible!=cell.HostedControl.Visible)
cell.HostedControl.Visible = visible;
}
}
}
}
}
}

View File

@@ -0,0 +1,47 @@
using System.Drawing;
using System.Drawing.Drawing2D;
namespace DevComponents.Tree
{
namespace Display
{
/// <summary>
/// Base class for node expand button display.
/// </summary>
public abstract class NodeExpandDisplay
{
/// <summary>Creates new instance of the class</summary>
public NodeExpandDisplay()
{
}
/// <summary>Draws expand button.</summary>
/// <param name="e">Context parameters for drawing expand button.</param>
public abstract void DrawExpandButton(NodeExpandPartRendererEventArgs e);
protected Pen GetBorderPen(NodeExpandPartRendererEventArgs e)
{
return new Pen(e.BorderColor, Dpi.Width1);
}
protected Pen GetExpandPen(NodeExpandPartRendererEventArgs e)
{
return new Pen(e.ExpandLineColor,Dpi.Width1);
}
protected Brush GetBackgroundBrush(NodeExpandPartRendererEventArgs e)
{
if(e.BackColor.IsEmpty && e.BackColor2.IsEmpty)
return null;
if(e.BackColor2.IsEmpty)
return new SolidBrush(e.BackColor);
System.Drawing.Drawing2D.LinearGradientBrush brush=DisplayHelp.CreateLinearGradientBrush(e.ExpandPartBounds,e.BackColor,e.BackColor2,e.BackColorGradientAngle);
//brush.SetSigmaBellShape(0.8f);
return brush;
}
}
}
}

View File

@@ -0,0 +1,51 @@
using System.Drawing;
namespace DevComponents.Tree.Display
{
/// <summary>
/// Represents class that paints elliptical expand button.
/// </summary>
public class NodeExpandEllipseDisplay:NodeExpandDisplay
{
/// <summary>Draws ellipse type expand button.</summary>
/// <param name="e">Expand context drawing information.</param>
public override void DrawExpandButton(NodeExpandPartRendererEventArgs e)
{
Rectangle expandPartBounds = e.ExpandPartBounds;
if (expandPartBounds.IsEmpty)
return;
Brush brush = GetBackgroundBrush(e);
expandPartBounds.Width--;
expandPartBounds.Height--;
if (brush != null)
{
e.Graphics.FillEllipse(brush, expandPartBounds);
brush.Dispose();
}
using (Pen pen = GetBorderPen(e))
{
e.Graphics.DrawEllipse(pen, expandPartBounds);
}
if (e.Node.Expanded)
{
using (Pen pen = GetExpandPen(e))
{
e.Graphics.DrawLine(pen, expandPartBounds.X + 2, expandPartBounds.Y + expandPartBounds.Height / 2, expandPartBounds.Right - 2, expandPartBounds.Y + expandPartBounds.Height / 2);
}
}
else
{
using (Pen pen = GetExpandPen(e))
{
e.Graphics.DrawLine(pen, expandPartBounds.X + 2, expandPartBounds.Y + expandPartBounds.Height / 2, expandPartBounds.Right - 2, expandPartBounds.Y + expandPartBounds.Height / 2);
e.Graphics.DrawLine(pen, expandPartBounds.X + expandPartBounds.Width / 2, expandPartBounds.Y + 2, expandPartBounds.X + expandPartBounds.Width / 2, expandPartBounds.Bottom - 2);
}
}
}
}
}

View File

@@ -0,0 +1,25 @@
namespace DevComponents.Tree.Display
{
/// <summary>
/// Represents expand button display using predefined images.
/// </summary>
public class NodeExpandImageDisplay:NodeExpandDisplay
{
/// <summary>
/// Draws image type expand button.
/// </summary>
/// <param name="e">Expand context information</param>
public override void DrawExpandButton(NodeExpandPartRendererEventArgs e)
{
if(e.Node.Expanded)
{
if(e.ExpandImageCollapse!=null)
e.Graphics.DrawImage(e.ExpandImageCollapse,e.ExpandPartBounds);
}
else if(e.ExpandImage!=null)
e.Graphics.DrawImage(e.ExpandImage,e.ExpandPartBounds);
}
}
}

View File

@@ -0,0 +1,48 @@
using System;
using System.Drawing;
namespace DevComponents.Tree
{
/// <summary>
/// Represents event arguments for RenderExpandPart event.
/// </summary>
public class NodeExpandPartRendererEventArgs:EventArgs
{
/// <summary>
/// Gets or sets reference to Graphics object, canvas node is rendered on.
/// </summary>
public System.Drawing.Graphics Graphics=null;
/// <summary>
/// Gets or sets the reference to Node object being rendered.
/// </summary>
public DevComponents.Tree.Node Node=null;
/// <summary>Expand part bounds</summary>
public Rectangle ExpandPartBounds=Rectangle.Empty;
/// <summary>Expand part border color</summary>
public Color BorderColor=Color.Empty;
/// <summary>Expand part line color</summary>
public Color ExpandLineColor=Color.Empty;
/// <summary>Expand part background color</summary>
public Color BackColor=Color.Empty;
/// <summary>Expand part target gradient background color</summary>
public Color BackColor2=Color.Empty;
/// <summary>Gradient angle</summary>
public int BackColorGradientAngle=90;
// /// <summary>Indicates whether mouse is over the expand part</summary>
// public bool MouseOver=false;
/// <summary>Expand part image when node is expanded</summary>
public Image ExpandImage=null;
/// <summary>Expand part image when node is collapsed</summary>
public Image ExpandImageCollapse=null;
/// <summary>Internal support for expand button types</summary>
internal eExpandButtonType ExpandButtonType=eExpandButtonType.Ellipse;
/// <summary>
/// Creates new instance of the class and initializes it with default values.
/// </summary>
/// <param name="g">Reference to graphics object.</param>
public NodeExpandPartRendererEventArgs(Graphics g)
{
this.Graphics = g;
}
}
}

View File

@@ -0,0 +1,53 @@
using System;
using System.Drawing;
namespace DevComponents.Tree.Display
{
/// <summary>
/// Represents class that paints rectangular expand button.
/// </summary>
public class NodeExpandRectDisplay:NodeExpandDisplay
{
/// <summary>
/// Draw rectangular type expand button.
/// </summary>
/// <param name="e">Expand button context information.</param>
public override void DrawExpandButton(NodeExpandPartRendererEventArgs e)
{
Rectangle expandPartBounds = e.ExpandPartBounds;
if (expandPartBounds.IsEmpty)
return;
expandPartBounds.Width--;
expandPartBounds.Height--;
Brush brush = GetBackgroundBrush(e);
if (brush != null)
{
e.Graphics.FillRectangle(brush, expandPartBounds);
brush.Dispose();
}
using (Pen pen = GetBorderPen(e))
{
e.Graphics.DrawRectangle(pen, expandPartBounds);
}
if (e.Node.Expanded)
{
using (Pen pen = GetExpandPen(e))
{
e.Graphics.DrawLine(pen, expandPartBounds.X + 2, expandPartBounds.Y + expandPartBounds.Height / 2, expandPartBounds.Right - 2, expandPartBounds.Y + expandPartBounds.Height / 2);
}
}
else
{
using (Pen pen = GetExpandPen(e))
{
e.Graphics.DrawLine(pen, expandPartBounds.X + 2, expandPartBounds.Y + expandPartBounds.Height / 2, expandPartBounds.Right - 2, expandPartBounds.Y + expandPartBounds.Height / 2);
e.Graphics.DrawLine(pen, expandPartBounds.X + expandPartBounds.Width / 2, expandPartBounds.Y + 2, expandPartBounds.X + expandPartBounds.Width / 2, expandPartBounds.Bottom - 2);
}
}
}
}
}

View File

@@ -0,0 +1,102 @@
using System.Drawing;
namespace DevComponents.Tree.Display
{
/// <summary>
/// Describes colors used by Professional Renderer.
/// </summary>
public class NodeProfessionalColorTable
{
/// <summary>
/// Gets or sets the gradient begin color for top part of background.
/// </summary>
public Color NodeTopGradientBegin = ColorScheme.GetColor("B0CCF9");
/// <summary>
/// Gets or sets the middle gradient color for top part of background.
/// </summary>
public Color NodeTopGradientMiddle = ColorScheme.GetColor("E2EDFF"); // Color.FromArgb(242, 245, 250);
/// <summary>
/// Gets or sets the end gradient color for top part of background.
/// </summary>
public Color NodeTopGradientEnd = Color.Empty;
/// <summary>
/// Gets or sets the end gradient type for top part of background.
/// </summary>
public eGradientType NodeTopGradientType = eGradientType.Linear;
/// <summary>
/// Gets or sets the end gradient angle for top part of background.
/// </summary>
public int NodeTopGradientAngle = 90;
/// <summary>
/// Gets or sets the starting gradient color for bottom part of background.
/// </summary>
public Color NodeBottomGradientBegin = ColorScheme.GetColor("75ABFF");
/// <summary>
/// Gets or sets the middle gradient color for bottom part of background.
/// </summary>
public Color NodeBottomGradientMiddle = Color.FromArgb(208, 242, 248);
/// <summary>
/// Gets or sets the end gradient color for bottom part of background.
/// </summary>
public Color NodeBottomGradientEnd = Color.Empty;
/// <summary>
/// Gets or sets the type of the gradient for bottom part of background.
/// </summary>
public eGradientType NodeBottomGradientType = eGradientType.Linear;
/// <summary>
/// Gets or sets the gradient angle for bottom part of background.
/// </summary>
public int NodeBottomGradientAngle = 90;
/// <summary>
/// Gets or sets the starting gradient color for top part of background when mouse is over the node.
/// </summary>
public Color NodeMouseOverTopGradientBegin = ColorScheme.GetColor("B0CCF9");
/// <summary>
/// Gets or sets the middle gradient color for top part of background when mouse is over the node.
/// </summary>
public Color NodeMouseOverTopGradientMiddle = Color.White;
/// <summary>
/// Gets or sets the end gradient color for top part of background when mouse is over the node.
/// </summary>
public Color NodeMouseOverTopGradientEnd = Color.Empty;
/// <summary>
/// Gets or sets the gradient type for top part of background when mouse is over the node.
/// </summary>
public eGradientType NodeMouseOverTopGradientType = eGradientType.Linear;
/// <summary>
/// Gets or sets the gradient angle for top part of background when mouse is over the node.
/// </summary>
public int NodeMouseOverTopGradientAngle = 90;
/// <summary>
/// Gets or sets the starting gradient color for bottom part of background when mouse is over the node.
/// </summary>
public Color NodeMouseOverBottomGradientBegin = ColorScheme.GetColor("6599EA");
/// <summary>
/// Gets or sets the middle gradient color for bottom part of background when mouse is over the node.
/// </summary>
public Color NodeMouseOverBottomGradientMiddle = Color.Cyan;
/// <summary>
/// Gets or sets the end gradient color for bottom part of background when mouse is over the node.
/// </summary>
public Color NodeMouseOverBottomGradientEnd = Color.Empty;
/// <summary>
/// Gets or sets the gradient type for bottom part of background when mouse is over the node.
/// </summary>
public eGradientType NodeMouseOverBottomGradientType = eGradientType.Linear;
/// <summary>
/// Gets or sets the gradient angle for bottom part of background when mouse is over the node.
/// </summary>
public int NodeMouseOverBottomGradientAngle = 90;
// public Color NodeTopGradientBegin=ColorScheme.GetColor("BDCCD9");
// public Color NodeTopGradientMiddle=Color.White;
// public Color NodeTopGradientEnd=ColorScheme.GetColor("406986");
//
// public Color NodeBottomGradientBegin=ColorScheme.GetColor("03436D");
// public Color NodeBottomGradientMiddle=ColorScheme.GetColor("0BC0E9");
// public Color NodeBottomGradientEnd=ColorScheme.GetColor("0C84C1");
}
}

View File

@@ -0,0 +1,213 @@
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
namespace DevComponents.Tree.Display
{
/// <summary>
/// Represents professional rendered which provides extensive rendering above and beyond the NodeSystemRenderer.
/// </summary>
public class NodeProfessionalRenderer : NodeSystemRenderer
{
#region Private Variables
private NodeProfessionalColorTable m_ColorTable=new NodeProfessionalColorTable();
#endregion
/// <summary>
/// Gets or sets the color table used by renderer.
/// </summary>
public NodeProfessionalColorTable ColorTable
{
get { return m_ColorTable;}
set
{
m_ColorTable = value;
}
}
/// <summary>
/// Draws node background. If you need to provide custom rendering this is the method that you should override in your custom rendered. If you
/// do not want default rendering to occur do not call the base implementation. You can call OnRenderNodeBackground method so events can occur.
/// </summary>
/// <param name="e">Information provided for rendering.</param>
public override void DrawNodeBackground(NodeRendererEventArgs e)
{
ElementStyleDisplayInfo di=GetElementStyleDisplayInfo(e.Style,e.Graphics,DisplayHelp.GetDrawRectangle(e.NodeBounds));
PaintBackground(e);
ElementStyleDisplay.PaintBackgroundImage(di);
ElementStyleDisplay.PaintBorder(di);
// Let events occur
OnRenderNodeBackground(e);
}
private void PaintBackgroundPart(Graphics g, Rectangle bounds, GraphicsPath path, Color color1, Color color2, eGradientType gradientType, int gradientAngle)
{
if(color2.IsEmpty)
{
if(!color1.IsEmpty)
{
using(SolidBrush brush=new SolidBrush(color1))
g.FillPath(brush,path);
}
}
else if(!m_ColorTable.NodeTopGradientBegin.IsEmpty)
{
if (gradientType == eGradientType.Linear)
{
Rectangle rb = bounds;
rb.X--;
rb.Height++;
rb.Width += 2;
using (LinearGradientBrush brush = DisplayHelp.CreateLinearGradientBrush(rb, color1, color2, gradientAngle))
{
g.FillPath(brush, path);
}
}
else if (gradientType == eGradientType.Radial)
{
int d = (int)Math.Sqrt(bounds.Width * bounds.Width + bounds.Height * bounds.Height);
GraphicsPath fillPath = new GraphicsPath();
fillPath.AddEllipse(bounds.X - (d - bounds.Width), bounds.Y - (d - bounds.Height) / 2, d, d);
using (PathGradientBrush brush = new PathGradientBrush(fillPath))
{
brush.CenterColor = color1;
brush.SurroundColors = new Color[] { color2 };
g.FillPath(brush, path);
}
fillPath.Dispose();
}
}
}
/// <summary>
/// Paints background of the node.
/// </summary>
/// <param name="e">Context information.</param>
protected virtual void PaintBackground(NodeRendererEventArgs e)
{
Graphics g = e.Graphics;
bool mouseOver = e.Node.IsMouseOver;
Region oldClip = g.Clip;
Rectangle clipRect=e.NodeBounds;
clipRect.Width--;
clipRect.Height--;
g.SetClip(clipRect, CombineMode.Replace);
// Prepare colors
NodeColors colors=new NodeColors();
colors.NodeTopGradientBegin = m_ColorTable.NodeTopGradientBegin;
colors.NodeTopGradientMiddle = m_ColorTable.NodeTopGradientMiddle;
colors.NodeTopGradientEnd = m_ColorTable.NodeTopGradientEnd;
colors.NodeTopGradientType = m_ColorTable.NodeTopGradientType;
colors.NodeTopGradientAngle = m_ColorTable.NodeTopGradientAngle;
colors.NodeBottomGradientBegin = m_ColorTable.NodeBottomGradientBegin;
colors.NodeBottomGradientMiddle = m_ColorTable.NodeBottomGradientMiddle;
colors.NodeBottomGradientEnd = m_ColorTable.NodeBottomGradientEnd;
colors.NodeBottomGradientType = m_ColorTable.NodeBottomGradientType;
colors.NodeBottomGradientAngle = m_ColorTable.NodeBottomGradientAngle;
if(mouseOver)
{
colors.NodeTopGradientBegin = m_ColorTable.NodeMouseOverTopGradientBegin;
colors.NodeTopGradientMiddle = m_ColorTable.NodeMouseOverTopGradientMiddle;
colors.NodeTopGradientEnd = m_ColorTable.NodeMouseOverTopGradientEnd;
colors.NodeTopGradientType = m_ColorTable.NodeMouseOverTopGradientType;
colors.NodeTopGradientAngle = m_ColorTable.NodeMouseOverTopGradientAngle;
colors.NodeBottomGradientBegin = m_ColorTable.NodeMouseOverBottomGradientBegin;
colors.NodeBottomGradientMiddle = m_ColorTable.NodeMouseOverBottomGradientMiddle;
colors.NodeBottomGradientEnd = m_ColorTable.NodeMouseOverBottomGradientEnd;
colors.NodeBottomGradientType = m_ColorTable.NodeMouseOverBottomGradientType;
colors.NodeBottomGradientAngle = m_ColorTable.NodeMouseOverBottomGradientAngle;
}
// Paint Background, Top Part
Rectangle bounds=DisplayHelp.GetDrawRectangle(ElementStyleDisplay.GetBackgroundRectangle(e.Style,e.NodeBounds));
GraphicsPath path;
if (g.SmoothingMode == SmoothingMode.AntiAlias)
{
Rectangle r = bounds;
r.Width--;
path = ElementStyleDisplay.GetBackgroundPath(e.Style, r, eStyleBackgroundPathPart.TopHalf);
}
else
path = ElementStyleDisplay.GetBackgroundPath(e.Style, bounds, eStyleBackgroundPathPart.TopHalf);
path.CloseAllFigures();
Rectangle backRect = bounds;
backRect.Height = backRect.Height/2;
PaintBackgroundPart(g, backRect, path, colors.NodeTopGradientBegin, colors.NodeTopGradientEnd,
colors.NodeTopGradientType, colors.NodeTopGradientAngle);
Rectangle ellipse = new Rectangle(bounds.X, bounds.Y - bounds.Height / 2, bounds.Width, bounds.Height);
GraphicsPath pathFill=new GraphicsPath();
pathFill.AddEllipse(ellipse);
PathGradientBrush pathBrush = new PathGradientBrush(pathFill);
pathBrush.CenterColor = colors.NodeTopGradientMiddle;
pathBrush.SurroundColors = new Color[] { Color.Transparent };
pathBrush.CenterPoint = new PointF(ellipse.X + ellipse.Width / 2, bounds.Y);
Blend blend = new Blend();
blend.Factors = new float[] { 0f, .8f, 1f };
blend.Positions = new float[] { .0f, .8f, 1f };
pathBrush.Blend = blend;
pathFill.Dispose();
g.FillPath(pathBrush, path);
pathBrush.Dispose();
path.Dispose();
// Bottom Part
if (g.SmoothingMode == SmoothingMode.AntiAlias)
{
Rectangle r = bounds;
r.Width--;
path = ElementStyleDisplay.GetBackgroundPath(e.Style, r, eStyleBackgroundPathPart.BottomHalf);
}
else
path = ElementStyleDisplay.GetBackgroundPath(e.Style, bounds, eStyleBackgroundPathPart.BottomHalf);
path.CloseAllFigures();
backRect.Y += backRect.Height;
PaintBackgroundPart(g, backRect, path, colors.NodeBottomGradientBegin, colors.NodeBottomGradientEnd,
colors.NodeBottomGradientType, colors.NodeBottomGradientAngle);
ellipse = new Rectangle(bounds.X, bounds.Y + bounds.Height / 2 - 2, bounds.Width, bounds.Height + 4);
pathFill=new GraphicsPath();
pathFill.AddEllipse(ellipse);
pathBrush = new PathGradientBrush(pathFill);
pathBrush.CenterColor = colors.NodeBottomGradientMiddle;
pathBrush.SurroundColors = new Color[] { Color.Transparent };
pathBrush.CenterPoint = new PointF(ellipse.X + ellipse.Width / 2, bounds.Bottom);
blend = new Blend();
blend.Factors = new float[] { 0f, .5f, 1f };
blend.Positions = new float[] { .0f, .4f, 1f };
pathBrush.Blend = blend;
//path.Dispose();
g.FillPath(pathBrush, path);
pathBrush.Dispose();
pathFill.Dispose();
path.Dispose();
if (oldClip != null)
g.Clip = oldClip;
else
g.ResetClip();
}
private class NodeColors
{
public Color NodeTopGradientBegin;
public Color NodeTopGradientMiddle;
public Color NodeTopGradientEnd;
public eGradientType NodeTopGradientType=eGradientType.Linear;
public int NodeTopGradientAngle=90;
public Color NodeBottomGradientBegin;
public Color NodeBottomGradientMiddle;
public Color NodeBottomGradientEnd;
public eGradientType NodeBottomGradientType=eGradientType.Linear;
public int NodeBottomGradientAngle=90;
}
}
}

View File

@@ -0,0 +1,267 @@
using System;
using System.Drawing;
namespace DevComponents.Tree.Display
{
/// <summary>
/// Represents abstract renderer class for node objects.
/// </summary>
public abstract class NodeRenderer
{
#region Events
/// <summary>
/// Occurs when node background is being drawn.
/// </summary>
public event NodeRendererEventHandler RenderNodeBackground;
/// <summary>
/// Occurs when node expand part is being drawn.
/// </summary>
public event NodeExpandPartRendererEventHandler RenderNodeExpandPart;
/// <summary>
/// Occurs when node command part is being drawn.
/// </summary>
public event NodeCommandPartRendererEventHandler RenderNodeCommandPart;
/// <summary>
/// Occurs when cell bacgkround is being drawn.
/// </summary>
public event NodeCellRendererEventHandler RenderCellBackground;
/// <summary>
/// Occurs when cell check-box is being drawn.
/// </summary>
public event NodeCellRendererEventHandler RenderCellCheckBox;
/// <summary>
/// Occurs when cell image is being drawn.
/// </summary>
public event NodeCellRendererEventHandler RenderCellImage;
/// <summary>
/// Occurs when cell text is being drawn.
/// </summary>
public event NodeCellRendererEventHandler RenderCellText;
/// <summary>
/// Occurs when cell text is being drawn.
/// </summary>
public event SelectionRendererEventHandler RenderSelection;
/// <summary>
/// Occurs when node connector is being drawn.
/// </summary>
public event ConnectorRendererEventHandler RenderConnector;
/// <summary>
/// Occurs when tree background is rendered.
/// </summary>
public event TreeBackgroundRendererEventHandler RenderTreeBackground;
#endregion
#region Private Variables
#endregion
#region Constructor
public NodeRenderer()
{
}
#endregion
#region Internal Implementation
/// <summary>
/// Draws node background. If you need to provide custom rendering this is the method that you should override in your custom rendered. If you
/// do not want default rendering to occur do not call the base implementation. You can call OnRenderNodeBackground method so events can occur.
/// </summary>
/// <param name="e">Information provided for rendering.</param>
public virtual void DrawNodeBackground(NodeRendererEventArgs e)
{
OnRenderNodeBackground(e);
}
/// <summary>
/// Raises RenderNodeBackground event.
/// </summary>
/// <param name="e">Event arguments.</param>
protected virtual void OnRenderNodeBackground(NodeRendererEventArgs e)
{
if(RenderNodeBackground!=null)
RenderNodeBackground(this,e);
}
/// <summary>
/// Draws node expand part. If you need to provide custom rendering this is the method that you should override in your custom rendered. If you
/// do not want default rendering to occur do not call the base implementation. You can call OnRenderNodeExpandPart method so events can occur.
/// </summary>
/// <param name="e">Information provided for rendering.</param>
public virtual void DrawNodeExpandPart(NodeExpandPartRendererEventArgs e)
{
OnRenderNodeExpandPart(e);
}
/// <summary>
/// Raises RenderNodeExpandPart event.
/// </summary>
/// <param name="e"></param>
protected virtual void OnRenderNodeExpandPart(NodeExpandPartRendererEventArgs e)
{
if(RenderNodeExpandPart!=null)
RenderNodeExpandPart(this,e);
}
/// <summary>
/// Draws node command part. If you need to provide custom rendering this is the method that you should override in your custom rendered. If you
/// do not want default rendering to occur do not call the base implementation. You can call OnRenderNodeCommandPart method so events can occur.
/// </summary>
/// <param name="e">Information provided for rendering.</param>
public virtual void DrawNodeCommandPart(NodeCommandPartRendererEventArgs e)
{
OnRenderNodeCommandPart(e);
}
/// <summary>
/// Raises RenderNodeCommandPart event.
/// </summary>
/// <param name="e">Event arguments.</param>
protected virtual void OnRenderNodeCommandPart(NodeCommandPartRendererEventArgs e)
{
if(RenderNodeCommandPart!=null)
RenderNodeCommandPart(this,e);
}
/// <summary>
/// Draws cell background. If you need to provide custom rendering this is the method that you should override in your custom rendered. If you
/// do not want default rendering to occur do not call the base implementation. You can call OnRenderCellBackground method so events can occur.
/// </summary>
/// <param name="e">Information provided for rendering.</param>
public virtual void DrawCellBackground(NodeCellRendererEventArgs e)
{
OnRenderCellBackground(e);
}
/// <summary>
/// Raises RenderCellBackground event.
/// </summary>
/// <param name="e">Event arguments</param>
protected virtual void OnRenderCellBackground(NodeCellRendererEventArgs e)
{
if(RenderCellBackground!=null)
RenderCellBackground(this, e);
}
/// <summary>
/// Draws cell check box. If you need to provide custom rendering this is the method that you should override in your custom rendered. If you
/// do not want default rendering to occur do not call the base implementation. You can call OnRenderCellCheckBox method so events can occur.
/// </summary>
/// <param name="e">Information provided for rendering.</param>
public virtual void DrawCellCheckBox(NodeCellRendererEventArgs e)
{
OnRenderCellCheckBox(e);
}
/// <summary>
/// Raises RenderCellCheckBox event.
/// </summary>
/// <param name="e">Event arguments</param>
protected virtual void OnRenderCellCheckBox(NodeCellRendererEventArgs e)
{
if(RenderCellCheckBox!=null)
RenderCellCheckBox(this, e);
}
/// <summary>
/// Draws cell image. If you need to provide custom rendering this is the method that you should override in your custom rendered. If you
/// do not want default rendering to occur do not call the base implementation. You can call OnRenderCellImage method so events can occur.
/// </summary>
/// <param name="e">Information provided for rendering.</param>
public virtual void DrawCellImage(NodeCellRendererEventArgs e)
{
OnRenderCellImage(e);
}
/// <summary>
/// Raises RenderCellImage event.
/// </summary>
/// <param name="e">Event arguments</param>
protected virtual void OnRenderCellImage(NodeCellRendererEventArgs e)
{
if(RenderCellImage!=null)
RenderCellImage(this, e);
}
/// <summary>
/// Draws cell text. If you need to provide custom rendering this is the method that you should override in your custom rendered. If you
/// do not want default rendering to occur do not call the base implementation. You can call OnRenderCellText method so events can occur.
/// </summary>
/// <param name="e">Information provided for rendering.</param>
public virtual void DrawCellText(NodeCellRendererEventArgs e)
{
OnRenderCellText(e);
}
/// <summary>
/// Raises RenderCellImage event.
/// </summary>
/// <param name="e">Event arguments</param>
protected virtual void OnRenderCellText(NodeCellRendererEventArgs e)
{
if(RenderCellText!=null)
RenderCellText(this, e);
}
/// <summary>
/// Draws selection for SelectedNode. If you need to provide custom rendering this is the method that you should override in your custom rendered. If you
/// do not want default rendering to occur do not call the base implementation. You can call OnRenderSelection method so events can occur.
/// </summary>
/// <param name="e">Information provided for rendering.</param>
public virtual void DrawSelection(SelectionRendererEventArgs e)
{
OnRenderSelection(e);
}
/// <summary>
/// Raises RenderSelection event.
/// </summary>
/// <param name="e">Event data.</param>
protected virtual void OnRenderSelection(SelectionRendererEventArgs e)
{
if(RenderSelection!=null)
RenderSelection(this, e);
}
/// <summary>
/// Draws connector between nodes. If you need to provide custom rendering this is the method that you should override in your custom rendered. If you
/// do not want default rendering to occur do not call the base implementation. You can call OnRenderConnector method so events can occur.
/// </summary>
/// <param name="e">Information provided for rendering.</param>
public virtual void DrawConnector(ConnectorRendererEventArgs e)
{
OnRenderConnector(e);
}
/// <summary>
/// Raises RenderConnector event.
/// </summary>
/// <param name="e">Event data.</param>
protected virtual void OnRenderConnector(ConnectorRendererEventArgs e)
{
if(RenderConnector!=null)
RenderConnector(this, e);
}
/// <summary>
/// Draws the tree background. If you need to provide custom rendering this is the method that you should override in your custom rendered. If you
/// do not want default rendering to occur do not call the base implementation. You can call OnRenderTreeBackground method so events can occur.
/// </summary>
/// <param name="e">Information provided for rendering.</param>
public virtual void DrawTreeBackground(TreeBackgroundRendererEventArgs e)
{
OnRenderTreeBackground(e);
}
/// <summary>
/// Raises RenderTreeBackground event.
/// </summary>
/// <param name="e">Event data.</param>
protected virtual void OnRenderTreeBackground(TreeBackgroundRendererEventArgs e)
{
if(RenderTreeBackground!=null)
RenderTreeBackground(this, e);
}
#endregion
}
}

View File

@@ -0,0 +1,44 @@
using System;
using System.Drawing;
namespace DevComponents.Tree.Display
{
/// <summary>
/// Summary description for NodeRendererEventArgs.
/// </summary>
public class NodeRendererEventArgs:EventArgs
{
/// <summary>
/// Gets or sets reference to Graphics object, canvas node is rendered on.
/// </summary>
public System.Drawing.Graphics Graphics=null;
/// <summary>
/// Gets or sets the reference to Node object being rendered.
/// </summary>
public DevComponents.Tree.Node Node=null;
/// <summary>
/// Gets or sets the absolute node bounds.
/// </summary>
public Rectangle NodeBounds=Rectangle.Empty;
/// <summary>
/// Gets or sets the reference to element style for rendered node or cell. Style provided here is the style
/// for current node or cell state.
/// </summary>
public ElementStyle Style=null;
/// <summary>
/// Creates new instance of the class.
/// </summary>
public NodeRendererEventArgs()
{
}
public NodeRendererEventArgs(Graphics g, Node node, Rectangle bounds, ElementStyle style)
{
this.Graphics = g;
this.Node = node;
this.NodeBounds = bounds;
this.Style = style;
}
}
}

View File

@@ -0,0 +1,51 @@
using System.Drawing;
namespace DevComponents.Tree.Display
{
/// <summary>
/// Represent class that paints selection around node.
/// </summary>
internal class NodeSelectionDisplay
{
public void PaintSelection(SelectionRendererEventArgs info)
{
Rectangle inside=info.Bounds;
inside.Inflate(1,1);
inside.Width--;
inside.Height--;
Rectangle outside=info.Bounds;
outside.Inflate(info.Width,info.Width);
outside.Width--;
outside.Height--;
if(!info.BorderColor.IsEmpty)
{
using(Pen pen=new Pen(info.BorderColor,1))
{
info.Graphics.DrawRectangle(pen,inside);
info.Graphics.DrawRectangle(pen,outside);
}
}
if(!info.FillColor.IsEmpty)
{
using(SolidBrush brush=new SolidBrush(info.FillColor))
{
Region region=new Region(outside);
region.Exclude(inside);
info.Graphics.FillRegion(brush,region);
}
}
}
}
internal class NodeSelectionDisplayInfo
{
public Node Node=null;
public Graphics Graphics=null;
public Rectangle Bounds=Rectangle.Empty;
public Color BorderColor=Color.Empty;
public Color FillColor=Color.Empty;
public int Width=4;
}
}

View File

@@ -0,0 +1,215 @@
using System;
using System.Drawing;
namespace DevComponents.Tree.Display
{
/// <summary>
/// Represents default system node and cell renderer.
/// </summary>
public class NodeSystemRenderer:NodeRenderer
{
#region Private Variables
private NodeExpandEllipseDisplay m_NodeExpandEllipseDisplay=new NodeExpandEllipseDisplay();
private NodeExpandRectDisplay m_NodeExpandRectDisplay=new NodeExpandRectDisplay();
private NodeExpandImageDisplay m_NodeExpandImageDisplay=new NodeExpandImageDisplay();
private NodeCommandDisplay m_NodeCommandDisplay=new NodeCommandDisplay();
private ElementStyleDisplayInfo m_ElementStyleDisplayInfo=new ElementStyleDisplayInfo();
private NodeSelectionDisplay m_SelectionDisplay=new NodeSelectionDisplay();
private CurveConnectorDisplay m_CurveConnectorDisplay=null;
private LineConnectorDisplay m_LineConnectorDisplay=null;
#endregion
#region Internal Implementation
/// <summary>
/// Returns ElementStyleDisplayInfo class that provides information for ElementStyle rendering.
/// </summary>
/// <param name="style">Reference to style.</param>
/// <param name="g">Reference to graphics object.</param>
/// <param name="bounds">Style bounds</param>
/// <returns>New instance of ElementStyleDisplayInfo</returns>
protected ElementStyleDisplayInfo GetElementStyleDisplayInfo(ElementStyle style, Graphics g, Rectangle bounds)
{
m_ElementStyleDisplayInfo.Style=style;
m_ElementStyleDisplayInfo.Graphics=g;
m_ElementStyleDisplayInfo.Bounds=bounds;
return m_ElementStyleDisplayInfo;
}
private NodeConnectorDisplay GetConnectorDisplay(NodeConnector c)
{
NodeConnectorDisplay d=null;
if(c==null)
return null;
switch(c.ConnectorType)
{
case eNodeConnectorType.Curve:
{
if(m_CurveConnectorDisplay==null)
m_CurveConnectorDisplay=new CurveConnectorDisplay();
d=m_CurveConnectorDisplay;
break;
}
case eNodeConnectorType.Line:
{
if(m_LineConnectorDisplay==null)
m_LineConnectorDisplay=new LineConnectorDisplay();
d=m_LineConnectorDisplay;
break;
}
}
return d;
}
/// <summary>
/// Draws node background. If you need to provide custom rendering this is the method that you should override in your custom rendered. If you
/// do not want default rendering to occur do not call the base implementation. You can call OnRenderNodeBackground method so events can occur.
/// </summary>
/// <param name="e">Information provided for rendering.</param>
public override void DrawNodeBackground(NodeRendererEventArgs e)
{
ElementStyleDisplayInfo di=GetElementStyleDisplayInfo(e.Style,e.Graphics,DisplayHelp.GetDrawRectangle(e.NodeBounds));
ElementStyleDisplay.Paint(di);
base.DrawNodeBackground(e);
}
/// <summary>
/// Draws node expand part. If you need to provide custom rendering this is the method that you should override in your custom rendered. If you
/// do not want default rendering to occur do not call the base implementation. You can call OnRenderNodeExpandPart method so events can occur.
/// </summary>
/// <param name="e">Information provided for rendering.</param>
public override void DrawNodeExpandPart(NodeExpandPartRendererEventArgs e)
{
GetExpandDisplay(e.ExpandButtonType).DrawExpandButton(e);
base.DrawNodeExpandPart(e);
}
private NodeExpandDisplay GetExpandDisplay(eExpandButtonType e)
{
NodeExpandDisplay d=null;
switch(e)
{
case eExpandButtonType.Ellipse:
d=m_NodeExpandEllipseDisplay;
break;
case eExpandButtonType.Rectangle:
d=m_NodeExpandRectDisplay;
break;
case eExpandButtonType.Image:
d= m_NodeExpandImageDisplay;
break;
}
return d;
}
/// <summary>
/// Draws node command part. If you need to provide custom rendering this is the method that you should override in your custom rendered. If you
/// do not want default rendering to occur do not call the base implementation. You can call OnRenderNodeCommandPart method so events can occur.
/// </summary>
/// <param name="e">Information provided for rendering.</param>
public override void DrawNodeCommandPart(NodeCommandPartRendererEventArgs e)
{
m_NodeCommandDisplay.DrawCommandButton(e);
base.DrawNodeCommandPart(e);
}
/// <summary>
/// Draws cell background. If you need to provide custom rendering this is the method that you should override in your custom rendered. If you
/// do not want default rendering to occur do not call the base implementation. You can call OnRenderCellBackground method so events can occur.
/// </summary>
/// <param name="e">Information provided for rendering.</param>
public override void DrawCellBackground(NodeCellRendererEventArgs e)
{
ElementStyleDisplayInfo di=GetElementStyleDisplayInfo(e.Style,e.Graphics,DisplayHelp.GetDrawRectangle(e.CellBounds));
ElementStyleDisplay.Paint(di);
base.DrawCellBackground(e);
}
/// <summary>
/// Draws cell check box. If you need to provide custom rendering this is the method that you should override in your custom rendered. If you
/// do not want default rendering to occur do not call the base implementation. You can call OnRenderCellCheckBox method so events can occur.
/// </summary>
/// <param name="e">Information provided for rendering.</param>
public override void DrawCellCheckBox(NodeCellRendererEventArgs e)
{
CellDisplay.PaintCellCheckBox(e);
base.DrawCellCheckBox(e);
}
/// <summary>
/// Draws cell image. If you need to provide custom rendering this is the method that you should override in your custom rendered. If you
/// do not want default rendering to occur do not call the base implementation. You can call OnRenderCellImage method so events can occur.
/// </summary>
/// <param name="e">Information provided for rendering.</param>
public override void DrawCellImage(NodeCellRendererEventArgs e)
{
CellDisplay.PaintCellImage(e);
base.DrawCellImage(e);
}
/// <summary>
/// Draws cell text. If you need to provide custom rendering this is the method that you should override in your custom rendered. If you
/// do not want default rendering to occur do not call the base implementation. You can call OnRenderCellText method so events can occur.
/// </summary>
/// <param name="e">Information provided for rendering.</param>
public override void DrawCellText(NodeCellRendererEventArgs e)
{
CellDisplay.PaintText(e);
base.DrawCellText(e);
}
/// <summary>
/// Draws selection for SelectedNode. If you need to provide custom rendering this is the method that you should override in your custom rendered. If you
/// do not want default rendering to occur do not call the base implementation. You can call OnRenderSelection method so events can occur.
/// </summary>
/// <param name="e">Information provided for rendering.</param>
public override void DrawSelection(SelectionRendererEventArgs e)
{
m_SelectionDisplay.PaintSelection(e);
base.DrawSelection(e);
}
/// <summary>
/// Draws connector between nodes. If you need to provide custom rendering this is the method that you should override in your custom rendered. If you
/// do not want default rendering to occur do not call the base implementation. You can call OnRenderConnector method so events can occur.
/// </summary>
/// <param name="e">Information provided for rendering.</param>
public override void DrawConnector(ConnectorRendererEventArgs e)
{
NodeConnectorDisplay display = GetConnectorDisplay(e.NodeConnector);
if(display!=null)
display.DrawConnector(e);
base.DrawConnector(e);
}
/// <summary>
/// Draws the tree background. If you need to provide custom rendering this is the method that you should override in your custom rendered. If you
/// do not want default rendering to occur do not call the base implementation. You can call OnRenderTreeBackground method so events can occur.
/// </summary>
/// <param name="e">Information provided for rendering.</param>
public override void DrawTreeBackground(TreeBackgroundRendererEventArgs e)
{
TreeGX tree = e.TreeGX;
Graphics g = e.Graphics;
if(!tree.BackColor.IsEmpty)
{
using(SolidBrush brush=new SolidBrush(tree.BackColor))
g.FillRectangle(brush,tree.DisplayRectangle);
}
ElementStyleDisplayInfo info=new ElementStyleDisplayInfo();
info.Bounds=tree.DisplayRectangle;
info.Graphics=g;
info.Style=tree.BackgroundStyle;
ElementStyleDisplay.Paint(info);
base.DrawTreeBackground (e);
}
#endregion
}
}

View File

@@ -0,0 +1,557 @@
using System.Drawing;
using System.Drawing.Drawing2D;
namespace DevComponents.Tree.Display
{
/// <summary>
/// Summary description for NodeTreeDisplay.
/// </summary>
public class NodeTreeDisplay:NodeDisplay
{
#region Private Variables
// Cashed objects
ElementStyleDisplayInfo m_ElementStyleDisplayInfo=new ElementStyleDisplayInfo();
NodeCellRendererEventArgs m_CellDisplayInfo=new NodeCellRendererEventArgs();
// CurveConnectorDisplay m_CurveConnectorDisplay=null;
// LineConnectorDisplay m_LineConnectorDisplay=null;
private NodeSystemRenderer m_SystemRenderer=new NodeSystemRenderer();
private NodeProfessionalRenderer m_ProfRenderer=new NodeProfessionalRenderer();
#endregion
/// <summary>Creates new instance of the class</summary>
/// <param name="tree">Object to initialize class with.</param>
public NodeTreeDisplay(TreeGX tree):base(tree)
{
}
/// <summary>
/// Paints the treee on canvas.
/// </summary>
public override void Paint(Graphics g, Rectangle clipRectangle)
{
base.Paint(g,clipRectangle);
// Paint header
// Paint Nodes...
NodeDisplayContext context=new NodeDisplayContext();
context.Graphics=g;
context.DefaultFont=this.Tree.Font;
context.ClipRectangle=clipRectangle;
context.Offset=this.Offset;
context.Styles=this.Tree.Styles;
// Setup rendering
context.NodeRenderer = m_SystemRenderer;
if(this.Tree.NodeRenderer!=null && this.Tree.RenderMode==eNodeRenderMode.Custom)
context.NodeRenderer=this.Tree.NodeRenderer;
else if(this.Tree.RenderMode==eNodeRenderMode.Professional)
context.NodeRenderer = m_ProfRenderer;
context.NodeRendererEventArgs=new NodeRendererEventArgs();
if(this.Tree.NodeStyle!=null)
context.DefaultNodeStyle=this.Tree.NodeStyle;
else
context.DefaultNodeStyle=GetDefaultNodeStyle();
if(this.Tree.NodeStyleExpanded!=null)
context.ExpandedNodeStyle=this.Tree.NodeStyleExpanded;
if(this.Tree.NodeStyleSelected!=null)
context.SelectedNodeStyle=this.Tree.NodeStyleSelected;
if(this.Tree.NodeStyleMouseOver!=null)
context.MouseOverNodeStyle=this.Tree.NodeStyleMouseOver;
if(this.Tree.CellStyleDefault!=null)
context.CellStyleDefault=this.Tree.CellStyleDefault;
// else
// context.CellStyleDefault=ElementStyle.GetDefaultCellStyle(context.DefaultNodeStyle);
if(this.Tree.CellStyleDisabled!=null)
context.CellStyleDisabled=this.Tree.CellStyleDisabled;
else
context.CellStyleDisabled=ElementStyle.GetDefaultDisabledCellStyle();
if(this.Tree.CellStyleMouseDown!=null)
context.CellStyleMouseDown=this.Tree.CellStyleMouseDown;
if(this.Tree.CellStyleMouseOver!=null)
context.CellStyleMouseOver=this.Tree.CellStyleMouseOver;
if(this.Tree.CellStyleSelected!=null)
context.CellStyleSelected=this.Tree.CellStyleSelected;
else
context.CellStyleSelected=ElementStyle.GetDefaultSelectedCellStyle();
// Setup connector
//context.RootConnectorDisplay=GetConnectorDisplay(this.Tree.RootConnector);
//context.NodesConnectorDisplay=GetConnectorDisplay(this.Tree.NodesConnector);
//context.LinkConnectorDisplay=GetConnectorDisplay(this.Tree.LinkConnector);
context.ConnectorDisplayInfo=new ConnectorRendererEventArgs();
context.ConnectorDisplayInfo.Graphics=context.Graphics;
if(this.Tree.SelectedPathConnector!=null)
{
// Prepare nodes for path display. Downstream nodes are easily recognized when
// path upstream nodes need special treatment to improve performance
if(this.Tree.SelectedNode!=null)
{
Node n=this.Tree.SelectedNode;
while(n!=null)
{
// This marker will be reset once node is painted...
n.SelectedConnectorMarker = true;
n=n.Parent;
}
}
//context.SelectedPathConnectorDisplay=GetConnectorDisplay(this.Tree.SelectedPathConnector);
}
// Setup Node Expander Painter
context.ExpandDisplayInfo=new NodeExpandPartRendererEventArgs(context.Graphics);
context.ExpandDisplayInfo.BackColor=this.Tree.GetColor(this.Tree.ExpandBackColor, this.Tree.ExpandBackColorSchemePart);
context.ExpandDisplayInfo.BackColor2=this.Tree.GetColor(this.Tree.ExpandBackColor2, this.Tree.ExpandBackColor2SchemePart);
context.ExpandDisplayInfo.BackColorGradientAngle=this.Tree.ExpandBackColorGradientAngle;
context.ExpandDisplayInfo.BorderColor=this.Tree.GetColor(this.Tree.ExpandBorderColor, this.Tree.ExpandBorderColorSchemePart);
context.ExpandDisplayInfo.ExpandLineColor=this.Tree.GetColor(this.Tree.ExpandLineColor, this.Tree.ExpandLineColorSchemePart);
context.ExpandDisplayInfo.Graphics=context.Graphics;
context.ExpandDisplayInfo.ExpandButtonType = this.Tree.ExpandButtonType;
context.ExpandDisplayInfo.ExpandImage=this.Tree.ExpandImage;
context.ExpandDisplayInfo.ExpandImageCollapse=this.Tree.ExpandImageCollapse;
//context.ExpandDisplay=this.GetExpandDisplay(this.Tree.ExpandButtonType);
// Setup Selection Display
//context.SelectionDisplay=new NodeSelectionDisplay();
context.SelectionDisplayInfo=new SelectionRendererEventArgs();
context.SelectionDisplayInfo.Graphics=context.Graphics;
context.SelectionDisplayInfo.FillColor=this.Tree.SelectionBoxFillColor;
context.SelectionDisplayInfo.BorderColor=this.Tree.SelectionBoxBorderColor;
context.SelectionDisplayInfo.Width=this.Tree.SelectionBoxSize;
// Setup Node Command Display
//context.CommandDisplay=new NodeCommandDisplay();
context.CommandDisplayInfo=new NodeCommandPartRendererEventArgs(context.Graphics);
context.CommandDisplayInfo.BackColor=this.Tree.GetColor(this.Tree.CommandBackColor, this.Tree.CommandBackColorSchemePart);
context.CommandDisplayInfo.BackColor2=this.Tree.GetColor(this.Tree.CommandBackColor2, this.Tree.CommandBackColor2SchemePart);
context.CommandDisplayInfo.BackColorGradientAngle=this.Tree.CommandBackColorGradientAngle;
context.CommandDisplayInfo.ForeColor=this.Tree.GetColor(this.Tree.CommandForeColor, this.Tree.CommandForeColorSchemePart);
context.CommandDisplayInfo.MouseOverBackColor=this.Tree.GetColor(this.Tree.CommandMouseOverBackColor, this.Tree.CommandMouseOverBackColorSchemePart);
context.CommandDisplayInfo.MouseOverBackColor2=this.Tree.GetColor(this.Tree.CommandMouseOverBackColor2, this.Tree.CommandMouseOverBackColor2SchemePart);
context.CommandDisplayInfo.MouseOverBackColorGradientAngle=this.Tree.CommandMouseOverBackColorGradientAngle;
context.CommandDisplayInfo.MouseOverForeColor=this.Tree.GetColor(this.Tree.CommandMouseOverForeColor, this.Tree.CommandMouseOverForeColorSchemePart);
if(this.Tree.DisplayRootNode!=null)
this.PaintNode(this.Tree.DisplayRootNode, context);
else
this.PaintNodes(this.Tree.Nodes, context);
Node dragNode=this.Tree.GetDragNode();
if(dragNode!=null && dragNode.Parent==null)
{
Point p=context.Offset;
context.Offset=Point.Empty;
PaintNode(dragNode,context);
context.Offset=p;
}
PaintSelection(context);
}
private void PaintSelection(NodeDisplayContext context)
{
if(this.Tree.SelectedNode!=null && this.Tree.SelectedNode.Visible && this.Tree.SelectionBox)
{
context.SelectionDisplayInfo.Node=this.Tree.SelectedNode;
context.SelectionDisplayInfo.Bounds=NodeDisplay.GetNodeRectangle(eNodeRectanglePart.NodeContentBounds, context.SelectionDisplayInfo.Node, context.Offset);
//context.SelectionDisplay.PaintSelection(context.SelectionDisplayInfo);
context.NodeRenderer.DrawSelection(context.SelectionDisplayInfo);
}
}
private void PaintNodes(NodeCollection nodes,NodeDisplayContext context)
{
foreach(Node node in nodes)
{
PaintNode(node, context);
}
}
private void PaintNode(Node node, NodeDisplayContext context)
{
if(!node.Visible)
{
node.SelectedConnectorMarker = false;
return;
}
Rectangle r=NodeDisplay.GetNodeRectangle(eNodeRectanglePart.NodeContentBounds,node,context.Offset);
if(r.IsEmpty)
{
node.SelectedConnectorMarker = false;
return;
}
if(node.Parent!=null && !node.Parent.BoundsRelative.IsEmpty)
{
this.PaintConnector(node, context);
}
if(node.HasLinkedNodes)
{
foreach(LinkedNode linkedNode in node.LinkedNodes)
{
if(!linkedNode.Node.IsVisible)
continue;
this.PaintConnector(node,linkedNode.Node, context,true, linkedNode.ConnectorPoints);
}
}
node.SelectedConnectorMarker = false;
if(r.IntersectsWith(context.ClipRectangle) || context.ClipRectangle.IsEmpty)
PaintSingleNode(node, context);
// else if(node.HasHostedControls) // Move controls to proper location
// MoveHostedControls(node, context);
if(node.Expanded && node.Nodes.Count>0)
PaintNodes(node.Nodes,context);
}
private void PaintSingleNode(Node node, NodeDisplayContext context)
{
Rectangle r=NodeDisplay.GetNodeRectangle(eNodeRectanglePart.NodeContentBounds,node,context.Offset);
NodeRenderer renderer=context.NodeRenderer;
if(node.NodeRenderer!=null && node.RenderMode==eNodeRenderMode.Custom)
renderer = node.NodeRenderer;
// Paint node background
ElementStyle style=context.DefaultNodeStyle.Copy();
if(node.Style!=null)
style=node.Style.Copy();
bool bApllyStyles=true;
if(node.MouseOverNodePart==eMouseOverNodePart.Node && style!=null)
{
ElementStyle mouseOverStyle=context.MouseOverNodeStyle;
if(node.StyleMouseOver!=null)
mouseOverStyle=node.StyleMouseOver;
if (mouseOverStyle != null)
{
style.ApplyStyle(mouseOverStyle);
bApllyStyles = false;
}
}
// On default style apply expanded style
if(bApllyStyles && node.Expanded && style!=null)
{
ElementStyle expandedStyle=context.ExpandedNodeStyle;
if(node.StyleExpanded!=null)
expandedStyle=node.StyleExpanded;
if(expandedStyle!=null)
style.ApplyStyle(expandedStyle);
}
// Apply selected style if needed too
if(bApllyStyles && node.IsSelected && style!=null)
{
ElementStyle selectedStyle=context.SelectedNodeStyle;
if(node.StyleSelected!=null)
selectedStyle=node.StyleSelected;
if(selectedStyle!=null)
style.ApplyStyle(selectedStyle);
}
Region backRegion=null;
if(style!=null)
{
if(style.Font==null)
style.Font=context.DefaultFont;
context.NodeRendererEventArgs.Graphics=context.Graphics;
context.NodeRendererEventArgs.Node = node;
context.NodeRendererEventArgs.NodeBounds = r;
context.NodeRendererEventArgs.Style = style;
renderer.DrawNodeBackground(context.NodeRendererEventArgs);
ElementStyleDisplayInfo di=new ElementStyleDisplayInfo(style,context.Graphics,DisplayHelp.GetDrawRectangle(r));
//ElementStyleDisplay.Paint(di);
backRegion=ElementStyleDisplay.GetStyleRegion(di);
}
if(NodeDisplay.DrawExpandPart(node))
{
r=NodeDisplay.GetNodeRectangle(eNodeRectanglePart.ExpandBounds,node,context.Offset);
context.ExpandDisplayInfo.Node=node;
context.ExpandDisplayInfo.ExpandPartBounds=r;
//context.ExpandDisplayInfo.MouseOver=(node.MouseOverNodePart==eMouseOverNodePart.Expand);
//context.ExpandDisplay.DrawExpandButton(context.ExpandDisplayInfo);
renderer.DrawNodeExpandPart(context.ExpandDisplayInfo);
}
// TODO: Support for display of columns should go here
// if(node.NodesColumnHeaderVisible)
// {
// foreach(ColumnHeader col in node.NodesColumns)
// {
// r=col.Bounds;
// r.Offset(context.Offset);
// r.Offset(node.Bounds.Location);
// using(Pen pen=new Pen(Color.Yellow))
// context.Graphics.DrawRectangle(pen,Display.GetDrawRectangle(r));
// }
// }
Region oldRegion=null;
if(backRegion!=null)
{
oldRegion=context.Graphics.Clip;
context.Graphics.SetClip(backRegion,CombineMode.Replace);
}
if(!node.CommandBoundsRelative.IsEmpty)
{
r=NodeDisplay.GetNodeRectangle(eNodeRectanglePart.CommandBounds,node,context.Offset);
context.CommandDisplayInfo.Node=node;
context.CommandDisplayInfo.CommandPartBounds=r;
context.CommandDisplayInfo.Graphics = context.Graphics;
//context.CommandDisplay.DrawCommandButton(context.CommandDisplayInfo);
renderer.DrawNodeCommandPart(context.CommandDisplayInfo);
context.CommandDisplayInfo.Graphics = null;
}
ElementStyle cellStyle = null;
if(context.CellStyleDefault==null)
{
cellStyle=new ElementStyle();
cellStyle.TextColor = style.TextColor;
cellStyle.TextShadowColor = style.TextShadowColor;
cellStyle.TextShadowOffset = style.TextShadowOffset;
cellStyle.TextAlignment = style.TextAlignment;
cellStyle.TextLineAlignment = style.TextLineAlignment;
cellStyle.WordWrap = style.WordWrap;
cellStyle.Font = style.Font;
}
foreach(Cell cell in node.Cells)
{
if(cell.StyleNormal!=null)
style=cell.StyleNormal;
else if(context.CellStyleDefault!=null)
style=context.CellStyleDefault.Copy();
else
style = cellStyle;
if(!cell.Enabled && cell.StyleDisabled!=null)
style.ApplyStyle(cell.StyleDisabled);
else if(!cell.Enabled && context.CellStyleDisabled!=null)
style.ApplyStyle(context.CellStyleDisabled);
else if(cell.IsMouseDown && cell.StyleMouseDown!=null)
style.ApplyStyle(cell.StyleMouseDown);
else if(cell.IsMouseDown && context.CellStyleMouseDown!=null)
style.ApplyStyle(context.CellStyleMouseDown);
else
{
if(cell.IsSelected && cell.StyleSelected!=null)
style.ApplyStyle(cell.StyleSelected);
else if(cell.IsSelected && context.CellStyleSelected!=null)
style.ApplyStyle(context.CellStyleSelected);
if(cell.IsMouseOver && cell.StyleMouseOver!=null)
style.ApplyStyle(cell.StyleMouseOver);
else if(cell.IsMouseOver && context.CellStyleMouseOver!=null)
style.ApplyStyle(context.CellStyleMouseOver);
}
r=NodeDisplay.GetNodeRectangle(eNodeRectanglePart.NodeBounds,node,context.Offset);
if(style!=null)
{
if(style.Font==null)
style.Font=context.DefaultFont;
Rectangle rCell=cell.BoundsRelative;
Rectangle rText=cell.TextContentBounds;
rCell.Offset(r.Location);
rText.Offset(r.Location);
ElementStyleDisplayInfo di=GetElementStyleDisplayInfo(style,context.Graphics,DisplayHelp.GetDrawRectangle(rCell));
ElementStyleDisplay.Paint(di);
NodeCellRendererEventArgs ci=GetCellDisplayInfo(style,context.Graphics,cell,r.Location, rCell, rText);
if(ci.Cell.CheckBoxVisible)
renderer.DrawCellCheckBox(ci); //CellDisplay.PaintCellCheckBox(ci);
if(!ci.Cell.Images.LargestImageSize.IsEmpty)
renderer.DrawCellImage(ci); //CellDisplay.PaintCellImage(ci);
renderer.DrawCellText(ci) ; //CellDisplay.PaintText(ci);
//CellDisplay.PaintCell(ci);
}
}
if(backRegion!=null)
context.Graphics.SetClip(oldRegion,CombineMode.Replace);
}
private void PaintConnector(Node fromNode, Node toNode, NodeDisplayContext context,bool linkConnector)
{
PaintConnector(fromNode, toNode, context, linkConnector, null);
}
private void PaintConnector(Node fromNode, Node toNode, NodeDisplayContext context,bool linkConnector, ConnectorPointsCollection connectorPoints)
{
bool isRootNode=IsRootNode(fromNode);
// if(context.RootConnectorDisplay==null && isRootNode || context.NodesConnectorDisplay==null && !isRootNode || linkConnector && context.LinkConnectorDisplay==null)
// return;
context.ConnectorDisplayInfo.FromNode=fromNode;
context.ConnectorDisplayInfo.ToNode=toNode;
context.ConnectorDisplayInfo.IsRootNode=isRootNode;
context.ConnectorDisplayInfo.LinkConnector=linkConnector;
if(fromNode.Style!=null)
context.ConnectorDisplayInfo.StyleFromNode=fromNode.Style;
else
context.ConnectorDisplayInfo.StyleFromNode=context.DefaultNodeStyle;
if(toNode.Style!=null)
context.ConnectorDisplayInfo.StyleToNode=toNode.Style;
else
context.ConnectorDisplayInfo.StyleToNode=context.DefaultNodeStyle;
context.ConnectorDisplayInfo.Offset=context.Offset;
//NodeConnectorDisplay display=null;
if(linkConnector)
{
context.ConnectorDisplayInfo.NodeConnector=this.Tree.LinkConnector;
}
else if(toNode.SelectedConnectorMarker)
{
//display = context.SelectedPathConnectorDisplay;
context.ConnectorDisplayInfo.NodeConnector=this.Tree.SelectedPathConnector;
}
else if(toNode.ParentConnector!=null)
{
//display=this.GetConnectorDisplay(toNode.ParentConnector);
context.ConnectorDisplayInfo.NodeConnector=toNode.ParentConnector;
}
else if(isRootNode)
{
//display=context.RootConnectorDisplay;
context.ConnectorDisplayInfo.NodeConnector=this.Tree.RootConnector;
}
else
{
//display=context.NodesConnectorDisplay;
context.ConnectorDisplayInfo.NodeConnector=this.Tree.NodesConnector;
}
if(linkConnector)
{
if (connectorPoints != null && connectorPoints.Count > 0)
context.ConnectorDisplayInfo.ConnectorPoints=connectorPoints;
}
else
{
if(connectorPoints!=null)
context.ConnectorDisplayInfo.ConnectorPoints=connectorPoints;
else if(toNode.ParentConnectorPoints.Count>0)
context.ConnectorDisplayInfo.ConnectorPoints=toNode.ParentConnectorPoints;
else
context.ConnectorDisplayInfo.ConnectorPoints=null;
}
context.NodeRenderer.DrawConnector(context.ConnectorDisplayInfo);
//if(display!=null)
// display.DrawConnector(context.ConnectorDisplayInfo);
}
private void PaintConnector(Node toNode, NodeDisplayContext context)
{
PaintConnector(toNode.Parent, toNode, context,false);
}
// private void MoveHostedControls(Node node, NodeDisplayContext context)
// {
// foreach(Cell cell in node.Cells)
// {
// if(cell.HostedControl!=null && cell.HostedControl.Visible)
// {
// Rectangle bounds = NodeDisplay.GetCellRectangle(eCellRectanglePart.TextBounds, cell, context.Offset);
// if(cell.HostedControl.Bounds!=bounds)
// cell.HostedControl.Bounds=bounds;
// return;
// }
// }
// }
private ElementStyleDisplayInfo GetElementStyleDisplayInfo(ElementStyle style, Graphics g, Rectangle bounds)
{
m_ElementStyleDisplayInfo.Style=style;
m_ElementStyleDisplayInfo.Graphics=g;
m_ElementStyleDisplayInfo.Bounds=bounds;
return m_ElementStyleDisplayInfo;
}
private NodeCellRendererEventArgs GetCellDisplayInfo(ElementStyle style, Graphics g, Cell cell, Point cellOffset, Rectangle cellBounds, Rectangle cellTextBounds)
{
m_CellDisplayInfo.Cell=cell;
m_CellDisplayInfo.Graphics=g;
m_CellDisplayInfo.Style=style;
m_CellDisplayInfo.CellOffset=cellOffset;
m_CellDisplayInfo.CellBounds = cellBounds;
m_CellDisplayInfo.CellTextBounds = cellTextBounds;
return m_CellDisplayInfo;
}
// private NodeConnectorDisplay GetConnectorDisplay(NodeConnector c)
// {
// NodeConnectorDisplay d=null;
// if(c==null)
// return null;
//
// switch(c.ConnectorType)
// {
// case eNodeConnectorType.Curve:
// {
// if(m_CurveConnectorDisplay==null)
// m_CurveConnectorDisplay=new CurveConnectorDisplay();
// d=m_CurveConnectorDisplay;
// break;
// }
// case eNodeConnectorType.Line:
// {
// if(m_LineConnectorDisplay==null)
// m_LineConnectorDisplay=new LineConnectorDisplay();
// d=m_LineConnectorDisplay;
// break;
// }
// }
// return d;
// }
private class NodeDisplayContext
{
public Graphics Graphics=null;
public Font DefaultFont=null;
public Rectangle ClipRectangle=Rectangle.Empty;
public Point Offset=Point.Empty;
public ElementStyle DefaultNodeStyle=null;
public ElementStyle ExpandedNodeStyle=null;
public ElementStyle SelectedNodeStyle=null;
public ElementStyle MouseOverNodeStyle=null;
public ElementStyle CellStyleDefault=null;
public ElementStyle CellStyleMouseDown=null;
public ElementStyle CellStyleMouseOver=null;
public ElementStyle CellStyleSelected=null;
public ElementStyle CellStyleDisabled=null;
public ElementStyleCollection Styles=null;
//public NodeConnectorDisplay RootConnectorDisplay=null;
//public NodeConnectorDisplay NodesConnectorDisplay=null;
//public NodeConnectorDisplay LinkConnectorDisplay=null;
//public NodeConnectorDisplay SelectedPathConnectorDisplay=null;
public ConnectorRendererEventArgs ConnectorDisplayInfo=null;
public NodeExpandPartRendererEventArgs ExpandDisplayInfo=null;
//public NodeExpandDisplay ExpandDisplay=null;
//public NodeSelectionDisplay SelectionDisplay=null;
public SelectionRendererEventArgs SelectionDisplayInfo=null;
//public NodeCommandDisplay CommandDisplay=null;
public NodeCommandPartRendererEventArgs CommandDisplayInfo=null;
public bool SelectedNodePath=false;
public NodeRenderer NodeRenderer=null;
public NodeRendererEventArgs NodeRendererEventArgs=null;
}
}
}

View File

@@ -0,0 +1,36 @@
using System;
using System.Drawing;
namespace DevComponents.Tree
{
/// <summary>
/// Data form RenderSelection event.
/// </summary>
public class SelectionRendererEventArgs : EventArgs
{
/// <summary>
/// Gets or sets reference to Graphics object, canvas node is rendered on.
/// </summary>
public System.Drawing.Graphics Graphics=null;
/// <summary>
/// Gets or sets the reference to selected Node object.
/// </summary>
public DevComponents.Tree.Node Node=null;
/// <summary>
/// Gets or sets the selection bounds.
/// </summary>
public Rectangle Bounds=Rectangle.Empty;
/// <summary>
/// Gets or sets border color of the selection rectangle.
/// </summary>
public Color BorderColor=Color.Empty;
/// <summary>
/// Gets or sets fill color of the selection rectangle.
/// </summary>
public Color FillColor=Color.Empty;
/// <summary>
/// Gets or sets the width in pixels of the border of the selection rectangle.
/// </summary>
public int Width=4;
}
}

View File

@@ -0,0 +1,31 @@
using System;
using System.Drawing;
namespace DevComponents.Tree.Display
{
/// <summary>
/// Provides data for tree background rendering events.
/// </summary>
public class TreeBackgroundRendererEventArgs
{
/// <summary>
/// Gets or sets reference to Graphics object, canvas tree background is rendered on.
/// </summary>
public System.Drawing.Graphics Graphics=null;
/// <summary>
/// Gets or sets the reference to TreeGX control.
/// </summary>
public TreeGX TreeGX = null;
/// <summary>
/// Creates new instance of the class and initializes it with default values.
/// </summary>
/// <param name="g">Reference to graphics object.</param>
public TreeBackgroundRendererEventArgs(Graphics g, TreeGX tree)
{
this.Graphics = g;
this.TreeGX = tree;
}
}
}