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,393 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using DevComponents.DotNetBar;
namespace DevComponents.AdvTree.Layout
{
internal class CellTileLayout : CellLayout
{
/// <summary>
/// Initializes a new instance of the CellTileLayout class.
/// </summary>
public CellTileLayout(LayoutSettings layoutSettings) : base(layoutSettings)
{
}
public override Size LayoutCells(NodeLayoutContextInfo layoutInfo, int x, int y)
{
eCellLayout layout = layoutInfo.CellLayout;
if (layoutInfo.ContextNode.CellLayout != layoutInfo.CellLayout && layoutInfo.ContextNode.CellLayout != eCellLayout.Default)
layout = layoutInfo.ContextNode.CellLayout;
if (layout == eCellLayout.Default && !(layoutInfo.ContextNode.HasChildNodes && layoutInfo.IsViewGroupping) && layoutInfo.ContextNode.ImageAlignment == eCellPartAlignment.Default)
{
return TileLayout(layoutInfo, x, y);
}
else
return base.LayoutCells(layoutInfo, x, y);
}
private Size TileLayout(NodeLayoutContextInfo layoutInfo, int x, int y)
{
Node node = layoutInfo.ContextNode;
int height = 0, width = 0, realHeight = 0;
//eHorizontalAlign align = eHorizontalAlign.Left;
Size tileSize = layoutInfo.TileSize;
int iVisibleCells = 0;
int cellCount = node.Cells.Count;
bool isVerticalOverflow = false;
for (int i = 0; i < cellCount; i++)
{
Cell cell = node.Cells[i];
bool bCellVisible = isVerticalOverflow ? false : true;
// Setup cell layout helper class
LayoutCellInfo cellLayout = this.GetLayoutCellInfo();
cellLayout.Top = y;
cellLayout.Left = x;
cellLayout.CellWidth = tileSize.Width;
cellLayout.ContextCell = cell;
cellLayout.Graphics = layoutInfo.Graphics;
cellLayout.LeftToRight = layoutInfo.LeftToRight;
cellLayout.Font = layoutInfo.DefaultFont;
cellLayout.View = layoutInfo.View;
cellLayout.CellIndex = i;
if (cell.Layout != eCellPartLayout.Default)
cellLayout.VerticalPartAlignment = (cell.Layout == eCellPartLayout.Vertical);
else if (layoutInfo.CellPartLayout != eCellPartLayout.Default)
cellLayout.VerticalPartAlignment = (layoutInfo.CellPartLayout == eCellPartLayout.Vertical);
// Prepare union style
if (cell.StyleNormal != null)
cellLayout.LayoutStyle = cell.StyleNormal;
else
cellLayout.LayoutStyle = layoutInfo.DefaultCellStyle;
this.LayoutSingleTileCell(cellLayout);
if (bCellVisible && y + cell.BoundsRelative.Height > tileSize.Height && i > 0)
{
isVerticalOverflow = true;
bCellVisible = false;
}
cell.SetVisible(bCellVisible);
if (bCellVisible)
{
iVisibleCells++;
y += cell.BoundsRelative.Height;
height += cell.BoundsRelative.Height;
if (cell.BoundsRelative.Height > 0)
{
y += this.CellVerticalSpacing;
height += this.CellVerticalSpacing;
}
if (cell.BoundsRelative.Width > width)
width = cell.BoundsRelative.Width;
if (i == 0)
{
realHeight += cell.BoundsRelative.Height;
if (cell.BoundsRelative.Height > 0)
realHeight += this.CellVerticalSpacing;
}
else
realHeight = Math.Max(realHeight, height);
// Align other cells under the text of the first cell and to the right of the image, if any
if (i == 0 && !cell.Images.LargestImageSize.IsEmpty && cellCount > 1)
{
Size largestImageSize = Dpi.ImageSize(cell.Images.LargestImageSize);
if (cell.TextContentBounds.IsEmpty)
x += largestImageSize.Width + this.ImageTextSpacing;
else
x += (cell.TextContentBounds.X - x);
tileSize.Width = cell.TextContentBounds.Width;
height -= cell.BoundsRelative.Height;
height += cell.TextContentBounds.Height;
y -= cell.BoundsRelative.Height;
y += cell.TextContentBounds.Height;
}
}
}
// Take last added spacing off
y -= this.CellVerticalSpacing;
height -= this.CellVerticalSpacing;
realHeight -= this.CellVerticalSpacing;
if (node.Cells[0].BoundsRelative.Height > height && !node.Cells[0].Images.LargestImageSize.IsEmpty)
{
int textOffset = ((realHeight - height) / iVisibleCells) / 2;
if (textOffset > 0)
{
foreach (Cell cell in node.Cells)
{
if (!cell.IsVisible) continue;
cell.TextContentBounds = new Rectangle(cell.TextContentBounds.X, cell.TextContentBounds.Y + textOffset, cell.TextContentBounds.Width, cell.TextContentBounds.Height);
}
}
}
else if(iVisibleCells == 1)
{
Rectangle rtc = node.Cells[0].TextContentBounds;
node.Cells[0].TextContentBounds = new Rectangle(rtc.X, rtc.Y, rtc.Width, node.Cells[0].BoundsRelative.Height);
}
// Additional pass needed if horizontal alignment is other than left and there is more than one cell visible
//if (align != eHorizontalAlign.Left && iVisibleCells > 1)
//{
// foreach (Cell cell in node.Cells)
// {
// if (!cell.IsVisible)
// continue;
// if (align == eHorizontalAlign.Center)
// this.Offset(cell, (width - cell.BoundsRelative.Width) / 2, 0);
// else // Right aligned cells
// this.Offset(cell, width - cell.BoundsRelative.Width, 0);
// }
//}
if (width < layoutInfo.TileSize.Width)
width = layoutInfo.TileSize.Width;
if (realHeight < layoutInfo.TileSize.Height)
realHeight = layoutInfo.TileSize.Height;
return new Size(width, realHeight);
}
protected virtual void LayoutSingleTileCell(LayoutCellInfo info)
{
Size textSize = Size.Empty;
Font font = info.Font;
int fontHeight = info.FontHeight;
int height = 0;
if (info.LayoutStyle.Font != null)
{
font = info.LayoutStyle.Font;
fontHeight = font.Height;
}
info.ContextCell.OnLayoutCell();
Size largestImageSize = info.ContextCell.Images.LargestImageSize;
if (largestImageSize.IsEmpty && HasImage(info.ContextCell))
info.ContextCell.Images.RefreshLargestImageSize();
largestImageSize = Dpi.ImageSize(info.ContextCell.Images.LargestImageSize);
if (info.ContextCell.HostedControl != null)
{
Size controlSize = info.ContextCell.HostedControl.Size;
if (!info.ContextCell.HostedControlSize.IsEmpty)
controlSize = info.ContextCell.HostedControlSize;
if (info.CellWidth == 0)
textSize = new Size(controlSize.Width, controlSize.Height);
else
{
int availTextWidth = info.CellWidth -
ElementStyleLayout.HorizontalStyleWhiteSpace(info.LayoutStyle);
textSize = new Size(availTextWidth, controlSize.Height);
}
}
else if (info.ContextCell.HostedItem != null)
{
if (info.CellWidth != 0) info.ContextCell.HostedItem.WidthInternal = info.CellWidth;
info.ContextCell.HostedItem.RecalcSize();
Size controlSize = info.ContextCell.HostedItem.Size;
if (info.CellWidth == 0)
textSize = new Size(controlSize.Width, controlSize.Height);
else
{
int availTextWidth = info.CellWidth -
ElementStyleLayout.HorizontalStyleWhiteSpace(info.LayoutStyle);
textSize = new Size(availTextWidth, controlSize.Height);
info.ContextCell.HostedItem.WidthInternal = availTextWidth;
}
}
else
{
// Calculate Text Width and Height
if (info.CellWidth == 0)
{
if (info.ContextCell.TextMarkupBody == null)
{
string text = info.ContextCell.DisplayText;
if (text != "")
{
if (info.LayoutStyle.WordWrap && info.LayoutStyle.MaximumWidth > 0)
textSize = TextDrawing.MeasureString(info.Graphics, text, font, info.LayoutStyle.MaximumWidth);
else if (info.ContextCell.Parent != null && info.ContextCell.Parent.Style != null && info.ContextCell.Parent.Style.WordWrap && info.ContextCell.Parent.Style.MaximumWidth > 0)
textSize = TextDrawing.MeasureString(info.Graphics, text, font, info.ContextCell.Parent.Style.MaximumWidth);
else
textSize = TextDrawing.MeasureString(info.Graphics, text, font, 0, eTextFormat.Left | eTextFormat.LeftAndRightPadding | eTextFormat.GlyphOverhangPadding | eTextFormat.NoPrefix);
#if (FRAMEWORK20)
if (!BarFunctions.IsVista && BarUtilities.UseTextRenderer) textSize.Width += 4;
#endif
}
else if (largestImageSize.IsEmpty && !info.ContextCell.CheckBoxVisible)
{
textSize = new Size(5, fontHeight);
}
}
else
{
Size availSize = new Size(1600, 1);
if (info.LayoutStyle.WordWrap && info.LayoutStyle.MaximumWidth > 0)
availSize.Width = info.LayoutStyle.MaximumWidth;
else if (info.ContextCell.Parent != null && info.ContextCell.Parent.Style != null && info.ContextCell.Parent.Style.WordWrap && info.ContextCell.Parent.Style.MaximumWidth > 0)
availSize.Width = info.ContextCell.Parent.Style.MaximumWidth;
DevComponents.DotNetBar.TextMarkup.MarkupDrawContext d = new DevComponents.DotNetBar.TextMarkup.MarkupDrawContext(info.Graphics, font, Color.Empty, false);
info.ContextCell.TextMarkupBody.Measure(availSize, d);
availSize = info.ContextCell.TextMarkupBody.Bounds.Size;
d.RightToLeft = !info.LeftToRight;
info.ContextCell.TextMarkupBody.Arrange(new Rectangle(0, 0, availSize.Width, availSize.Height), d);
textSize = info.ContextCell.TextMarkupBody.Bounds.Size;
}
}
else
{
int availTextWidth = info.CellWidth -
ElementStyleLayout.HorizontalStyleWhiteSpace(info.LayoutStyle);
availTextWidth -= largestImageSize.Width +
(largestImageSize.Width > 0 ? ImageTextSpacing * 2 : 0);
if (info.ContextCell.CheckBoxVisible)
availTextWidth -= CheckBoxSize.Width + ImageTextSpacing * 2;
int cellHeight = fontHeight;
if (info.LayoutStyle.WordWrap || info.ContextCell.TextMarkupBody != null)
{
cellHeight = info.LayoutStyle.MaximumHeight - info.LayoutStyle.MarginTop -
info.LayoutStyle.MarginBottom - info.LayoutStyle.PaddingTop - info.LayoutStyle.PaddingBottom;
if (info.ContextCell.TextMarkupBody == null)
{
if (availTextWidth > 0)
{
if (cellHeight > 0)
textSize = TextDrawing.MeasureString(info.Graphics, info.ContextCell.DisplayText, font, new Size(availTextWidth, cellHeight), info.LayoutStyle.TextFormat);
else
textSize = TextDrawing.MeasureString(info.Graphics, info.ContextCell.DisplayText, font, availTextWidth, info.LayoutStyle.TextFormat);
}
}
else
{
Size availSize = new Size(availTextWidth, 1);
DevComponents.DotNetBar.TextMarkup.MarkupDrawContext d = new DevComponents.DotNetBar.TextMarkup.MarkupDrawContext(info.Graphics, font, Color.Empty, false);
info.ContextCell.TextMarkupBody.Measure(availSize, d);
availSize = info.ContextCell.TextMarkupBody.Bounds.Size;
availSize.Width = availTextWidth;
d.RightToLeft = !info.LeftToRight;
info.ContextCell.TextMarkupBody.Arrange(new Rectangle(0, 0, availSize.Width, availSize.Height), d);
textSize = info.ContextCell.TextMarkupBody.Bounds.Size;
}
}
else
textSize = new Size(availTextWidth, cellHeight);
}
}
if (info.LayoutStyle.WordWrap)
info.ContextCell.WordWrap = true;
else
info.ContextCell.WordWrap = false;
height = (int)Math.Max(height, Math.Ceiling((double)textSize.Height));
if (info.VerticalPartAlignment)
{
if (largestImageSize.Height > 0)
height += largestImageSize.Height + this.ImageTextSpacing;
if (info.ContextCell.CheckBoxVisible)
height += CheckBoxSize.Height + this.ImageCheckBoxSpacing;
}
else
{
if (largestImageSize.Height > height)
height = largestImageSize.Height;
if (info.ContextCell.CheckBoxVisible && CheckBoxSize.Height > height)
height = CheckBoxSize.Height;
}
Rectangle r = new Rectangle(info.Left + ElementStyleLayout.LeftWhiteSpace(info.LayoutStyle),
info.Top + ElementStyleLayout.TopWhiteSpace(info.LayoutStyle)
, info.CellWidth, height);
if (r.Width == 0)
{
if (info.VerticalPartAlignment)
{
r.Width = (int)Math.Ceiling((double)textSize.Width);
if (largestImageSize.Width > r.Width)
r.Width = (largestImageSize.Width + this.ImageTextSpacing);
if (info.ContextCell.CheckBoxVisible && CheckBoxSize.Width > r.Width)
r.Width += (CheckBoxSize.Width + this.ImageTextSpacing);
}
else
{
r.Width = (int)Math.Ceiling((double)textSize.Width);
if (largestImageSize.Width > 0)
r.Width += (largestImageSize.Width + this.ImageTextSpacing);
if (info.ContextCell.CheckBoxVisible)
r.Width += (CheckBoxSize.Width + this.ImageTextSpacing);
}
}
// Now that we have cell bounds store them
Rectangle rCellBounds = new Rectangle(info.Left, info.Top, info.CellWidth, r.Height + info.LayoutStyle.MarginTop + info.LayoutStyle.MarginBottom + info.LayoutStyle.PaddingTop + info.LayoutStyle.PaddingBottom);
if (rCellBounds.Width == 0)
rCellBounds.Width = r.Width + ElementStyleLayout.HorizontalStyleWhiteSpace(info.LayoutStyle);
info.ContextCell.SetBounds(rCellBounds);
// Set position of the check box
if (info.ContextCell.CheckBoxVisible && rCellBounds.Width >= this.CheckBoxSize.Width)
{
eVerticalAlign va = GetCheckBoxVerticalAlign(info.ContextCell.CheckBoxAlignment, info.View);
eHorizontalAlign ha = GetCheckBoxHorizontalAlign(info.ContextCell.CheckBoxAlignment, info.LeftToRight, info.View);
if (ha == eHorizontalAlign.Center && (!string.IsNullOrEmpty(info.ContextCell.Text) || !largestImageSize.IsEmpty))
ha = eHorizontalAlign.Left;
if (info.VerticalPartAlignment)
info.ContextCell.SetCheckBoxBounds(AlignContentVertical(this.CheckBoxSize, ref r, ha, va, this.ImageTextSpacing));
else
info.ContextCell.SetCheckBoxBounds(AlignContent(this.CheckBoxSize, ref r, ha, va, this.ImageTextSpacing));
}
else
info.ContextCell.SetCheckBoxBounds(Rectangle.Empty);
// Set Position of the image
if (!largestImageSize.IsEmpty && rCellBounds.Width >= largestImageSize.Width)
{
eVerticalAlign va = GetVerticalAlign(info.ContextCell.ImageAlignment, info.View);
eHorizontalAlign ha = GetHorizontalAlign(info.ContextCell.ImageAlignment, info.LeftToRight, info.View);
if (ha == eHorizontalAlign.Center && (!string.IsNullOrEmpty(info.ContextCell.Text) || info.ContextCell.CheckBoxVisible))
ha = eHorizontalAlign.Left;
if (info.VerticalPartAlignment)
info.ContextCell.SetImageBounds(AlignContentVertical(largestImageSize, ref r, ha, va, this.ImageTextSpacing));
else
info.ContextCell.SetImageBounds(AlignContent(largestImageSize, ref r, ha, va, this.ImageTextSpacing));
}
else
info.ContextCell.SetImageBounds(Rectangle.Empty);
// Set position of the text
//info.ContextCell.SetTextBounds(Rectangle.Empty);
if (!textSize.IsEmpty)
{
if (info.CellWidth > 0)
r.Width -= 2;
if (info.View == eView.Tile && info.CellIndex == 0)
info.ContextCell.TextContentBounds = new Rectangle(r.X, r.Y, textSize.Width, textSize.Height + 1);
else
info.ContextCell.TextContentBounds = r;
}
else
info.ContextCell.TextContentBounds = Rectangle.Empty;
}
}
}

