592 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			592 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System;
 | |
| using System.Drawing;
 | |
| using System.Collections;
 | |
| 
 | |
| namespace DevComponents.Tree.Layout
 | |
| {
 | |
| 	/// <summary>
 | |
| 	/// Summary description for NodeLayout.
 | |
| 	/// </summary>
 | |
| 	internal abstract class NodeLayout
 | |
| 	{
 | |
| 		#region Private Variables
 | |
| 		protected int m_Height=0;
 | |
| 		protected int m_Width=0;
 | |
| 		protected TreeGX m_Tree=null;
 | |
| 		protected Rectangle m_ClientArea;
 | |
| 		//protected int m_ExpandAreaWidth=8;
 | |
|         private Size m_ExpandPartSize = new Size(9, 9);
 | |
| 		private int m_CommandAreaWidth=10;
 | |
| 		private int m_TreeLayoutChildNodeIndent = 16;
 | |
| 
 | |
| 		private System.Windows.Forms.LeftRightAlignment m_LeftRight=System.Windows.Forms.LeftRightAlignment.Left;
 | |
| 		private int m_NodeVerticalSpacing=0;
 | |
| 		private int m_NodeHorizontalSpacing=0;
 | |
| 		private CellLayout m_CellLayout=null;
 | |
| 		private Graphics m_Graphics=null;
 | |
| 		#endregion
 | |
| 
 | |
| 		public NodeLayout(TreeGX treeControl, Rectangle clientArea)
 | |
| 		{
 | |
| 			m_Tree=treeControl;
 | |
| 			m_ClientArea=clientArea;
 | |
| 		}
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// Performs layout of the nodes inside of the tree control.
 | |
| 		/// </summary>
 | |
| 		public virtual void PerformLayout()
 | |
| 		{
 | |
| 		}
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// Performs layout for single unassigned node. Node does not have to be part of the tree control.
 | |
| 		/// </summary>
 | |
| 		/// <param name="node">Node to perform layout on.</param>
 | |
| 		public virtual void PerformSingleNodeLayout(Node node)
 | |
| 		{
 | |
| 			if(node==null)
 | |
| 				return;
 | |
| 
 | |
| 			this.PrepareStyles();
 | |
| 			// Get default Columns
 | |
| 
 | |
| 			System.Drawing.Graphics graphics=this.GetGraphics();
 | |
| 			try
 | |
| 			{
 | |
| 				NodeLayoutContextInfo layoutInfo=this.GetDefaultNodeLayoutContextInfo(graphics);
 | |
| 				layoutInfo.ContextNode=node;
 | |
| 				LayoutNode(layoutInfo);
 | |
| 			}
 | |
| 			finally
 | |
| 			{
 | |
| 				graphics.Dispose();
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		public int Width
 | |
| 		{
 | |
| 			get {return m_Width;}
 | |
| 		}
 | |
| 
 | |
| 		public int Height
 | |
| 		{
 | |
| 			get {return m_Height;}
 | |
| 		}
 | |
| 
 | |
| 		public Rectangle ClientArea
 | |
| 		{
 | |
| 			get {return m_ClientArea;}
 | |
| 			set {m_ClientArea=value;}
 | |
| 		}
 | |
| 		
 | |
| 		public Graphics Graphics
 | |
| 		{
 | |
| 			get { return m_Graphics;}
 | |
| 			set { m_Graphics = value;}
 | |
| 		}
 | |
| 		
 | |
| 		internal bool DisposeGraphics
 | |
| 		{
 | |
| 			get
 | |
| 			{
 | |
| 				return (m_Graphics == null);
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		protected virtual System.Drawing.Graphics GetGraphics()
 | |
| 		{
 | |
| 			if(m_Graphics!=null)
 | |
| 				return m_Graphics;
 | |
| 			
 | |
| 			Graphics g=m_Tree.CreateGraphics();
 | |
| 			if(m_Tree.AntiAlias)
 | |
| 			{
 | |
| 				g.SmoothingMode=System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
 | |
| 				g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
 | |
| 			}
 | |
| 			return g;
 | |
| 		}
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// Resizes all styles and prepares them for layout.
 | |
| 		/// </summary>
 | |
| 		protected virtual void PrepareStyles()
 | |
| 		{
 | |
| 			// Resize styles if needed
 | |
| 			foreach(ElementStyle es in m_Tree.Styles)
 | |
| 			{
 | |
| 				if(es.SizeChanged)
 | |
| 					ElementStyleLayout.CalculateStyleSize(es,m_Tree.Font);
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// Returns default top-level columns for tree control.
 | |
| 		/// </summary>
 | |
| 		/// <returns>Returns array list of ColumnInfo objects.</returns>
 | |
| 		protected virtual ArrayList GetDefaultColumnInfo()
 | |
| 		{
 | |
| 			ArrayList ci=new ArrayList();
 | |
| 			
 | |
| 			ColumnHeaderCollection columns=m_Tree.Columns;
 | |
| 			if(columns!=null)
 | |
| 			{
 | |
| 				foreach(ColumnHeader h in columns)
 | |
| 				{
 | |
| 					ci.Add(new ColumnInfo(h.Bounds.Width, h.Visible));
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			return ci;
 | |
| 		}
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// Returns column information for a given node.
 | |
| 		/// </summary>
 | |
| 		/// <param name="node">Node to return column information for</param>
 | |
| 		/// <returns>Returns array list of ColumnInfo objects or null if there are no columns defined.</returns>
 | |
| 		protected virtual ArrayList GetNodeColumnInfo(Node node)
 | |
| 		{
 | |
| 			if(node.NodesColumns.Count==0)
 | |
| 				return null;
 | |
| 
 | |
| 			ArrayList ci=new ArrayList();
 | |
| 			foreach(ColumnHeader h in node.NodesColumns)
 | |
| 			{
 | |
| 				ci.Add(new ColumnInfo(h.Width.Absolute, h.Visible));
 | |
| 			}
 | |
| 			return ci;
 | |
| 		}
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// Gets or sets the vertical spacing between nodes in pixels.
 | |
| 		/// </summary>
 | |
| 		public virtual int NodeVerticalSpacing
 | |
| 		{
 | |
| 			get {return m_NodeVerticalSpacing;}
 | |
| 			set {m_NodeVerticalSpacing=value;}
 | |
| 		}
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// Gets or sets the horizontal spacing between nodes in pixels.
 | |
| 		/// </summary>
 | |
| 		public virtual int NodeHorizontalSpacing
 | |
| 		{
 | |
| 			get {return m_NodeHorizontalSpacing;}
 | |
| 			set {m_NodeHorizontalSpacing=value;}
 | |
| 		}
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// Gets or sets the child node indent in pixels.
 | |
| 		/// </summary>
 | |
| 		public virtual int TreeLayoutChildNodeIndent
 | |
| 		{
 | |
| 			get {return m_TreeLayoutChildNodeIndent; }
 | |
| 			set { m_TreeLayoutChildNodeIndent = value; }
 | |
| 		}
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// Returns column header collection for the given column template name.
 | |
| 		/// </summary>
 | |
| 		/// <param name="name">Name of the column template.</param>
 | |
| 		/// <returns>Column header collection or null if template name cannot be found.</returns>
 | |
| 		public virtual ColumnHeaderCollection GetColumnHeader(string name)
 | |
| 		{
 | |
| 			if(name=="" || name==null)
 | |
| 				return null;
 | |
| 			return m_Tree.Headers.GetByName(name).Columns;
 | |
| 		}
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// Returns width of the expand button area. Default is 8 pixels.
 | |
| 		/// </summary>
 | |
| 		protected virtual int ExpandAreaWidth
 | |
| 		{
 | |
| 			get {return Dpi.Width(m_ExpandPartSize.Width);}
 | |
| 		}
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// Gets or sets width of command button area. Default is 8 pixels.
 | |
| 		/// </summary>
 | |
| 		public virtual int CommandAreaWidth
 | |
| 		{
 | |
| 			get {return m_CommandAreaWidth;}
 | |
| 			set {m_CommandAreaWidth=value;}
 | |
| 		}
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// Sets the position and size of the node command button.
 | |
| 		/// </summary>
 | |
| 		/// <param name="layoutInfo">Node layout context information</param>
 | |
| 		protected virtual void LayoutCommandPart(NodeLayoutContextInfo layoutInfo, ElementStyle nodeStyle)
 | |
| 		{
 | |
| 			// Command part is right-aligned just before the node border
 | |
| 			Rectangle bounds=new Rectangle(layoutInfo.ContextNode.ContentBounds.Right-this.CommandAreaWidth-
 | |
| 				ElementStyleLayout.StyleSpacing(nodeStyle,eSpacePart.Border,eStyleSide.Right),layoutInfo.ContextNode.ContentBounds.Y+
 | |
| 				ElementStyleLayout.StyleSpacing(nodeStyle,eSpacePart.Border,eStyleSide.Top), 
 | |
| 				this.CommandAreaWidth, layoutInfo.ContextNode.ContentBounds.Height-
 | |
| 				ElementStyleLayout.StyleSpacing(nodeStyle,eSpacePart.Border,eStyleSide.Top)-
 | |
| 				ElementStyleLayout.StyleSpacing(nodeStyle,eSpacePart.Border,eStyleSide.Bottom));
 | |
| //			Rectangle bounds=new Rectangle(layoutInfo.ContextNode.ContentBounds.Right-this.CommandAreaWidth-
 | |
| //				ElementStyleLayout.StyleSpacing(nodeStyle,eSpacePart.Border,eStyleSide.Right),layoutInfo.ContextNode.ContentBounds.Y, 
 | |
| //				this.CommandAreaWidth, layoutInfo.ContextNode.ContentBounds.Height);
 | |
| 			layoutInfo.ContextNode.CommandBoundsRelative=bounds;
 | |
| 		}
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// Determines the rectangle of the +/- part of the tree node that is used to expand node.
 | |
| 		/// </summary>
 | |
| 		/// <param name="layoutInfo">Node layout context information</param>
 | |
| 		protected virtual void LayoutExpandPart(NodeLayoutContextInfo layoutInfo, bool bLeftNode)
 | |
| 		{
 | |
| 			Node node=layoutInfo.ContextNode;
 | |
| 
 | |
| 			Size partSize=Dpi.Size(GetExpandPartSize());
 | |
| 
 | |
| 			Rectangle bounds=new Rectangle(0,0,partSize.Width,partSize.Height);
 | |
| 			
 | |
| 			bounds.Y=(node.BoundsRelative.Height-bounds.Height)/2;
 | |
| 
 | |
| 			if(bLeftNode)
 | |
| 				bounds.X=(this.ExpandAreaWidth-bounds.Width)/2;
 | |
| 			else
 | |
| 				bounds.X=node.BoundsRelative.Right-this.ExpandAreaWidth+(this.ExpandAreaWidth-partSize.Width)/2;
 | |
| 
 | |
| 			node.SetExpandPartRectangle(bounds);
 | |
| 		}
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// Returns the size of the node expand part.
 | |
| 		/// </summary>
 | |
| 		/// <returns>Size of the expand part, default 8,8.</returns>
 | |
| 		protected virtual Size GetExpandPartSize()
 | |
| 		{
 | |
| 			return m_ExpandPartSize;
 | |
| 		}
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// Gets or sets the size of the expand part that is expanding/collapsing the node. Default value is 8,8.
 | |
| 		/// </summary>
 | |
| 		public System.Drawing.Size ExpandPartSize
 | |
| 		{
 | |
| 			get {return m_ExpandPartSize;}
 | |
| 			set 
 | |
|             {
 | |
|                 m_ExpandPartSize=value;
 | |
|             }
 | |
| 		}
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// Provides the layout for single node.
 | |
| 		/// </summary>
 | |
| 		/// <param name="layoutInfo">Layout information.</param>
 | |
| 		protected virtual void LayoutNode(NodeLayoutContextInfo layoutInfo)
 | |
| 		{
 | |
| //			if(!layoutInfo.ContextNode.SizeChanged)
 | |
| //				return;
 | |
| 
 | |
| 			bool bHasExpandPart=this.HasExpandPart(layoutInfo);
 | |
| 			bool bHasCommandPart=this.HasCommandPart(layoutInfo);
 | |
| 
 | |
| 			Node node=layoutInfo.ContextNode;
 | |
| 			
 | |
| 			Rectangle nodeRect=Rectangle.Empty;
 | |
| 			Rectangle nodeContentRect=Rectangle.Empty; // Node content rect excludes expand rect
 | |
| 
 | |
| 			int height=0, width=0;
 | |
| 			
 | |
| 			// Left node relative to the main root node...
 | |
| 			bool bLeftNode=(layoutInfo.MapPositionNear && layoutInfo.LeftToRight);
 | |
| 			if(bLeftNode && bHasExpandPart || this.ReserveExpandPartSpace)
 | |
| 			{
 | |
| 				width+=(this.ExpandAreaWidth+this.GetCellLayout().CellPartSpacing);
 | |
| 			}
 | |
| 
 | |
| 			int x=width;		// relative to 0,0 of the node
 | |
| 			int y=0;			// Relative to 0,0 of the node
 | |
| 			
 | |
| 			// Apply node style
 | |
| 			ElementStyle nodeStyle=null;
 | |
| 			if(node.Expanded && node.StyleExpanded!=null)
 | |
| 				nodeStyle=node.StyleExpanded;
 | |
| 			else if(node.Style!=null)
 | |
| 				nodeStyle=node.Style;
 | |
| 			else
 | |
| 				nodeStyle=layoutInfo.DefaultNodeStyle;
 | |
| 
 | |
| 			nodeContentRect.X=x;
 | |
| 
 | |
| 			if(nodeStyle!=null)
 | |
| 			{
 | |
| 				x+=ElementStyleLayout.LeftWhiteSpace(nodeStyle); // nodeStyle.MarginLeft+nodeStyle.PaddingLeft;
 | |
| 				y+=ElementStyleLayout.TopWhiteSpace(nodeStyle); //nodeStyle.MarginTop+nodeStyle.PaddingTop;
 | |
| 				nodeContentRect.X+=nodeStyle.MarginLeft;
 | |
| 				nodeContentRect.Y+=nodeStyle.MarginTop;
 | |
| 			}
 | |
| 
 | |
| 			Size size=this.GetCellLayout().LayoutCells(layoutInfo,x,y);
 | |
| 
 | |
| 			node.SetCellsBounds(new Rectangle(x,y,size.Width,size.Height));
 | |
| 
 | |
| 			height=size.Height;
 | |
| 			width+=size.Width;
 | |
| 
 | |
| 			nodeContentRect.Width=size.Width;
 | |
| 			nodeContentRect.Height=size.Height;
 | |
| 
 | |
| 			if(nodeStyle!=null)
 | |
| 			{
 | |
| 				nodeContentRect.Width+=(ElementStyleLayout.StyleSpacing(nodeStyle,eSpacePart.Padding | eSpacePart.Border,eStyleSide.Left)+
 | |
| 					ElementStyleLayout.StyleSpacing(nodeStyle,eSpacePart.Padding | eSpacePart.Border,eStyleSide.Right));
 | |
| 				nodeContentRect.Height+=(ElementStyleLayout.StyleSpacing(nodeStyle,eSpacePart.Padding | eSpacePart.Border,eStyleSide.Top)+
 | |
| 					ElementStyleLayout.StyleSpacing(nodeStyle,eSpacePart.Padding | eSpacePart.Border,eStyleSide.Bottom));
 | |
| 
 | |
| 				width+=(ElementStyleLayout.HorizontalStyleWhiteSpace(nodeStyle));
 | |
| 				height+=(ElementStyleLayout.VerticalStyleWhiteSpace(nodeStyle));
 | |
| 			}
 | |
| 
 | |
| 			if(!bLeftNode && bHasExpandPart)
 | |
| 				width+=this.ExpandAreaWidth;
 | |
| 
 | |
| 			if(bHasCommandPart)
 | |
| 			{
 | |
| 				width+=this.CommandAreaWidth;
 | |
| 				nodeContentRect.Width+=this.CommandAreaWidth;
 | |
| 			}
 | |
| 
 | |
| 			nodeRect.Height=height;
 | |
| 			nodeRect.Width=width;
 | |
| 			node.SetBounds(nodeRect);
 | |
| 			node.SetContentBounds(nodeContentRect);
 | |
| 
 | |
| 			if(bHasCommandPart)
 | |
| 				LayoutCommandPart(layoutInfo, nodeStyle);
 | |
| 			else
 | |
| 				node.CommandBoundsRelative=Rectangle.Empty;
 | |
| 
 | |
| 			if(bHasExpandPart)
 | |
| 				LayoutExpandPart(layoutInfo,bLeftNode);
 | |
| 			else
 | |
| 				node.SetExpandPartRectangle(Rectangle.Empty);
 | |
| 
 | |
| 			node.SizeChanged=false;
 | |
| 
 | |
| 			// Calculate size and location of node column header if any
 | |
| 			//if(node.NodesColumnHeaderVisible)
 | |
| 			{
 | |
| 				//layoutInfo.Left+=this.NodeLevelOffset;
 | |
| 				LayoutColumnHeader(layoutInfo);
 | |
| 				//layoutInfo.Left-=this.NodeLevelOffset;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// Returns true if given node has expand part.
 | |
| 		/// </summary>
 | |
| 		/// <param name="layoutInfo">Layout context information.</param>
 | |
| 		/// <returns></returns>
 | |
| 		protected virtual bool HasExpandPart(NodeLayoutContextInfo layoutInfo)
 | |
| 		{
 | |
| 			Node node=layoutInfo.ContextNode;
 | |
| 			if(node.ExpandVisibility==eNodeExpandVisibility.Auto)
 | |
| 			{
 | |
| 				if(IsRootNode(node) && !RootHasExpandedPart || !NodeOperations.GetAnyVisibleNodes(node))
 | |
| 					return false;
 | |
| 				return true;
 | |
| 			}
 | |
| 			else
 | |
| 				return (node.ExpandVisibility==eNodeExpandVisibility.Visible);
 | |
| 		}
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// Returns whether given node has command part.
 | |
| 		/// </summary>
 | |
| 		/// <param name="layoutInfo">Layout context information.</param>
 | |
| 		/// <returns>True if command part should be drawn otherwise false.</returns>
 | |
| 		protected virtual bool HasCommandPart(NodeLayoutContextInfo layoutInfo)
 | |
| 		{
 | |
| 			return layoutInfo.ContextNode.CommandButton;
 | |
| 		}
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// Returns true if root node should have expanded part
 | |
| 		/// </summary>
 | |
| 		protected virtual bool RootHasExpandedPart
 | |
| 		{
 | |
| 			get {return true;}
 | |
| 		}
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// Returns true if expand part space should be accounted for even if they expand part is not visible or need to be displayed. Default value is false.
 | |
| 		/// </summary>
 | |
| 		protected virtual bool ReserveExpandPartSpace
 | |
| 		{
 | |
| 			get
 | |
| 			{
 | |
| 				return false;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// Returns class responsible for cell layout.
 | |
| 		/// </summary>
 | |
| 		/// <returns>Cell layout class.</returns>
 | |
| 		protected virtual CellLayout GetCellLayout()
 | |
| 		{
 | |
| 			if(m_CellLayout==null)
 | |
| 				m_CellLayout=new CellLayout();
 | |
| 			return m_CellLayout;
 | |
| 		}
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// Offsets node location and location of it's child nodes bounds.
 | |
| 		/// </summary>
 | |
| 		/// <param name="node">Node to offset.</param>
 | |
| 		/// <param name="x">Horizontal offset.</param>
 | |
| 		/// <param name="y">Vertical offset.</param>
 | |
| 		protected virtual void OffsetNodeLocation(Node node, int x, int y)
 | |
| 		{
 | |
| 			node.SetBounds(new Rectangle(node.BoundsRelative.X+x,node.BoundsRelative.Y+y,node.BoundsRelative.Width,node.BoundsRelative.Height));
 | |
| 			if(node.Expanded)
 | |
| 				node.ChildNodesBounds=new Rectangle(node.ChildNodesBounds.X+x,node.ChildNodesBounds.Y+y,node.ChildNodesBounds.Width,node.ChildNodesBounds.Height);
 | |
| 		}
 | |
| 
 | |
| 		protected virtual NodeLayoutContextInfo GetDefaultNodeLayoutContextInfo(System.Drawing.Graphics graphics)
 | |
| 		{
 | |
| 			NodeLayoutContextInfo layoutInfo=new NodeLayoutContextInfo();
 | |
| 			layoutInfo.ClientRectangle=m_ClientArea;
 | |
| 			layoutInfo.DefaultColumns=this.GetDefaultColumnInfo();
 | |
| 			layoutInfo.ChildColumns=null;
 | |
| 			layoutInfo.Left=0;
 | |
| 			layoutInfo.Top=0; // TODO: Include Columns if visible into this...
 | |
| 			layoutInfo.DefaultFont=m_Tree.Font;
 | |
| 			layoutInfo.LeftToRight=(this.LeftRight==System.Windows.Forms.LeftRightAlignment.Left);
 | |
| 			layoutInfo.Graphics=graphics;
 | |
| 			layoutInfo.Styles=m_Tree.Styles;
 | |
| 			if(m_Tree.CellLayout!=eCellLayout.Default)
 | |
| 				layoutInfo.CellLayout=m_Tree.CellLayout;
 | |
| 			if(m_Tree.CellPartLayout!=eCellPartLayout.Default)
 | |
| 				layoutInfo.CellPartLayout=m_Tree.CellPartLayout;
 | |
| 				
 | |
| 			if(m_Tree.NodeStyle!=null)
 | |
| 				layoutInfo.DefaultNodeStyle=m_Tree.NodeStyle;
 | |
| 
 | |
| 			if(m_Tree.CellStyleDefault!=null)
 | |
| 				layoutInfo.DefaultCellStyle=m_Tree.CellStyleDefault;
 | |
| 			else
 | |
| 				layoutInfo.DefaultCellStyle=ElementStyle.GetDefaultCellStyle(layoutInfo.DefaultNodeStyle);
 | |
| 
 | |
| 			// Determine size of the default Column Header
 | |
| 			if(m_Tree.ColumnStyleNormal!=null)
 | |
| 			{
 | |
| 				ElementStyleLayout.CalculateStyleSize(m_Tree.ColumnStyleNormal,layoutInfo.DefaultFont);
 | |
| 				layoutInfo.DefaultHeaderSize=m_Tree.ColumnStyleNormal.Size;
 | |
| 			}
 | |
| 
 | |
| 			if(layoutInfo.DefaultHeaderSize.IsEmpty)
 | |
| 				layoutInfo.DefaultHeaderSize.Height=layoutInfo.DefaultFont.Height+4;
 | |
| 
 | |
| 			return layoutInfo;
 | |
| 		}
 | |
| 
 | |
| 		protected Node[] GetTopLevelNodes()
 | |
| 		{
 | |
| 			if(m_Tree.DisplayRootNode!=null)
 | |
| 				return new Node[] {m_Tree.DisplayRootNode};
 | |
| 			else
 | |
| 			{
 | |
| 				Node[] nodes=new Node[m_Tree.Nodes.Count];
 | |
| 				m_Tree.Nodes.CopyTo(nodes);
 | |
| 				return nodes;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		protected bool IsRootNode(Node node)
 | |
| 		{
 | |
| 			return NodeOperations.IsRootNode(m_Tree,node);
 | |
| 		}
 | |
| 
 | |
| 		protected virtual void EmptyBoundsUnusedNodes(Node[] topLevelNodes)
 | |
| 		{
 | |
| 			if(m_Tree.DisplayRootNode!=null)
 | |
| 			{
 | |
| 				Node node=m_Tree.DisplayRootNode.PrevVisibleNode;
 | |
| 				while(node!=null)
 | |
| 				{
 | |
| 					node.SetBounds(Rectangle.Empty);
 | |
| 					node=node.PrevVisibleNode;
 | |
| 				}
 | |
| 				node=m_Tree.DisplayRootNode.NextNode;
 | |
| 				if(node==null)
 | |
| 				{
 | |
| 					node=m_Tree.DisplayRootNode.Parent;
 | |
| 					while(node!=null)
 | |
| 					{
 | |
| 						if(node.NextNode!=null)
 | |
| 						{
 | |
| 							node=node.NextNode;
 | |
| 							break;
 | |
| 						}
 | |
| 						else
 | |
| 							node=node.Parent;
 | |
| 					}
 | |
| 				}
 | |
| 				while(node!=null)
 | |
| 				{
 | |
| 					node.SetBounds(Rectangle.Empty);
 | |
| 					node=node.NextVisibleNode;
 | |
| 				}
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				for(int i=1;i<topLevelNodes.Length;i++)
 | |
| 				{
 | |
| 					topLevelNodes[i].SetBounds(Rectangle.Empty);
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		#region Column Support
 | |
| 		// Assumes that layoutInfo is up-to-date and that Node that is connected with
 | |
| 		// columns is already processed and it's size and location calculated.
 | |
| 		// layoutInfo.Top member reflects the next position below the node
 | |
| 		// layoutInfo.LevelOffset should reflect the X offset for the child nodes.
 | |
| 		public void LayoutColumnHeader(NodeLayoutContextInfo layoutInfo)
 | |
| 		{
 | |
| 			Node node=layoutInfo.ContextNode;
 | |
| 
 | |
| 			if(node.NodesColumns.Count==0)
 | |
| 			{
 | |
| 				node.ColumnHeaderHeight=0;
 | |
| 				return;
 | |
| 			}
 | |
| 			
 | |
| 			int x=layoutInfo.Left;
 | |
| 			int y=layoutInfo.ContextNode.BoundsRelative.Bottom;
 | |
| 
 | |
| 			bool bLeftNode=(layoutInfo.MapPositionNear && layoutInfo.LeftToRight);
 | |
| 			int expandPartWidth=this.ExpandAreaWidth;
 | |
| 			int cellPartSpacing=GetCellLayout().CellPartSpacing;
 | |
| 
 | |
| 			if(!bLeftNode)
 | |
| 				x+=(expandPartWidth+cellPartSpacing);
 | |
| 
 | |
| 			int clientWidth=layoutInfo.ClientRectangle.Width-(layoutInfo.Left+expandPartWidth);
 | |
| 			if(clientWidth<=0)
 | |
| 				clientWidth=layoutInfo.ClientRectangle.Width;
 | |
| 			
 | |
| 			node.ColumnHeaderHeight=Layout.ColumnHeaderLayout.LayoutColumnHeader(layoutInfo,x,y,clientWidth,this.GetCellLayout().CellHorizontalSpacing);
 | |
| 		}
 | |
| 		#endregion
 | |
| 		
 | |
| 		#region RTL Support
 | |
| 		public virtual System.Windows.Forms.LeftRightAlignment LeftRight
 | |
| 		{
 | |
| 			get {return m_LeftRight;}
 | |
| 			set {m_LeftRight=value;}
 | |
| 		}
 | |
| 		#endregion
 | |
| 	}
 | |
| }
 |