using System;
using System.Drawing;
using System.Drawing.Drawing2D;
namespace DevComponents.AdvTree
{
namespace Display
{
///
/// Base class for drawing node connectors.
///
public abstract class NodeConnectorDisplay
{
//private bool m_RootNode=false;
//private bool m_DrawRootAllLevels=false;
//private bool m_EndCap=true;
//private bool m_DrawConnectorUnderNodes=true;
///
/// Creates new instance of the object.
///
public NodeConnectorDisplay()
{
}
///
/// Draws connector line between two nodes.
///
/// Connector context information.
public virtual void DrawConnector(ConnectorRendererEventArgs info){}
/////
///// Returns the connector starting coordinates.
/////
///// Connector display information.
///// Point object.
//protected virtual 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
///// Returns true if fromNode is above the toNode.
/////
///// From Node object.
///// To Node object
///// True if fromNode is above toNode.
//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;
//}
/////
///// Returns true if fromNode is below toNode.
/////
///// From Node object.
///// To Node object.
///// True if fromNode is below toNode.
//protected bool IsBelow(Node fromNode, Node toNode)
//{
// int toMidPoint=toNode.BoundsRelative.Top+toNode.BoundsRelative.Height/2;
// if(fromNode.BoundsRelative.Bottom
///// Returns whether connector is extended to underline the node.
/////
///// Refernce to Node style.
///// True if node should be underlined by connector.
//protected bool UnderlineNode(ElementStyle nodeStyle)
//{
// if(!nodeStyle.PaintBottomBorder && !nodeStyle.PaintTopBorder &&
// !nodeStyle.PaintLeftBorder && !nodeStyle.PaintRightBorder)
// return true;
// return false;
//}
/////
///// Returns the connector end point. The array of end points. Two valid points will be returned if node needs to be underlined by connector.
/////
///// Connector display info.
///// Array of point objects.
//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 = 0; // 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
///// Returns the offest for the node connector cap.
/////
///// Cap type.
///// Cap size.
/////
//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;
//}
/////
///// Returns true if source node is on the left side of the target node.
/////
///// Reference to source node.
///// Reference to target node.
///// True if source is on the left side of target.
//protected bool IsOnLeftSide(Node source, Node target)
//{
// if((source.BoundsRelative.Left+source.BoundsRelative.Width/2)>target.BoundsRelative.Left)
// return true;
// return false;
//}
///
/// Returns new instance of pen object for node connector line. Caller is responsible for
/// disposing of this object.
///
/// Node connector display info.
/// New instance of Pen object.
protected Pen GetLinePen(ConnectorRendererEventArgs info)
{
Pen pen = new Pen(info.NodeConnector.LineColor, info.NodeConnector.LineWidth);
pen.DashStyle = info.NodeConnector.DashStyle;
return pen;
}
/////
///// Returns new instance of pen object for the end node connector line. Caller is responsible for
///// disposing of this object.
/////
///// Node connector display info.
///// New instance of Pen object.
//protected Pen GetEndLinePen(ConnectorRendererEventArgs info)
//{
// return new Pen(info.NodeConnector.LineColor,EndLineWidth);
//}
/////
///// Returns new instance of pen object for the node underline line. Caller is responsible for
///// disposing of this object.
/////
///// Node connector display info.
///// New instance of Pen object.
//protected Pen GetEndUnderlinePen(ConnectorRendererEventArgs info)
//{
// return new Pen(info.NodeConnector.LineColor,EndLineWidth);
//}
//private int EndLineWidth
//{
// get {return 1;}
//}
// ///
// /// Draws straight line connector between start and end point.
// ///
// /// Node connector display info.
// /// Start point.
// /// End point.
// /// Underline end point if any.
// protected void DrawStraightLineConnector(ConnectorRendererEventArgs info, Point pStart, Point pEnd)
// {
// using (Pen pen = this.GetLinePen(info))
// {
// if (pen.DashStyle != DashStyle.Solid)
// {
// SmoothingMode sm = info.Graphics.SmoothingMode;
// info.Graphics.SmoothingMode = SmoothingMode.Default;
// info.Graphics.DrawLine(pen, pStart, pEnd);
// info.Graphics.SmoothingMode = sm;
// }
// else
// info.Graphics.DrawLine(pen, pStart, pEnd);
// }
// }
// ///
// /// Draws straight line connector between start and end point.
// ///
// /// Node connector display info.
// /// Start point.
// /// End point.
// /// Underline end point if any.
// 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.XpEnd.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);
// 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;
//}
}
}
///
/// Represents custom connector path info.
///
internal class ConnectorPointInfo
{
public Point[] Points1=null;
public Point[] Points2=null;
}
}