View File

@@ -0,0 +1,193 @@
using System;
using System.Drawing;
using DevComponents.DotNetBar;
namespace DevComponents.AdvTree.Layout
{
/// <summary>
/// Class that is used to layout column header.
/// </summary>
internal class ColumnHeaderLayout
{
public ColumnHeaderLayout()
{
}
// 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 static int LayoutColumnHeader(NodeLayoutContextInfo layoutInfo,int x, int y, int clientWidth, int cellHorizontalSpacing)
{
ColumnHeaderCollection columns = null;
Node node=layoutInfo.ContextNode;
if (node == null)
columns = layoutInfo.TreeColumns;
else
columns = node.NodesColumns;
columns.UsesRelativeSize = false;
int height=0;
bool adjustHeight = false;
Rectangle totalBounds = Rectangle.Empty;
ColumnHeader lastVisibleColumn = null;
ColumnHeader stretchToFillColumn = null;
bool allRelative = true;
bool firstVisible = true;
for (int i = 0; i < columns.Count; i++)
{
ColumnHeader col = columns.ColumnAtDisplayIndex(i);
col.IsLastVisible = false;
if(!col.Visible)
continue;
col.IsFirstVisible = firstVisible;
firstVisible = false;
//if(col.SizeChanged)
{
// Column for child nodes is always placed below the current node and
// is not included in the node's rectangle
Rectangle bounds=Rectangle.Empty;
bounds.X=x;
bounds.Y=y;
if (col.Width.AutoSize)
{
int autoWidth = col.Width.AutoSizeWidth;
if (col.Width.AutoSizeMinHeader)
{
Font headerFont = layoutInfo.DefaultFont;
if (!string.IsNullOrEmpty(col.StyleNormal))
{
ElementStyle style = layoutInfo.Styles[col.StyleNormal];
if (style != null && style.Font != null)
headerFont = style.Font;
}
else if (layoutInfo.ColumnStyle != null && layoutInfo.ColumnStyle.Font != null)
headerFont = layoutInfo.ColumnStyle.Font;
if (headerFont != null)
{
int columnHeaderTextWidth = (int)Math.Ceiling(layoutInfo.Graphics.MeasureString(col.Text, headerFont).Width) + 2;
autoWidth = Math.Max(autoWidth, columnHeaderTextWidth);
col.Width.SetAutoSizeWidth(autoWidth);
}
}
bounds.Width = autoWidth;
allRelative = false;
}
else if (col.Width.Absolute > 0)
{
bounds.Width = col.Width.Absolute;
allRelative = false;
}
else if (col.Width.Absolute == -1)
{
bounds.Width = 0;
allRelative = false;
}
else if (col.Width.Relative > 0)
{
if (col.IsFirstVisible)
{
clientWidth -= layoutInfo.ExpandPartWidth;
bounds.Width = (clientWidth * col.Width.Relative) / 100 - cellHorizontalSpacing;
bounds.Width += layoutInfo.ExpandPartWidth;
}
else
bounds.Width = (clientWidth * col.Width.Relative) / 100 - cellHorizontalSpacing;
columns.UsesRelativeSize = true;
}
lastVisibleColumn = col;
if (col.StretchToFill)
{
stretchToFillColumn = col;
columns.UsesRelativeSize = true;
}
if(col.StyleNormal=="" && col.StyleMouseDown=="" && col.StyleMouseOver=="")
{
bounds.Height=layoutInfo.DefaultHeaderSize.Height;
}
else
{
Size sz=Size.Empty;
if(col.StyleNormal!="")
{
ElementStyleLayout.CalculateStyleSize(layoutInfo.Styles[col.StyleNormal],layoutInfo.DefaultFont);
sz=layoutInfo.Styles[col.StyleNormal].Size;
}
if(sz.Height==0)
bounds.Height=layoutInfo.DefaultHeaderSize.Height;
else
bounds.Height=sz.Height;
}
if (col.Image != null && col.Image.Height+4>bounds.Height)
{
bounds.Height = col.Image.Height + 4;
}
col.SetBounds(bounds);
col.SizeChanged=false;
x += (bounds.Width + cellHorizontalSpacing);
if (bounds.Height > height)
{
if (height > 0)
adjustHeight = true;
height = bounds.Height;
}
else if (bounds.Height < height)
adjustHeight = true;
}
if (totalBounds.IsEmpty)
totalBounds = col.Bounds;
else
totalBounds = Rectangle.Union(totalBounds, col.Bounds);
}
if (adjustHeight)
{
foreach (ColumnHeader col in columns)
{
col.SetBounds(new Rectangle(col.Bounds.X, col.Bounds.Y, col.Bounds.Width, height));
}
}
if (lastVisibleColumn != null && allRelative)
{
lastVisibleColumn.SetBounds(new Rectangle(lastVisibleColumn.Bounds.X, lastVisibleColumn.Bounds.Y, lastVisibleColumn.Bounds.Width + cellHorizontalSpacing, lastVisibleColumn.Bounds.Height));
totalBounds = Rectangle.Union(totalBounds, lastVisibleColumn.Bounds);
}
if (lastVisibleColumn != null) lastVisibleColumn.IsLastVisible = true;
if (stretchToFillColumn != null && totalBounds.Width < clientWidth)
{
int stretch = clientWidth - totalBounds.Width;
if (stretchToFillColumn.IsFirstVisible && stretchToFillColumn.IsLastVisible) // Single column visible only case
stretch -= layoutInfo.Indent;
else if (stretchToFillColumn.Parent != null && stretchToFillColumn.Parent.ParentNode != null)
stretch -= layoutInfo.Indent;
stretchToFillColumn.SetBounds(new Rectangle(stretchToFillColumn.Bounds.X, stretchToFillColumn.Bounds.Y,
stretchToFillColumn.Bounds.Width + stretch, stretchToFillColumn.Bounds.Height));
totalBounds = Rectangle.Union(totalBounds, stretchToFillColumn.Bounds);
if (!stretchToFillColumn.IsLastVisible) // Offset columns to the right if this was not last visible column
{
int startIndex = columns.GetDisplayIndex(stretchToFillColumn) + 1;
for (int i = startIndex; i < columns.Count; i++)
{
ColumnHeader col = columns.ColumnAtDisplayIndex(i);
if (!col.Visible) continue;
col.SetBounds(new Rectangle(col.Bounds.X + stretch, col.Bounds.Y, col.Bounds.Width, col.Bounds.Height));
totalBounds = Rectangle.Union(totalBounds, col.Bounds);
}
}
}
columns.SetBounds(totalBounds);
return height;
}
}
}

