using System; using System.Collections.Generic; using System.Text; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Text; namespace DevComponents.AdvTree.Layout { /// /// Performs ListView Tile style layout. /// internal class NodeTileLayout : NodeLayout { public NodeTileLayout(AdvTree treeControl, Rectangle clientArea, LayoutSettings layoutSettings) : base(treeControl, clientArea, layoutSettings) { } public override void UpdateTopLevelColumnsWidth() { // Columns are not visible in tile layout this.Tree.Columns.SetBounds(Rectangle.Empty); } /// /// Returns default top-level columns for tree control. /// /// Returns array list of ColumnInfo objects. protected override NodeColumnInfo GetDefaultColumnInfo() { // There are no columns in Tile view List ci = new List(); NodeColumnInfo info = new NodeColumnInfo(ci, false); return info; } protected override NodeLayoutContextInfo GetDefaultNodeLayoutContextInfo(System.Drawing.Graphics graphics) { NodeLayoutContextInfo context = base.GetDefaultNodeLayoutContextInfo(graphics); context.IsViewGroupping = this.Groupping; return context; } public override void PerformLayout() { this.PrepareStyles(); Rectangle area = Rectangle.Empty; Graphics g=this.GetGraphics(); SmoothingMode sm = g.SmoothingMode; TextRenderingHint th = g.TextRenderingHint; if (m_Tree.AntiAlias) { g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; } NodeLayoutContextInfo layoutInfo = GetDefaultNodeLayoutContextInfo(g); layoutInfo.ExpandPartAlignedLeft = true; layoutInfo.Left = ClientArea.X; layoutInfo.Top = ClientArea.Y; CellLayout cellLayout = this.GetCellLayout(); cellLayout.ResetCheckBoxSize(); if (this.Tree.CheckBoxImageChecked != null) cellLayout.CheckBoxSize = this.Tree.CheckBoxImageChecked.Size; LayoutTopLevelColumns(layoutInfo); // Get default Columns NodeColumnInfo defaultColInfoList = this.GetDefaultColumnInfo(); layoutInfo.DefaultColumns = defaultColInfoList; try { // Loop through each top-level node Node[] topLevelNodes=this.GetTopLevelNodes(); int defaultTop = layoutInfo.Top; area = ProcessTopLevelNodes(area, layoutInfo, topLevelNodes); //if (defaultColInfoList.HasAutoSizeColumn) //{ // foreach (ColumnInfo columnInfo in defaultColInfoList.ColumnInfo) // { // if (columnInfo.AutoSize) // { // columnInfo.AutoSize = false; // columnInfo.Width = columnInfo.MaxWidth; // columnInfo.ColumnHeader.Width.SetAutoSizeWidth(columnInfo.MaxWidth); // columnInfo.MaxWidth = 0; // } // } // layoutInfo.ContextNode = null; // LayoutTopLevelColumns(layoutInfo); // layoutInfo.Top = defaultTop; // area = ProcessTopLevelNodes(Rectangle.Empty, layoutInfo, topLevelNodes); //} } finally { if (m_Tree.AntiAlias) { g.SmoothingMode = sm; //g.TextRenderingHint = th; } if(this.DisposeGraphics) g.Dispose(); } if (layoutInfo.FullRowBackgroundNodes.Count > 0) Tree.FullRowBackgroundNodes = layoutInfo.FullRowBackgroundNodes; else Tree.FullRowBackgroundNodes = null; m_Width = area.Width; m_Height = area.Height; } private void LayoutTopLevelColumns(NodeLayoutContextInfo layoutInfo) { // There are no columns in Tile view this.Tree.SetColumnHeaderControlVisibility(false); } private Rectangle ProcessTopLevelNodes(Rectangle area, NodeLayoutContextInfo layoutInfo, Node[] topLevelNodes) { layoutInfo.CurrentLevelLeft = layoutInfo.Left; bool isPreviousGroupNode = false; foreach (Node childNode in topLevelNodes) { layoutInfo.ContextNode = childNode; if (childNode.Visible) { if (_Groupping && childNode.HasChildNodes) { if (layoutInfo.CurrentLineHeight > 0) layoutInfo.Top += layoutInfo.CurrentLineHeight + this.LayoutSettings.NodeVerticalSpacing; layoutInfo.CurrentLineHeight = 0; layoutInfo.Left = layoutInfo.CurrentLevelLeft; isPreviousGroupNode = true; } else { if (isPreviousGroupNode) { if (layoutInfo.CurrentLineHeight > 0) layoutInfo.Top += layoutInfo.CurrentLineHeight + this.LayoutSettings.NodeVerticalSpacing; layoutInfo.CurrentLineHeight = 0; layoutInfo.Left = layoutInfo.CurrentLevelLeft; } isPreviousGroupNode = false; } } ProcessNode(layoutInfo); if (childNode.Visible) { area = Rectangle.Union(area, childNode.BoundsRelative); if (childNode.Expanded && childNode.HasChildNodes) area = Rectangle.Union(area, childNode.ChildNodesBounds); if (!(_Groupping && childNode.HasChildNodes)) layoutInfo.Left += childNode.BoundsRelative.Width + this.LayoutSettings.NodeHorizontalSpacing; } } return area; } private Rectangle ProcessChildNodes(NodeLayoutContextInfo layoutInfo, Node node, int nodeVerticalSpacing, NodeColumnInfo childColumns) { Rectangle childNodesBounds = new Rectangle(layoutInfo.Left, layoutInfo.Top, 0, 0); bool isPreviousGroupNode = false; foreach (Node childNode in node.Nodes) { if (!childNode.Visible) continue; if (_Groupping && childNode.HasChildNodes) { if (layoutInfo.CurrentLineHeight > 0) layoutInfo.Top += layoutInfo.CurrentLineHeight + this.LayoutSettings.NodeVerticalSpacing; layoutInfo.CurrentLineHeight = 0; layoutInfo.Left = layoutInfo.CurrentLevelLeft; isPreviousGroupNode = true; } else { if (isPreviousGroupNode) { if (layoutInfo.CurrentLineHeight > 0) layoutInfo.Top += layoutInfo.CurrentLineHeight + this.LayoutSettings.NodeVerticalSpacing; layoutInfo.CurrentLineHeight = 0; layoutInfo.Left = layoutInfo.CurrentLevelLeft; isPreviousGroupNode = false; } } layoutInfo.ContextNode = childNode; layoutInfo.ChildColumns = childColumns; ProcessNode(layoutInfo); if (!(_Groupping && childNode.HasChildNodes)) layoutInfo.Left += childNode.BoundsRelative.Width + this.LayoutSettings.NodeHorizontalSpacing; if (isPreviousGroupNode) { childNodesBounds.Width = Math.Max(childNodesBounds.Width, Math.Max(childNode.BoundsRelative.Width, (childNode.Expanded && childNode.ChildNodesBounds.Width > 0 ? childNode.ChildNodesBounds.Right - childNodesBounds.X : 0))); childNodesBounds.Height += childNode.BoundsRelative.Height + (childNode.Expanded ? childNode.ChildNodesBounds.Height + childNode.ColumnHeaderHeight : 0) + nodeVerticalSpacing; } else { childNodesBounds = Rectangle.Union(childNodesBounds, childNode.BoundsRelative); childNodesBounds.Height += nodeVerticalSpacing; } } return childNodesBounds; } #region Node routines private void ProcessNode(NodeLayoutContextInfo layoutInfo) { Node node=layoutInfo.ContextNode; if (!node.Visible || node.Cells.Count == 0) return; if (node.SizeChanged || _Groupping && node.HasChildNodes) { // Calculate size of the node itself... LayoutNode(layoutInfo); } if (node.FullRowBackground) layoutInfo.FullRowBackgroundNodes.Add(node); // Position the node if (_Groupping && node.HasChildNodes) { if (layoutInfo.CurrentLineHeight > 0) layoutInfo.Top += layoutInfo.CurrentLineHeight + this.LayoutSettings.NodeVerticalSpacing; layoutInfo.CurrentLineHeight = 0; } else { if (layoutInfo.Left + node.BoundsRelative.Width > this.ClientArea.Right) { layoutInfo.Left = layoutInfo.CurrentLevelLeft; layoutInfo.Top += layoutInfo.CurrentLineHeight + this.LayoutSettings.NodeVerticalSpacing; layoutInfo.CurrentLineHeight = 0; } } layoutInfo.CurrentLineHeight = Math.Max(layoutInfo.CurrentLineHeight, node.BoundsRelative.Height); if (node.BoundsRelative.X != layoutInfo.Left || node.BoundsRelative.Y != layoutInfo.Top) { // Adjust top position node.SetBounds(new Rectangle(layoutInfo.Left,layoutInfo.Top,node.BoundsRelative.Width,node.BoundsRelative.Height)); } // Position the node if (_Groupping && node.HasChildNodes) { if (layoutInfo.CurrentLineHeight > 0) layoutInfo.Top += layoutInfo.CurrentLineHeight + this.LayoutSettings.NodeVerticalSpacing; layoutInfo.CurrentLineHeight = 0; } int nodeVerticalSpacing = this.LayoutSettings.NodeVerticalSpacing; // Need to set the Top position properly //layoutInfo.Top += (node.BoundsRelative.Height + nodeVerticalSpacing); // No columns in tile view //if (DevComponents.AdvTree.Display.NodeDisplay.HasColumnsVisible(node)) // layoutInfo.Top += node.ColumnHeaderHeight; if(_Groupping && node.HasChildNodes && node.Expanded) { int originalLevelOffset=layoutInfo.Left; int originalLevelLeft = layoutInfo.CurrentLevelLeft; int childNodesTop = layoutInfo.Top; layoutInfo.Left += this.NodeLevelOffset + node.NodesIndent; layoutInfo.CurrentLevelLeft = layoutInfo.Left; NodeColumnInfo parentColumns = layoutInfo.ChildColumns; NodeColumnInfo childColumns = GetNodeColumnInfo(node); Rectangle childNodesBounds = ProcessChildNodes(layoutInfo, node, nodeVerticalSpacing, childColumns); //if (childColumns != null && childColumns.HasAutoSizeColumn) //{ // foreach (ColumnInfo columnInfo in childColumns.ColumnInfo) // { // if (columnInfo.AutoSize) // { // columnInfo.Width = columnInfo.MaxWidth; // columnInfo.ColumnHeader.Width.SetAutoSizeWidth(columnInfo.MaxWidth); // columnInfo.AutoSize = false; // columnInfo.MaxWidth = 0; // } // } // layoutInfo.Top = originalTop; // layoutInfo.Left = originalLevelOffset; // layoutInfo.ContextNode = node; // layoutInfo.ChildColumns = null; // LayoutNode(layoutInfo); // layoutInfo.Top = childNodesTop; // layoutInfo.Left += this.NodeLevelOffset + node.NodesIndent; // childNodesBounds = ProcessChildNodes(layoutInfo, node, nodeVerticalSpacing, childColumns); //} node.ChildNodesBounds = childNodesBounds; layoutInfo.ChildColumns=parentColumns; layoutInfo.ContextNode=node; layoutInfo.Left=originalLevelOffset; layoutInfo.CurrentLevelLeft = originalLevelLeft; } else node.ChildNodesBounds = Rectangle.Empty; } /// /// Gets whether the expand part of the node +/- is aligned to the left of the node in left-to-right layout. /// /// Node to get expand part alignment for /// true if node expand part is aligned to the left in left-to-right layout. private bool ExpandPartAlignedNear(Node node) { return true; // If changed LayoutExpandPart needs to be updated as well } /// /// Returns column information for a given node. /// /// Node to return column information for /// Returns array list of ColumnInfo objects or null if there are no columns defined. protected override NodeColumnInfo GetNodeColumnInfo(Node node) { // No columns in tile-view return null; } /// /// 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. /// protected override bool ReserveExpandPartSpace { get { return false; } } /// /// Returns true if given node has expand part. /// /// Layout context information. /// protected override bool HasExpandPart(NodeLayoutContextInfo layoutInfo) { Node node = layoutInfo.ContextNode; if (node.ExpandVisibility == eNodeExpandVisibility.Auto) { if (!_Groupping || !NodeOperations.GetAnyVisibleNodes(node)) return false; return true; } else return (node.ExpandVisibility == eNodeExpandVisibility.Visible); } private bool _Groupping = true; /// /// Gets or sets whether parent/child node relationship is displayed as groups. /// public bool Groupping { get { return _Groupping; } set { _Groupping = value; } } private CellTileLayout _CellLayout = null; /// /// Returns class responsible for cell layout. /// /// Cell layout class. protected internal override CellLayout GetCellLayout() { if (_CellLayout == null) _CellLayout = new CellTileLayout(this.LayoutSettings); return _CellLayout; } #endregion } }