335 lines
8.5 KiB
C#
335 lines
8.5 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|