View File

@@ -0,0 +1,78 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
namespace DevComponents.AdvTree.Layout
{
internal class LayoutSettings
{
#region Internal Implementation
private int _NodeVerticalSpacing = 3;
/// <summary>
/// Gets or sets the vertical spacing between nodes in pixels.
/// </summary>
public virtual int NodeVerticalSpacing
{
get { return _NodeVerticalSpacing; }
set { _NodeVerticalSpacing = value; }
}
private int _NodeHorizontalSpacing = 4;
/// <summary>
/// Gets or sets the horizontal spacing between nodes in pixels.
/// </summary>
public virtual int NodeHorizontalSpacing
{
get { return _NodeHorizontalSpacing; }
set { _NodeHorizontalSpacing = value; }
}
private int _CellHorizontalSpacing = 5;
/// <summary>
/// Returns horizontal spacing between cells in a node
/// </summary>
public int CellHorizontalSpacing
{
get { return _CellHorizontalSpacing; }
set
{
_CellHorizontalSpacing = value;
}
}
private int _ExpandAreaWidth = 24;
/// <summary>
/// Returns width of the expand button area. Default is 24 pixels.
/// </summary>
public virtual int ExpandAreaWidth
{
get { return _ExpandAreaWidth; }
set
{
_ExpandAreaWidth = value;
}
}
protected Size _ExpandPartSize = new Size(8, 8);
/// <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 _ExpandPartSize; }
set { _ExpandPartSize = value; }
}
private int _CommandAreaWidth = 10;
/// <summary>
/// Gets or sets width of command button area. Default is 8 pixels.
/// </summary>
public virtual int CommandAreaWidth
{
get { return _CommandAreaWidth; }
set { _CommandAreaWidth = value; }
}
#endregion
}
}

View File

@@ -0,0 +1,888 @@
using System;
using System.Drawing;
using DevComponents.DotNetBar;
using System.Collections;
namespace DevComponents.AdvTree
{
namespace Layout
{
/// <summary>
/// Represents class for Node's cell layout.
/// </summary>
internal class CellLayout
{
public CellLayout(LayoutSettings layoutSettings)
{
_LayoutSettings = layoutSettings;
}
private LayoutSettings _LayoutSettings;
public LayoutSettings LayoutSettings
{
get { return _LayoutSettings; }
set { _LayoutSettings = value; }
}
/// <summary>
/// Offset cell bounds, check box bounds, image bounds and text bounds by specified offset.
/// </summary>
/// <param name="cell">Cell to offset.</param>
/// <param name="x">Horizontal offset in pixels.</param>
/// <param name="y">Vertical offset in pixels.</param>
protected void Offset(Cell cell, int x, int y)
{
if (x == 0 && y == 0) return;
cell.SetBounds(new Rectangle(cell.BoundsRelative.X+x,cell.BoundsRelative.Y+y,cell.BoundsRelative.Width,cell.BoundsRelative.Height));
if(!cell.CheckBoxBoundsRelative.IsEmpty)
cell.SetCheckBoxBounds(new Rectangle(cell.CheckBoxBoundsRelative.X+x,cell.CheckBoxBoundsRelative.Y+y,cell.CheckBoxBoundsRelative.Width,cell.CheckBoxBoundsRelative.Height));
if(!cell.ImageBoundsRelative.IsEmpty)
cell.SetImageBounds(new Rectangle(cell.ImageBoundsRelative.X+x,cell.ImageBoundsRelative.Y+y,cell.ImageBoundsRelative.Width,cell.ImageBoundsRelative.Height));
if(!cell.TextContentBounds.IsEmpty)
cell.TextContentBounds=new Rectangle(cell.TextContentBounds.X+x,cell.TextContentBounds.Y+y,cell.TextContentBounds.Width,cell.TextContentBounds.Height);
}
protected virtual void LayoutSingleCell(LayoutCellInfo info)
{
Size textSize = Size.Empty;
Font font = info.Font;
int fontHeight = info.FontHeight; // Uses cached FontHeight reference. Huge performance savings on some fonts!!!
int height = 0;
if (info.LayoutStyle.Font != null)
{
font = info.LayoutStyle.Font;
fontHeight = font.Height;
}
info.ContextCell.OnLayoutCell();
if (info.ContextCell.Images.LargestImageSize.IsEmpty && HasImage(info.ContextCell))
info.ContextCell.Images.RefreshLargestImageSize();
Size largestImageSize = Dpi.ImageSize(info.ContextCell.Images.LargestImageSize);
Size checkBoxSize = Dpi.Size(CheckBoxSize);
if (info.ContextCell.HostedControl != null)
{
Size controlSize = info.ContextCell.HostedControl.Size;
if (!info.ContextCell.HostedControlSize.IsEmpty)
controlSize = info.ContextCell.HostedControlSize;
if (info.CellWidth == 0)
textSize = new Size(controlSize.Width, controlSize.Height);
else
{
int availTextWidth = info.CellWidth -
ElementStyleLayout.HorizontalStyleWhiteSpace(info.LayoutStyle);
textSize = new Size(availTextWidth, controlSize.Height);
}
}
else if (info.ContextCell.HostedItem != null)
{
if (info.CellWidth != 0) info.ContextCell.HostedItem.WidthInternal = info.CellWidth;
info.ContextCell.HostedItem.RecalcSize();
Size controlSize = info.ContextCell.HostedItem.Size;
if (info.CellWidth == 0)
textSize = new Size(controlSize.Width, controlSize.Height);
else
{
int availTextWidth = info.CellWidth -
ElementStyleLayout.HorizontalStyleWhiteSpace(info.LayoutStyle);
textSize = new Size(availTextWidth, controlSize.Height);
info.ContextCell.HostedItem.WidthInternal = availTextWidth;
}
}
else
{
// Calculate Text Width and Height
string cellDisplayText = info.ContextCell.DisplayText;
if (info.CellWidth == 0)
{
if (info.ContextCell.TextMarkupBody == null)
{
string text = cellDisplayText;
if (text != "")
{
if (info.LayoutStyle.WordWrap && info.LayoutStyle.MaximumWidth > 0)
textSize = TextDrawing.MeasureString(info.Graphics, text, font, info.LayoutStyle.MaximumWidth);
else if (info.ContextCell.Parent != null && info.ContextCell.Parent.Style != null && info.ContextCell.Parent.Style.WordWrap && info.ContextCell.Parent.Style.MaximumWidth > 0)
textSize = TextDrawing.MeasureString(info.Graphics, text, font, info.ContextCell.Parent.Style.MaximumWidth);
else
textSize = TextDrawing.MeasureString(info.Graphics, text, font, 0, eTextFormat.Left | eTextFormat.LeftAndRightPadding | eTextFormat.GlyphOverhangPadding | eTextFormat.NoPrefix);
#if (FRAMEWORK20)
if (!BarFunctions.IsVista && BarUtilities.UseTextRenderer) textSize.Width += 4;
#endif
}
else if (largestImageSize.IsEmpty && !info.ContextCell.CheckBoxVisible)
{
textSize = new Size(5, fontHeight);
}
}
else
{
Size availSize = new Size(1600, 1);
if (info.LayoutStyle.WordWrap && info.LayoutStyle.MaximumWidth > 0)
availSize.Width = info.LayoutStyle.MaximumWidth;
else if (info.ContextCell.Parent != null && info.ContextCell.Parent.Style != null && info.ContextCell.Parent.Style.WordWrap && info.ContextCell.Parent.Style.MaximumWidth > 0)
availSize.Width = info.ContextCell.Parent.Style.MaximumWidth;
DevComponents.DotNetBar.TextMarkup.MarkupDrawContext d = new DevComponents.DotNetBar.TextMarkup.MarkupDrawContext(info.Graphics, font, Color.Empty, false);
info.ContextCell.TextMarkupBody.Measure(availSize, d);
availSize = info.ContextCell.TextMarkupBody.Bounds.Size;
d.RightToLeft = !info.LeftToRight;
info.ContextCell.TextMarkupBody.Arrange(new Rectangle(0, 0, availSize.Width, availSize.Height), d);
textSize = info.ContextCell.TextMarkupBody.Bounds.Size;
}
}
else
{
int availTextWidth = info.CellWidth -
ElementStyleLayout.HorizontalStyleWhiteSpace(info.LayoutStyle);
availTextWidth -= largestImageSize.Width +
(largestImageSize.Width > 0 ? ImageTextSpacing * 2 : 0);
if (info.ContextCell.CheckBoxVisible)
availTextWidth -= checkBoxSize.Width + ImageTextSpacing * 2;
int cellHeight = fontHeight;
if (info.LayoutStyle.WordWrap || info.ContextCell.TextMarkupBody != null)
{
cellHeight = info.LayoutStyle.MaximumHeight - info.LayoutStyle.MarginTop -
info.LayoutStyle.MarginBottom - info.LayoutStyle.PaddingTop - info.LayoutStyle.PaddingBottom;
if (info.ContextCell.TextMarkupBody == null)
{
if (availTextWidth > 0)
{
if (cellHeight > 0)
{
textSize = TextDrawing.MeasureString(info.Graphics, cellDisplayText, font, new Size(availTextWidth, cellHeight), info.LayoutStyle.TextFormat);
if (textSize.Height == 0) textSize.Height = cellHeight;
}
else if (!string.IsNullOrEmpty(cellDisplayText))
textSize = TextDrawing.MeasureString(info.Graphics, cellDisplayText, font, availTextWidth, info.LayoutStyle.TextFormat);
else
textSize = new Size(availTextWidth, fontHeight);
}
}
else
{
Size availSize = new Size(availTextWidth, 1);
DevComponents.DotNetBar.TextMarkup.MarkupDrawContext d = new DevComponents.DotNetBar.TextMarkup.MarkupDrawContext(info.Graphics, font, Color.Empty, false);
info.ContextCell.TextMarkupBody.Measure(availSize, d);
availSize = info.ContextCell.TextMarkupBody.Bounds.Size;
availSize.Width = availTextWidth;
d.RightToLeft = !info.LeftToRight;
info.ContextCell.TextMarkupBody.Arrange(new Rectangle(0, 0, availSize.Width, availSize.Height), d);
textSize = info.ContextCell.TextMarkupBody.Bounds.Size;
}
}
else
textSize = new Size(availTextWidth, cellHeight);
}
}
if (info.LayoutStyle.WordWrap)
info.ContextCell.WordWrap = true;
else
info.ContextCell.WordWrap = false;
height = (int)Math.Max(height, Math.Ceiling((double)textSize.Height));
if (info.VerticalPartAlignment)
{
if (largestImageSize.Height > 0)
height += largestImageSize.Height + this.ImageTextSpacing;
if (info.ContextCell.CheckBoxVisible)
height += checkBoxSize.Height + this.ImageCheckBoxSpacing;
}
else
{
if (largestImageSize.Height > height)
height = largestImageSize.Height;
if (info.ContextCell.CheckBoxVisible && checkBoxSize.Height > height)
height = checkBoxSize.Height;
}
Rectangle r = new Rectangle(info.Left + ElementStyleLayout.LeftWhiteSpace(info.LayoutStyle),
info.Top + ElementStyleLayout.TopWhiteSpace(info.LayoutStyle)
, info.CellWidth, height);
if (r.Width == 0)
{
if (info.VerticalPartAlignment)
{
r.Width = (int)Math.Ceiling((double)textSize.Width);
if (largestImageSize.Width > r.Width)
r.Width = (largestImageSize.Width + this.ImageTextSpacing);
if (info.ContextCell.CheckBoxVisible && checkBoxSize.Width > r.Width)
r.Width += (checkBoxSize.Width + this.ImageTextSpacing);
}
else
{
r.Width = (int)Math.Ceiling((double)textSize.Width);
if (largestImageSize.Width > 0)
r.Width += (largestImageSize.Width + this.ImageTextSpacing);
if (info.ContextCell.CheckBoxVisible)
r.Width += (checkBoxSize.Width + this.ImageTextSpacing);
}
}
// Now that we have cell bounds store them
Rectangle rCellBounds = new Rectangle(info.Left, info.Top, info.CellWidth, r.Height + info.LayoutStyle.MarginTop + info.LayoutStyle.MarginBottom + info.LayoutStyle.PaddingTop + info.LayoutStyle.PaddingBottom);
if (rCellBounds.Width == 0)
rCellBounds.Width = r.Width + ElementStyleLayout.HorizontalStyleWhiteSpace(info.LayoutStyle);
info.ContextCell.SetBounds(rCellBounds);
// Set position of the check box
//Size checkBoxSize = this.CheckBoxSize;
if (info.ContextCell.CheckBoxVisible && rCellBounds.Width >= checkBoxSize.Width)
{
eVerticalAlign va = GetCheckBoxVerticalAlign(info.ContextCell.CheckBoxAlignment, info.View);
eHorizontalAlign ha = GetCheckBoxHorizontalAlign(info.ContextCell.CheckBoxAlignment, info.LeftToRight, info.View);
if (ha == eHorizontalAlign.Center && (!string.IsNullOrEmpty(info.ContextCell.Text) || !largestImageSize.IsEmpty))
ha = eHorizontalAlign.Left;
if (info.VerticalPartAlignment)
info.ContextCell.SetCheckBoxBounds(AlignContentVertical(checkBoxSize, ref r, ha, va, this.ImageTextSpacing));
else
info.ContextCell.SetCheckBoxBounds(AlignContent(checkBoxSize, ref r, ha, va, this.ImageTextSpacing));
}
else
info.ContextCell.SetCheckBoxBounds(Rectangle.Empty);
// Set Position of the image
if (!largestImageSize.IsEmpty && rCellBounds.Width >= largestImageSize.Width)
{
eVerticalAlign va = GetVerticalAlign(info.ContextCell.ImageAlignment, info.View);
eHorizontalAlign ha = GetHorizontalAlign(info.ContextCell.ImageAlignment, info.LeftToRight, info.View);
if (ha == eHorizontalAlign.Center && (!string.IsNullOrEmpty(info.ContextCell.Text) || info.ContextCell.CheckBoxVisible) && !info.VerticalPartAlignment)
ha = eHorizontalAlign.Left;
if (info.VerticalPartAlignment)
info.ContextCell.SetImageBounds(AlignContentVertical(largestImageSize, ref r, ha, va, this.ImageTextSpacing));
else
info.ContextCell.SetImageBounds(AlignContent(largestImageSize, ref r, ha, va, this.ImageTextSpacing));
}
else
info.ContextCell.SetImageBounds(Rectangle.Empty);
// Set position of the text
//info.ContextCell.SetTextBounds(Rectangle.Empty);
if (!textSize.IsEmpty)
{
if (info.CellWidth > 0)
{
r.Width -= 2 + ElementStyleLayout.HorizontalStyleWhiteSpace(info.LayoutStyle);
}
info.ContextCell.TextContentBounds = r;
}
else
info.ContextCell.TextContentBounds = Rectangle.Empty;
}
protected Rectangle AlignContent(System.Drawing.Size contentSize, ref Rectangle boundingRectangle, eHorizontalAlign horizAlign, eVerticalAlign vertAlign, int contentSpacing)
{
Rectangle contentRect=new Rectangle(Point.Empty,contentSize);
switch(horizAlign)
{
case eHorizontalAlign.Right:
{
contentRect.X=boundingRectangle.Right-contentRect.Width;
boundingRectangle.Width-=(contentRect.Width+contentSpacing);
break;
}
case eHorizontalAlign.Center:
{
contentRect.X = boundingRectangle.X + (boundingRectangle.Width - contentRect.Width) / 2;
break;
}
default:
{
contentRect.X=boundingRectangle.X;
boundingRectangle.X=contentRect.Right+contentSpacing;
boundingRectangle.Width-=(contentRect.Width+contentSpacing);
break;
}
}
switch(vertAlign)
{
case eVerticalAlign.Top:
{
contentRect.Y=boundingRectangle.Y;
break;
}
case eVerticalAlign.Middle:
{
contentRect.Y=boundingRectangle.Y+(boundingRectangle.Height-contentRect.Height)/2;
break;
}
case eVerticalAlign.Bottom:
{
contentRect.Y=boundingRectangle.Bottom-contentRect.Height;
break;
}
}
return contentRect;
}
protected Rectangle AlignContentVertical(System.Drawing.Size contentSize, ref Rectangle boundingRectangle, eHorizontalAlign horizAlign, eVerticalAlign vertAlign, int contentSpacing)
{
Rectangle contentRect=new Rectangle(Point.Empty,contentSize);
switch(horizAlign)
{
case eHorizontalAlign.Left:
{
contentRect.X=boundingRectangle.X;
break;
}
case eHorizontalAlign.Right:
{
contentRect.X=boundingRectangle.Right-contentRect.Width;
break;
}
case eHorizontalAlign.Center:
{
contentRect.X=boundingRectangle.X+(boundingRectangle.Width-contentRect.Width)/2;
break;
}
}
switch(vertAlign)
{
case eVerticalAlign.Bottom:
{
contentRect.Y=boundingRectangle.Bottom-contentRect.Height;
boundingRectangle.Height-=(contentRect.Height+contentSpacing);
break;
}
//case eVerticalAlign.Top:
default:
{
contentRect.Y=boundingRectangle.Y;
boundingRectangle.Y=contentRect.Bottom+contentSpacing;
boundingRectangle.Height-=(contentRect.Height+contentSpacing);
break;
}
// case eVerticalAlign.Middle:
// {
// contentRect.Y=boundingRectangle.Y+(boundingRectangle.Height-contentRect.Height)/2;
// break;
// }
}
return contentRect;
}
public static eHorizontalAlign GetHorizontalAlign(eCellPartAlignment align, bool leftToRight, eView view)
{
if (align == eCellPartAlignment.Default)
{
if (view == eView.Tree)
align = eCellPartAlignment.NearCenter;
else if (view == eView.Tile)
align = eCellPartAlignment.NearCenter;
}
if(((align==eCellPartAlignment.NearBottom || align==eCellPartAlignment.NearCenter ||
align==eCellPartAlignment.NearTop) && leftToRight) ||
((align==eCellPartAlignment.FarBottom || align==eCellPartAlignment.FarCenter ||
align==eCellPartAlignment.FarTop) && !leftToRight))
return eHorizontalAlign.Left;
else if(align==eCellPartAlignment.CenterBottom || align==eCellPartAlignment.CenterTop)
return eHorizontalAlign.Center;
return eHorizontalAlign.Right;
}
public static eVerticalAlign GetVerticalAlign(eCellPartAlignment align, eView view)
{
if (align == eCellPartAlignment.Default)
{
if (view == eView.Tree)
align = eCellPartAlignment.NearCenter;
else if (view == eView.Tile)
align = eCellPartAlignment.NearCenter;
}
eVerticalAlign va=eVerticalAlign.Middle;
switch(align)
{
case eCellPartAlignment.FarBottom:
case eCellPartAlignment.NearBottom:
case eCellPartAlignment.CenterBottom:
va=eVerticalAlign.Bottom;
break;
case eCellPartAlignment.FarTop:
case eCellPartAlignment.NearTop:
case eCellPartAlignment.CenterTop:
va=eVerticalAlign.Top;
break;
}
return va;
}
public static eHorizontalAlign GetCheckBoxHorizontalAlign(eCellPartAlignment align, bool leftToRight, eView view)
{
if (align == eCellPartAlignment.Default)
{
if (view == eView.Tree)
align = eCellPartAlignment.NearCenter;
else if (view == eView.Tile)
align = eCellPartAlignment.NearCenter;
}
if (((align == eCellPartAlignment.NearBottom || align == eCellPartAlignment.NearCenter ||
align == eCellPartAlignment.NearTop) && leftToRight) ||
((align == eCellPartAlignment.FarBottom || align == eCellPartAlignment.FarCenter ||
align == eCellPartAlignment.FarTop) && !leftToRight))
return eHorizontalAlign.Left;
else if (align == eCellPartAlignment.CenterBottom || align == eCellPartAlignment.CenterTop)
return eHorizontalAlign.Center;
return eHorizontalAlign.Right;
}
public static eVerticalAlign GetCheckBoxVerticalAlign(eCellPartAlignment align, eView view)
{
if (align == eCellPartAlignment.Default)
{
if (view == eView.Tree)
align = eCellPartAlignment.NearCenter;
else if (view == eView.Tile)
align = eCellPartAlignment.NearCenter;
}
eVerticalAlign va = eVerticalAlign.Middle;
switch (align)
{
case eCellPartAlignment.FarBottom:
case eCellPartAlignment.NearBottom:
case eCellPartAlignment.CenterBottom:
va = eVerticalAlign.Bottom;
break;
case eCellPartAlignment.FarTop:
case eCellPartAlignment.NearTop:
case eCellPartAlignment.CenterTop:
va = eVerticalAlign.Top;
break;
}
return va;
}
private Size _CheckBoxSize = new Size(12, 12);
internal System.Drawing.Size CheckBoxSize
{
get
{
return _CheckBoxSize;
}
set
{
_CheckBoxSize = value;
}
}
internal void ResetCheckBoxSize()
{
_CheckBoxSize = new Size(12, 12);
}
/// <summary>
/// Returns spacing between check box and image if both are displayed
/// </summary>
protected int ImageCheckBoxSpacing
{
get {return 4;}
}
/// <summary>
/// Returns spacing between image or checkbox and text
/// </summary>
protected int ImageTextSpacing
{
get {return 4;}
}
//private int _CellHorizontalSpacing = 5;
///// <summary>
///// Returns horizontal spacing between cells in a node
///// </summary>
//public int CellHorizontalSpacing
//{
// get {return _CellHorizontalSpacing;}
// set
// {
// _CellHorizontalSpacing = value;
// }
//}
/// <summary>
/// Returns vertical spacing between cells in a node
/// </summary>
public int CellVerticalSpacing
{
get {return 1;}
}
/// <summary>
/// Spacing between different parts of the cell, like image, option button, text and expand button area
/// </summary>
public int CellPartSpacing
{
get {return 1;}
}
public virtual Size LayoutCells(NodeLayoutContextInfo layoutInfo, int x, int y)
{
eCellLayout layout=layoutInfo.CellLayout;
if (layoutInfo.ContextNode.CellLayout != layoutInfo.CellLayout && layoutInfo.ContextNode.CellLayout != eCellLayout.Default)
layout = layoutInfo.ContextNode.CellLayout;
if (layout == eCellLayout.Horizontal || layout == eCellLayout.Default && layoutInfo.View == eView.Tree || layoutInfo.View == eView.Tile && layoutInfo.IsViewGroupping && layoutInfo.ContextNode.HasChildNodes)
return this.LayoutCellsHorizontal(layoutInfo, x, y);
else
return this.LayoutCellsVertical(layoutInfo, x, y);
}
protected virtual Size LayoutCellsHorizontal(NodeLayoutContextInfo layoutInfo, int x, int y)
{
Node node=layoutInfo.ContextNode;
int height=0, width=0;
bool adjustHeight = false;
int cellCount = node.Cells.Count;
bool firstVisible = true;
int runningColumnWidth = 0;
for(int i=0;i<cellCount;i++)
{
Cell cell = null;
if (layoutInfo.ChildColumns != null && layoutInfo.ChildColumns.ColumnInfo.Count == cellCount)
cell = node.Cells[layoutInfo.ChildColumns.ColumnInfo[i].AbsoluteIndex];
else if (layoutInfo.DefaultColumns.ColumnInfo.Count == cellCount)
cell = node.Cells[layoutInfo.DefaultColumns.ColumnInfo[i].AbsoluteIndex];
else
cell = node.Cells[i];
bool bCellVisible=true;
// Setup cell layout helper class
LayoutCellInfo cellLayout=this.GetLayoutCellInfo();
cellLayout.View = layoutInfo.View;
cellLayout.Top=y;
cellLayout.Left=x;
cellLayout.CellWidth=0;
cellLayout.CellHeight = 0;
cellLayout.ContextCell=cell;
cellLayout.Graphics=layoutInfo.Graphics;
cellLayout.LeftToRight=layoutInfo.LeftToRight;
cellLayout.Font=layoutInfo.DefaultFont;
if(cell.Layout!=eCellPartLayout.Default)
cellLayout.VerticalPartAlignment=(cell.Layout==eCellPartLayout.Vertical);
else if(layoutInfo.CellPartLayout!=eCellPartLayout.Default)
cellLayout.VerticalPartAlignment=(layoutInfo.CellPartLayout==eCellPartLayout.Vertical);
ColumnInfo ci = null;
if ((layoutInfo.DefaultColumns.ColumnInfo.Count > 0 || layoutInfo.ChildColumns != null && layoutInfo.ChildColumns.ColumnInfo.Count > 0) &&
(node.Cells.Count > 1 || node.Cells.Count == layoutInfo.DefaultColumns.ColumnInfo.Count ||
layoutInfo.ChildColumns != null && layoutInfo.ChildColumns.ColumnInfo.Count == node.Cells.Count))
{
bool usingTopLevelColumns = false;
if (layoutInfo.ChildColumns != null && layoutInfo.ChildColumns.ColumnInfo.Count > 0 && i < layoutInfo.ChildColumns.ColumnInfo.Count)
ci = layoutInfo.ChildColumns.ColumnInfo[i] as ColumnInfo;
else if (i < layoutInfo.DefaultColumns.ColumnInfo.Count)
{
ci = layoutInfo.DefaultColumns.ColumnInfo[i] as ColumnInfo;
usingTopLevelColumns = true;
}
if (ci != null)
{
bCellVisible = ci.Visible;
if (ci.AutoSize && cell.HostedControl == null)
cellLayout.CellWidth = 0;
else
{
cellLayout.CellWidth = ci.Width;
/*if (firstVisible && usingTopLevelColumns && cellLayout.CellWidth > 0)
{
cellLayout.CellWidth = Math.Max(-1, cellLayout.CellWidth - (layoutInfo.Left + x + this.LayoutSettings.CellHorizontalSpacing));
if (cellLayout.CellWidth == 0) cellLayout.CellWidth = -1; // this ensures that cell content is not visible since 0 indicates to take as much space as needed
}
else*/ if(usingTopLevelColumns && cellLayout.CellWidth>0 && runningColumnWidth<layoutInfo.Left+x)
{
// Removed layoutInfo.Left from calculation in case that PaddingLeft was set to larger value on AdvTree.BackgroundStyle to push content to the right
cellLayout.CellWidth = Math.Max(-1, cellLayout.CellWidth - ((layoutInfo.Left + x - layoutInfo.LeftMargin) - runningColumnWidth));
if (cellLayout.CellWidth == 0) cellLayout.CellWidth = -1; // this ensures that cell content is not visible since 0 indicates to take as much space as needed
}
runningColumnWidth += ci.Width + this.LayoutSettings.CellHorizontalSpacing;
}
}
}
else if (layoutInfo.View == eView.Tile)
{
if (layoutInfo.IsViewGroupping && node.HasChildNodes)
{
cellLayout.CellWidth = layoutInfo.ClientRectangle.Width - layoutInfo.Left - layoutInfo.ExpandPartWidth - 1;
}
else
{
cellLayout.CellWidth = layoutInfo.TileSize.Width;
cellLayout.CellHeight = layoutInfo.TileSize.Height;
}
}
// Prepare union style
if(cell.StyleNormal!=null)
cellLayout.LayoutStyle=cell.StyleNormal;
else
{
if(layoutInfo.ContextNode.Style!=null)
{
ElementStyle styleCopy = layoutInfo.DefaultCellStyle.Copy();
styleCopy.ApplyStyle(layoutInfo.ContextNode.Style);
cellLayout.LayoutStyle = styleCopy;
}
else
cellLayout.LayoutStyle=layoutInfo.DefaultCellStyle;
}
this.LayoutSingleCell(cellLayout);
cell.SetVisible(bCellVisible);
if(bCellVisible)
{
if (ci != null && ci.AutoSize && cell.HostedControl==null)
{
if (ci.ColumnHeader.Parent.ParentNode == null && firstVisible)
ci.MaxWidth = Math.Max(ci.MaxWidth, cell.BoundsRelative.Width + (layoutInfo.Left + x) + this.LayoutSettings.CellHorizontalSpacing);
else
ci.MaxWidth = Math.Max(ci.MaxWidth, cell.BoundsRelative.Width + this.LayoutSettings.CellHorizontalSpacing);
}
x += Math.Max(0, cell.BoundsRelative.Width);
width += Math.Max(0, cell.BoundsRelative.Width);
//if(cell.BoundsRelative.Width>0)
{
x += this.LayoutSettings.CellHorizontalSpacing;
width += this.LayoutSettings.CellHorizontalSpacing;
}
if (cell.BoundsRelative.Height > height)
{
if (height != 0) adjustHeight = true;
height = cell.BoundsRelative.Height;
}
else if (!firstVisible && cell.BoundsRelative.Height < height && !cell.TextContentBounds.IsEmpty)
adjustHeight = true;
firstVisible = false;
}
}
// Apply the uniform cell text height to all cells
if (adjustHeight)
{
for (int i = 0; i < node.Cells.Count; i++)
{
Cell cell = node.Cells[i];
if (cell.BoundsRelative.Height != height && !cell.TextContentBounds.IsEmpty)
{
cell.TextContentBounds = new Rectangle(cell.TextContentBounds.X, cell.TextContentBounds.Y,
cell.TextContentBounds.Width, cell.TextContentBounds.Height + (height - cell.BoundsRelative.Height));
int diff = height - cell.BoundsRelative.Height;
if (!cell.CheckBoxBoundsRelative.IsEmpty)
{
eVerticalAlign va = GetCheckBoxVerticalAlign(cell.CheckBoxAlignment, layoutInfo.View);
if (va == eVerticalAlign.Middle)
cell.SetCheckBoxBounds(new Rectangle(cell.CheckBoxBoundsRelative.X, cell.CheckBoxBoundsRelative.Y + (int)Math.Ceiling((double)diff / 2), cell.CheckBoxBoundsRelative.Width, cell.CheckBoxBoundsRelative.Height));
if (va == eVerticalAlign.Bottom)
cell.SetCheckBoxBounds(new Rectangle(cell.CheckBoxBoundsRelative.X, cell.CheckBoxBoundsRelative.Y + diff, cell.CheckBoxBoundsRelative.Width, cell.CheckBoxBoundsRelative.Height));
}
if (!cell.ImageBoundsRelative.IsEmpty)
{
eVerticalAlign va = GetVerticalAlign(cell.ImageAlignment, layoutInfo.View);
if(va== eVerticalAlign.Middle)
cell.SetImageBounds(new Rectangle(cell.ImageBoundsRelative.X, cell.ImageBoundsRelative.Y + (int)Math.Ceiling((double)diff / 2), cell.ImageBoundsRelative.Width, cell.ImageBoundsRelative.Height));
else if (va == eVerticalAlign.Bottom)
cell.SetImageBounds(new Rectangle(cell.ImageBoundsRelative.X, cell.ImageBoundsRelative.Y + diff, cell.ImageBoundsRelative.Width, cell.ImageBoundsRelative.Height));
}
cell.SetBounds(new Rectangle(cell.BoundsRelative.X, cell.BoundsRelative.Y, cell.BoundsRelative.Width, height));
}
}
}
// Take last added spacing off
x -= this.LayoutSettings.CellHorizontalSpacing;
width -= this.LayoutSettings.CellHorizontalSpacing;
return new Size(width,height);
}
protected virtual Size LayoutCellsVertical(NodeLayoutContextInfo layoutInfo, int x, int y)
{
Node node=layoutInfo.ContextNode;
int height=0, width=0;
eHorizontalAlign align = node.VerticalCellLayoutAlignment; // eHorizontalAlign.Center;
int iVisibleCells=0;
int cellCount = node.Cells.Count;
for(int i=0;i<cellCount;i++)
{
Cell cell = null;
if (layoutInfo.ChildColumns != null && layoutInfo.ChildColumns.ColumnInfo.Count == cellCount)
cell = node.Cells[layoutInfo.ChildColumns.ColumnInfo[i].AbsoluteIndex];
else if(layoutInfo.DefaultColumns.ColumnInfo.Count == cellCount)
cell = node.Cells[layoutInfo.DefaultColumns.ColumnInfo[i].AbsoluteIndex];
else
cell = node.Cells[i];
bool bCellVisible=true;
// Setup cell layout helper class
LayoutCellInfo cellLayout=this.GetLayoutCellInfo();
cellLayout.Top=y;
cellLayout.Left=x;
cellLayout.CellWidth=0;
cellLayout.ContextCell=cell;
cellLayout.Graphics=layoutInfo.Graphics;
cellLayout.LeftToRight=layoutInfo.LeftToRight;
cellLayout.Font=layoutInfo.DefaultFont;
if(cell.Layout!=eCellPartLayout.Default)
cellLayout.VerticalPartAlignment=(cell.Layout==eCellPartLayout.Vertical);
else if(layoutInfo.CellPartLayout!=eCellPartLayout.Default)
cellLayout.VerticalPartAlignment=(layoutInfo.CellPartLayout==eCellPartLayout.Vertical);
if (layoutInfo.DefaultColumns.ColumnInfo.Count > 0 || layoutInfo.ChildColumns != null && layoutInfo.ChildColumns.ColumnInfo.Count > 0)
{
ColumnInfo ci=null;
if (layoutInfo.ChildColumns != null && layoutInfo.ChildColumns.ColumnInfo.Count > 0)
ci=layoutInfo.ChildColumns.ColumnInfo[i] as ColumnInfo;
else
ci=layoutInfo.DefaultColumns.ColumnInfo[i] as ColumnInfo;
bCellVisible=ci.Visible;
cellLayout.CellWidth=ci.Width;
}
else if (layoutInfo.View == eView.Tile)
{
cellLayout.CellWidth = layoutInfo.TileSize.Width;
cellLayout.CellHeight = layoutInfo.TileSize.Height;
}
// Prepare union style
if(cell.StyleNormal!=null)
cellLayout.LayoutStyle=cell.StyleNormal;
else
cellLayout.LayoutStyle=layoutInfo.DefaultCellStyle;
this.LayoutSingleCell(cellLayout);
cell.SetVisible(bCellVisible);
if(bCellVisible)
{
iVisibleCells++;
y+=cell.BoundsRelative.Height;
height+=cell.BoundsRelative.Height;
if(cell.BoundsRelative.Height>0)
{
y+=this.CellVerticalSpacing;
height+=this.CellVerticalSpacing;
}
if(cell.BoundsRelative.Width>width)
width=cell.BoundsRelative.Width;
}
}
// Take last added spacing off
y-=this.CellVerticalSpacing;
height-=this.CellVerticalSpacing;
// Additional pass needed if horizontal alignment is other than left and there is more than one cell visible
if(align!=eHorizontalAlign.Left && iVisibleCells>1)
{
foreach(Cell cell in node.Cells)
{
if(!cell.IsVisible)
continue;
if(align==eHorizontalAlign.Center)
this.Offset(cell,(width-cell.BoundsRelative.Width)/2,0);
else // Right aligned cells
this.Offset(cell,width-cell.BoundsRelative.Width,0);
}
}
return new Size(width,height);
}
private LayoutCellInfo m_LayoutCellInfo=null;
protected virtual LayoutCellInfo GetLayoutCellInfo()
{
if(m_LayoutCellInfo==null)
m_LayoutCellInfo=new LayoutCellInfo();
return m_LayoutCellInfo;
}
protected virtual bool HasImage(Cell cell)
{
if (cell.Images.Image != null || cell.Images.ImageIndex >= 0 || !string.IsNullOrEmpty(cell.Images.ImageKey))
return true;
return false;
}
}
}
internal class LayoutCellInfo
{
public Cell ContextCell=null;
public int CellWidth=0;
public int CellHeight = 0;
public System.Drawing.Graphics Graphics=null;
public int Left=0;
public int Top=0;
public ElementStyle LayoutStyle=null;
public bool LeftToRight=true;
public bool VerticalPartAlignment=false;
public eView View = eView.Tree;
public int CellIndex = 0;
private Font _Font;
public Font Font
{
get { return _Font; }
set
{
if (_Font != value)
{
_Font = value;
if (_Font != null)
FontHeight = _Font.Height;
else
FontHeight = 0;
}
}
}
public int FontHeight = 0;
public LayoutCellInfo()
{
}
}
internal class ColumnInfo
{
public bool Visible;
public int Width;
public int MaxWidth = 0;
public ColumnHeader ColumnHeader = null;
public bool AutoSize = false;
// Specifies the absolute index for column data. AbsoluteIndex may be different from DisplayIndex of columns are re-arranged
public int AbsoluteIndex = -1;
public ColumnInfo(int width, bool visible, ColumnHeader h, int absoluteIndex)
{
this.Width=width;
this.Visible=visible;
this.ColumnHeader = h;
this.AutoSize = h.Width.AutoSize;
this.AbsoluteIndex = absoluteIndex;
}
}
}

View File

@@ -0,0 +1,702 @@
using System;
using System.Drawing;
using System.Collections;
using DevComponents.DotNetBar;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Collections.Generic;
namespace DevComponents.AdvTree.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 AdvTree m_Tree=null;
protected Rectangle m_ClientArea;
//protected int m_ExpandAreaWidth=8;
protected Size m_ExpandPartSize=new Size(8,8);
private Size _CachedExpandPartSize = Size.Empty;
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=3;
private int m_NodeHorizontalSpacing=0;
private CellLayout m_CellLayout=null;
private Graphics m_Graphics=null;
#endregion
public NodeLayout(AdvTree treeControl, Rectangle clientArea, LayoutSettings layoutSettings)
{
m_Tree=treeControl;
m_ClientArea=clientArea;
_LayoutSettings = layoutSettings;
}
/// <summary>
/// Performs layout of the nodes inside of the tree control.
/// </summary>
public virtual void PerformLayout()
{
}
public virtual void UpdateTopLevelColumnsWidth()
{
}
private LayoutSettings _LayoutSettings;
/// <summary>
/// Gets or sets layout settings.
/// </summary>
public LayoutSettings LayoutSettings
{
get { return _LayoutSettings; }
set { _LayoutSettings = value; }
}
/// <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 g=this.GetGraphics();
SmoothingMode sm = g.SmoothingMode;
TextRenderingHint th = g.TextRenderingHint;
if (m_Tree.AntiAlias)
{
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
//g.TextRenderingHint = DisplayHelp.AntiAliasTextRenderingHint;
}
try
{
NodeLayoutContextInfo layoutInfo=this.GetDefaultNodeLayoutContextInfo(g);
layoutInfo.ContextNode=node;
if (node.IsDragNode)
layoutInfo.DefaultColumns = new NodeColumnInfo(new List<ColumnInfo>(), false);
LayoutNode(layoutInfo);
}
finally
{
if (m_Tree.AntiAlias)
{
g.SmoothingMode = sm;
//g.TextRenderingHint = th;
}
g.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();
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);
}
if (_LayoutSettings != null)
_CachedExpandPartSize = Dpi.Size(_LayoutSettings.ExpandPartSize);
else
_CachedExpandPartSize = Dpi.Size(m_ExpandPartSize);
}
/// <summary>
/// Returns default top-level columns for tree control.
/// </summary>
/// <returns>Returns array list of ColumnInfo objects.</returns>
protected virtual NodeColumnInfo GetDefaultColumnInfo()
{
List<ColumnInfo> ci = new List<ColumnInfo>();
NodeColumnInfo info = new NodeColumnInfo(ci, false);
ColumnHeaderCollection columns=m_Tree.Columns;
//int treeWidth = m_Tree.ClientRectangle.Width;
if(columns!=null)
{
for (int i = 0; i < columns.Count; i++)
{
int columnIndex = columns.DisplayIndexMap[i];
ColumnHeader h = columns[columnIndex];
ColumnInfo columnInfo = new ColumnInfo(h.Bounds.Width, h.Visible, h, columnIndex);
ci.Add(columnInfo);
info.HasAutoSizeColumn |= columnInfo.AutoSize;
}
}
return info;
}
/// <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 NodeColumnInfo GetNodeColumnInfo(Node node)
{
if (!node.HasColumns)
{
return null;
}
List<ColumnInfo> ci = new List<ColumnInfo>();
NodeColumnInfo info = new NodeColumnInfo(ci, false);
ColumnHeaderCollection columns = node.NodesColumns;
for (int i = 0; i < columns.Count; i++)
{
int columnIndex = columns.DisplayIndexMap[i];
ColumnHeader h = columns[columnIndex];
ColumnInfo columnInfo = new ColumnInfo(h.Bounds.Width, h.Visible, h, columnIndex);
ci.Add(columnInfo);
info.HasAutoSizeColumn |= columnInfo.AutoSize;
}
return info;
}
///// <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;
}
//private int _ExpandAreaWidth = 24;
///// <summary>
///// Returns width of the expand button area. Default is 24 pixels.
///// </summary>
//public virtual int ExpandAreaWidth
//{
// get { return _ExpandAreaWidth; }
// set
// {
// _ExpandAreaWidth = value;
// }
//}
///// <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.LayoutSettings.CommandAreaWidth -
ElementStyleLayout.StyleSpacing(nodeStyle,eSpacePart.Border,eStyleSide.Right),layoutInfo.ContextNode.ContentBounds.Y+
ElementStyleLayout.StyleSpacing(nodeStyle,eSpacePart.Border,eStyleSide.Top),
this.LayoutSettings.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, int x)
{
Node node=layoutInfo.ContextNode;
Size partSize=GetExpandPartSize();
Rectangle bounds=new Rectangle(x,0,partSize.Width,partSize.Height);
if (node.ExpandPartVerticalAlignment == eVerticalAlign.Middle)
bounds.Y = (node.BoundsRelative.Height - bounds.Height) / 2;
else if (node.ExpandPartVerticalAlignment == eVerticalAlign.Top)
bounds.Y = Dpi.Height3;
else
bounds.Y = node.BoundsRelative.Height - partSize.Height - Dpi.Height3;
if (bLeftNode || layoutInfo.ExpandPartAlignedLeft && layoutInfo.LeftToRight)
bounds.X += (layoutInfo.ExpandAreaWidth - bounds.Width) / 2;
else
bounds.X = node.BoundsRelative.Right - layoutInfo.ExpandAreaWidth + (layoutInfo.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 _CachedExpandPartSize;
//if (_LayoutSettings != null)
// return _LayoutSettings.ExpandPartSize;
//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)
{
bool bHasExpandPart=this.HasExpandPart(layoutInfo);
bool bHasCommandPart=this.HasCommandPart(layoutInfo);
Node node=layoutInfo.ContextNode;
Rectangle nodeRect = new Rectangle(layoutInfo.Left, layoutInfo.Top, 0, 0);
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.LeftToRight; // (layoutInfo.MapPositionNear && layoutInfo.LeftToRight);
layoutInfo.LayoutNodeExpandPartWidth = 0;
if(bLeftNode && bHasExpandPart || this.ReserveExpandPartSpace)
{
layoutInfo.LayoutNodeExpandPartWidth = (layoutInfo.ExpandAreaWidth + this.GetCellLayout().CellPartSpacing);
width += (layoutInfo.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);
y+=ElementStyleLayout.TopWhiteSpace(nodeStyle);
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 && !this.ReserveExpandPartSpace)
width += layoutInfo.ExpandAreaWidth;
if(bHasCommandPart)
{
width += this.LayoutSettings.CommandAreaWidth;
nodeContentRect.Width += this.LayoutSettings.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 || this.ReserveExpandPartSpace)
LayoutExpandPart(layoutInfo,bLeftNode, 0);
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 internal virtual CellLayout GetCellLayout()
{
if (m_CellLayout == null)
m_CellLayout = new CellLayout(this.LayoutSettings);
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.Indent = m_Tree.Indent;
layoutInfo.Left=0;
layoutInfo.Top=0;
layoutInfo.LeftMargin = m_Tree.BackgroundStyle.PaddingLeft;
layoutInfo.DefaultFont=m_Tree.Font;
layoutInfo.LeftToRight=(this.LeftRight==System.Windows.Forms.LeftRightAlignment.Left);
layoutInfo.Graphics=graphics;
layoutInfo.Styles=m_Tree.Styles;
layoutInfo.FullRowBackgroundNodes = new ArrayList();
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;
layoutInfo.ExpandPartWidth = Dpi.Width(this.Tree.ExpandWidth);
layoutInfo.View = this.Tree.View;
layoutInfo.TileSize = Dpi.Size(this.Tree.TileSize);
layoutInfo.ColumnStyle = this.Tree.ColumnStyleNormal;
layoutInfo.ExpandAreaWidth = Dpi.Width(this.LayoutSettings.ExpandAreaWidth);
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);
}
}
}
public AdvTree Tree
{
get { return m_Tree; }
}
#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.HasColumns || !node.Expanded)
{
node.ColumnHeaderHeight = 0;
return;
}
int spacing = 2;
int x = layoutInfo.Left + this.NodeLevelOffset + node.NodesIndent;
int y=layoutInfo.ContextNode.BoundsRelative.Bottom + spacing;
bool bLeftNode=(layoutInfo.MapPositionNear && layoutInfo.LeftToRight);
int expandPartWidth = layoutInfo.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().LayoutSettings.CellHorizontalSpacing) + spacing;
if (!node.NodesColumnsHeaderVisible)
node.ColumnHeaderHeight = 0;
}
private int _NodeLevelOffset = 16;
internal int NodeLevelOffset
{
get { return _NodeLevelOffset; }
set
{
_NodeLevelOffset = value;
}
}
#endregion
#region RTL Support
public virtual System.Windows.Forms.LeftRightAlignment LeftRight
{
get {return m_LeftRight;}
set {m_LeftRight=value;}
}
#endregion
}
internal class NodeColumnInfo
{
/// <summary>
/// Initializes a new instance of the NodeColumnInfo structure.
/// </summary>
/// <param name="columnInfo"></param>
/// <param name="hasAutoSizeColumn"></param>
public NodeColumnInfo(List<ColumnInfo> columnInfo, bool hasAutoSizeColumn)
{
ColumnInfo = columnInfo;
HasAutoSizeColumn = hasAutoSizeColumn;
}
/// <summary>
/// Gets or sets the list of column info object for the columns.
/// </summary>
public List<ColumnInfo> ColumnInfo;
/// <summary>
/// Gets or sets whether columns have auto-size column.
/// </summary>
public bool HasAutoSizeColumn;
}
}

View File

@@ -0,0 +1,62 @@
using System;
using System.Drawing;
using System.Collections;
using DevComponents.DotNetBar;
namespace DevComponents.AdvTree.Layout
{
/// <summary>
/// Used to pass node contextual information used for layout of the node.
/// </summary>
internal class NodeLayoutContextInfo
{
public Node ContextNode=null;
public Rectangle ClientRectangle=Rectangle.Empty;
public int Left;
public int Top;
public int LeftMargin = 0;
public NodeColumnInfo DefaultColumns=null;
public NodeColumnInfo ChildColumns = null;
public ElementStyle DefaultCellStyle=null;
public ElementStyle DefaultNodeStyle=null;
public Size DefaultHeaderSize=Size.Empty;
public bool LeftToRight=true;
public bool HasExpandPart=true;
public System.Drawing.Graphics Graphics=null;
public ElementStyleCollection Styles=null;
public eCellLayout CellLayout=eCellLayout.Default;
public eCellPartLayout CellPartLayout=eCellPartLayout.Horizontal;
public bool MapPositionNear=false;
public bool ExpandPartAlignedLeft = false;
public ColumnHeaderCollection TreeColumns = null;
public ArrayList FullRowBackgroundNodes = null;
public int ExpandPartWidth = 0;
public int CurrentLineHeight = 0; // Used by tile layout
public int CurrentLevelLeft = 0; // Used by tile layout
public eView View = eView.Tree; // Current control view
public Size TileSize = Size.Empty; // Tile size
public bool IsViewGroupping = false; // Tile view grouping enabled
public ElementStyle ColumnStyle = null;
public int LayoutNodeExpandPartWidth = 0;
public int Indent = 0;
public int ExpandAreaWidth = 0; // Cached LayoutSettings.ExpandAreaWidth with DPI multipler applied.
private Font _DefaultFont = null;
public Font DefaultFont
{
get { return _DefaultFont; }
set
{
if (_DefaultFont != value)
{
_DefaultFont = value;
if (_DefaultFont != null)
DefaultFontHeight = _DefaultFont.Height;
else
DefaultFontHeight = 0;
}
}
}
public int DefaultFontHeight = 0;
}
}

View File

@@ -0,0 +1,393 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
namespace DevComponents.AdvTree.Layout
{
/// <summary>
/// Performs ListView Tile style layout.
/// </summary>
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);
}
/// <summary>
/// Returns default top-level columns for tree control.
/// </summary>
/// <returns>Returns array list of ColumnInfo objects.</returns>
protected override NodeColumnInfo GetDefaultColumnInfo()
{
// There are no columns in Tile view
List<ColumnInfo> ci = new List<ColumnInfo>();
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;
}
/// <summary>
/// Gets whether the expand part of the node +/- is aligned to the left of the node in left-to-right layout.
/// </summary>
/// <param name="node">Node to get expand part alignment for</param>
/// <returns>true if node expand part is aligned to the left in left-to-right layout.</returns>
private bool ExpandPartAlignedNear(Node node)
{
return true; // If changed LayoutExpandPart needs to be updated as well
}
/// <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 override NodeColumnInfo GetNodeColumnInfo(Node node)
{
// No columns in tile-view
return null;
}
/// <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 override bool ReserveExpandPartSpace
{
get
{
return false;
}
}
/// <summary>
/// Returns true if given node has expand part.
/// </summary>
/// <param name="layoutInfo">Layout context information.</param>
/// <returns></returns>
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;
/// <summary>
/// Gets or sets whether parent/child node relationship is displayed as groups.
/// </summary>
public bool Groupping
{
get { return _Groupping; }
set
{
_Groupping = value;
}
}
private CellTileLayout _CellLayout = null;
/// <summary>
/// Returns class responsible for cell layout.
/// </summary>
/// <returns>Cell layout class.</returns>
protected internal override CellLayout GetCellLayout()
{
if (_CellLayout == null)
_CellLayout = new CellTileLayout(this.LayoutSettings);
return _CellLayout;
}
#endregion
}
}

View File

@@ -0,0 +1,328 @@
using System.Collections;
using System.Drawing;
using System.Windows.Forms;
using System;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using DevComponents.DotNetBar;
namespace DevComponents.AdvTree.Layout
{
/// <summary>
/// Performs classic TreeView layout.
/// </summary>
internal class NodeTreeLayout:NodeLayout
{
public NodeTreeLayout(AdvTree treeControl, Rectangle clientArea, LayoutSettings layoutSettings)
: base(treeControl, clientArea, layoutSettings)
{
}
public override void UpdateTopLevelColumnsWidth()
{
if (this.Tree.Columns.Count > 0)
{
Rectangle columnsBounds = DevComponents.DotNetBar.ElementStyleLayout.GetInnerRect(this.Tree.BackgroundStyle, this.Tree.ClientRectangle);
if (this.Tree.VScrollBar != null) columnsBounds.Width -= this.Tree.VScrollBar.Width;
columnsBounds.Height = this.Tree.Columns.Bounds.Height;
if(this.Tree.Columns.Bounds.Width<columnsBounds.Width)
this.Tree.Columns.SetBounds(columnsBounds);
}
}
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;
//g.TextRenderingHint = DisplayHelp.AntiAliasTextRenderingHint;
}
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);
bool hasMinColumnAutoSizeWidth = false;
bool hasStretchToFillColumn = false;
if (defaultColInfoList.HasAutoSizeColumn)
{
foreach (ColumnInfo columnInfo in defaultColInfoList.ColumnInfo)
{
if (columnInfo.AutoSize)
{
columnInfo.AutoSize = false;
//if (columnInfo.ColumnHeader.Width.AutoSizeMinHeader)
//{
// columnInfo.Width = Math.Max(columnInfo.MaxWidth, columnInfo.Width);
// columnInfo.MaxWidth = Math.Max(columnInfo.MaxWidth, columnInfo.Width);
//}
//else
columnInfo.Width = columnInfo.MaxWidth;
columnInfo.ColumnHeader.Width.SetAutoSizeWidth(columnInfo.MaxWidth);
columnInfo.MaxWidth = 0;
if (columnInfo.ColumnHeader.Width.AutoSizeMinHeader)
hasMinColumnAutoSizeWidth = true;
if (columnInfo.ColumnHeader.StretchToFill)
hasStretchToFillColumn = true;
}
}
layoutInfo.ContextNode = null;
LayoutTopLevelColumns(layoutInfo);
// Adjust the of auto sized columns in case minimum header width is used
if (hasMinColumnAutoSizeWidth || hasStretchToFillColumn)
{
foreach (ColumnInfo columnInfo in defaultColInfoList.ColumnInfo)
{
if (columnInfo.ColumnHeader.Width.AutoSize && columnInfo.ColumnHeader.Width.AutoSizeMinHeader || columnInfo.ColumnHeader.StretchToFill)
{
columnInfo.Width = columnInfo.ColumnHeader.Bounds.Width;
}
}
}
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;
//if (columnsVisible && layoutInfo.DefaultColumns != null && layoutInfo.DefaultColumns.Count > 0)
//{
// bool layoutColumns = false;
// for (int i = 0; i < layoutInfo.DefaultColumns.Count; i++)
// {
// ColumnInfo ci = (ColumnInfo)layoutInfo.DefaultColumns[i];
// if (ci.Width == 0 && ci.MaxWidth > 0)
// {
// ci.ColumnHeader.ContentWidth = ci.MaxWidth;
// layoutColumns = true;
// }
// }
// if (layoutColumns)
// {
// layoutInfo.ContextNode = null;
// layoutInfo.TreeColumns = this.Tree.Columns;
// Layout.ColumnHeaderLayout.LayoutColumnHeader(layoutInfo, ClientArea.X,
// ClientArea.Y, ClientArea.Width, this.GetCellLayout().CellHorizontalSpacing);
// }
//}
m_Width = area.Width;
m_Height = area.Height;
}
private void LayoutTopLevelColumns(NodeLayoutContextInfo layoutInfo)
{
// Layout tree columns
if (this.Tree.Columns.Count > 0)
{
Rectangle columnsBounds = m_ClientArea;// DevComponents.DotNetBar.ElementStyleLayout.GetInnerRect(this.Tree.BackgroundStyle, this.Tree.ClientRectangle);
//if (this.Tree.VScrollBar != null) columnsBounds.Width -= this.Tree.VScrollBar.Width;
layoutInfo.TreeColumns = this.Tree.Columns;
int columnHeight = Layout.ColumnHeaderLayout.LayoutColumnHeader(layoutInfo, 0,
0, columnsBounds.Width, this.GetCellLayout().LayoutSettings.CellHorizontalSpacing);
columnHeight += this.LayoutSettings.NodeVerticalSpacing;
if (this.Tree.ColumnsVisible)
{
Rectangle headerBounds = layoutInfo.TreeColumns.Bounds;
if (headerBounds.Width > 0 && headerBounds.Width < columnsBounds.Width)
{
headerBounds.Width = columnsBounds.Width;
layoutInfo.TreeColumns.SetBounds(headerBounds);
}
layoutInfo.Top += columnHeight;
this.Tree.SetColumnHeaderControlVisibility(true);
}
else
this.Tree.SetColumnHeaderControlVisibility(false);
layoutInfo.TreeColumns = null;
}
else
this.Tree.SetColumnHeaderControlVisibility(false);
}
private Rectangle ProcessTopLevelNodes(Rectangle area, NodeLayoutContextInfo layoutInfo, Node[] topLevelNodes)
{
foreach (Node childNode in topLevelNodes)
{
layoutInfo.ContextNode = childNode;
ProcessNode(layoutInfo);
if (childNode.Visible)
{
area = Rectangle.Union(area, childNode.BoundsRelative);
if (childNode.Expanded)
area = Rectangle.Union(area, childNode.ChildNodesBounds);
}
}
return area;
}
#region Node routines
private void ProcessNode(NodeLayoutContextInfo layoutInfo)
{
Node node=layoutInfo.ContextNode;
if (!node.Visible) return;
int originalTop = layoutInfo.Top;
if (node.SizeChanged || node.HasColumns || layoutInfo.DefaultColumns!=null && layoutInfo.DefaultColumns.HasAutoSizeColumn || layoutInfo.ChildColumns!=null && layoutInfo.ChildColumns.HasAutoSizeColumn)
{
// Calculate size of the node itself...
LayoutNode(layoutInfo);
}
if (node.FullRowBackground)
layoutInfo.FullRowBackgroundNodes.Add(node);
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));
//foreach(Cell c in node.Cells)
// c.SetBounds(new Rectangle(c.BoundsRelative.X + layoutInfo.Left, c.BoundsRelative.Y+layoutInfo.Top, c.BoundsRelative.Width, c.BoundsRelative.Height));
}
int nodeVerticalSpacing = this.LayoutSettings.NodeVerticalSpacing;
// Need to set the Top position properly
layoutInfo.Top += (node.BoundsRelative.Height + nodeVerticalSpacing);
if (DevComponents.AdvTree.Display.NodeDisplay.HasColumnsVisible(node))
layoutInfo.Top += node.ColumnHeaderHeight;
if(node.Expanded)
{
int originalLevelOffset=layoutInfo.Left;
int childNodesTop = layoutInfo.Top;
layoutInfo.Left += this.NodeLevelOffset + node.NodesIndent;
NodeColumnInfo parentColumns = layoutInfo.ChildColumns;
NodeColumnInfo childColumns = GetNodeColumnInfo(node);
Rectangle childNodesBounds = ProcessChildNodes(layoutInfo, node, nodeVerticalSpacing, childColumns);
if (childColumns != null && childColumns.HasAutoSizeColumn)
{
bool hasMinColumnAutoSizeWidth = false;
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;
if (columnInfo.ColumnHeader.Width.AutoSizeMinHeader)
hasMinColumnAutoSizeWidth = true;
}
}
layoutInfo.Top = originalTop;
layoutInfo.Left = originalLevelOffset;
layoutInfo.ContextNode = node;
layoutInfo.ChildColumns = parentColumns;
LayoutNode(layoutInfo);
layoutInfo.Top = childNodesTop;
layoutInfo.Left += this.NodeLevelOffset + node.NodesIndent;
// Adjust the of auto sized columns in case minimum header width is used
if (hasMinColumnAutoSizeWidth)
{
foreach (ColumnInfo columnInfo in childColumns.ColumnInfo)
{
if (columnInfo.ColumnHeader.Width.AutoSize && columnInfo.ColumnHeader.Width.AutoSizeMinHeader)
{
columnInfo.Width = columnInfo.ColumnHeader.Bounds.Width;
}
}
}
childNodesBounds = ProcessChildNodes(layoutInfo, node, nodeVerticalSpacing, childColumns);
}
node.ChildNodesBounds = childNodesBounds;
layoutInfo.ChildColumns=parentColumns;
layoutInfo.ContextNode=node;
layoutInfo.Left=originalLevelOffset;
}
}
private Rectangle ProcessChildNodes(NodeLayoutContextInfo layoutInfo, Node node, int nodeVerticalSpacing, NodeColumnInfo childColumns)
{
Rectangle childNodesBounds = new Rectangle(layoutInfo.Left, layoutInfo.Top, 0, 0);
foreach (Node childNode in node.Nodes)
{
if (!childNode.Visible) continue;
layoutInfo.ContextNode = childNode;
layoutInfo.ChildColumns = childColumns;
ProcessNode(layoutInfo);
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;
}
return childNodesBounds;
}
/// <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 override bool ReserveExpandPartSpace
{
get
{
return true;
}
}
/// <summary>
/// Gets whether the expand part of the node +/- is aligned to the left of the node in left-to-right layout.
/// </summary>
/// <param name="node">Node to get expand part alignment for</param>
/// <returns>true if node expand part is aligned to the left in left-to-right layout.</returns>
private bool ExpandPartAlignedNear(Node node)
{
return true; // If changed LayoutExpandPart needs to be updated as well
}
// private NodeCollection GetTopLevelNodes()
// {
// return m_Tree.Nodes;
// }
#endregion
}
}