xenadmin/XenAdmin/Controls/CustomListPanel/CustomListRow.cs

631 lines
20 KiB
C#
Raw Normal View History

/* Copyright (c) Citrix Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* * Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows;
using System.Windows.Forms;
using System.Drawing.Drawing2D;
using XenAdmin.TabPages;
namespace XenAdmin.Controls
{
public class CustomListRow
{
private Color ForeColor_ = SystemColors.ControlText;
private Color BackColor_ = SystemColors.Control;
private Color BorderColor_ = SystemColors.ActiveBorder;
private Pen BorderPen = null;
private Pen ForePen = null;
public Color SelectedBackColor_ = Color.Black;
private Brush BackBrush = null;
private Brush SelectedBackBrush = null;
public bool ShowBorder = true;
public bool Enabled = true;
public bool DrawChildren = true;
private bool _selected = false;
public bool Selectable = true;
public bool DrawGroupBox = true;
public bool ShowOnlyHorizBorder = false;
public int Indent = 13; // left-indent to any child rows
public float BorderWidth = 1.0f;
public Padding Padding = new Padding(0, 3, 0, 3);
public List<ToolStripMenuItem> MenuItems = new List<ToolStripMenuItem>();
public ToolStripMenuItem DefaultMenuItem;
public CustomListRow Parent;
public CustomListPanel ParentPanel;
public List<CustomListRow> Children = new List<CustomListRow>();
public List<CustomListItem> Items = new List<CustomListItem>();
/// <summary>
/// Construct a header.
/// </summary>
public CustomListRow(object tag, Color back, Color fore, Color border, Font font)
{
this.BackColor = back;
this.ForeColor = fore;
this.BorderColor = border;
this.SelectedBackColor = back;
this.DrawGroupBox = false;
this.ShowOnlyHorizBorder = true;
CustomListItem name = new CustomListItem(tag, font, fore, new Padding(10, 3, 3, 3));
AddItem(name);
init();
}
/// <summary>
/// Construct child rows.
/// </summary>
public CustomListRow(Color back, params CustomListItem[] items)
{
Selectable = true;
BackColor = back;
this.SelectedBackColor = back;
ShowBorder = false;
foreach (CustomListItem item in items)
{
AddItem(item);
}
init();
}
/// <summary>
/// Construct fixed row.
/// </summary>
public CustomListRow(Color back, int height)
{
Selectable = true;
BackColor = back;
this.SelectedBackColor = back;
ShowBorder = false;
this.Padding = new Padding(0, 0, 0, height);
init();
}
private void init()
{
RecalculateBorderPen();
RecalculateForePen();
RecalculateBackBrushes();
}
public Color ForeColor
{
get { return ForeColor_; }
set
{
ForeColor_ = value;
RecalculateForePen();
}
}
public Color BackColor
{
get { return BackColor_; }
set
{
BackColor_ = value;
RecalculateBorderPen();
}
}
public Color BorderColor
{
get { return BorderColor_; }
set
{
BorderColor_ = value;
RecalculateBorderPen();
}
}
private void RecalculateBorderPen()
{
if (BorderPen != null)
BorderPen.Dispose();
BorderPen = new Pen(BorderColor, BorderWidth);
}
private void RecalculateForePen()
{
if (ForePen != null)
ForePen.Dispose();
ForePen = new Pen(ForeColor);
}
public Color SelectedBackColor
{
get { return SelectedBackColor_; }
set
{
SelectedBackColor_ = value;
RecalculateBackBrushes();
}
}
private void RecalculateBackBrushes()
{
if (BackBrush != null)
BackBrush.Dispose();
if (SelectedBackBrush != null)
SelectedBackBrush.Dispose();
BackBrush = new SolidBrush(BackColor);
SelectedBackBrush = new SolidBrush(SelectedBackColor);
}
public bool Selected
{
get
{
return _selected;
}
set
{
_selected = value;
if (!value)
foreach (CustomListRow child in Children)
child.Selected = false;
}
}
public int RowAndChildrenHeight
{
get
{
int height = Padding.Vertical + RowHeight;
if (DrawChildren)
{
foreach (CustomListRow child in Children)
{
height += child.RowAndChildrenHeight;
}
}
return height;
}
}
public int RowHeight
{
get
{
int height = 0;
int headWidth = HeaderWidth;
for (int i = 0; i < Items.Count; i++)
{
CustomListItem item = Items[i];
Size cSize = item.WrappedSize(headWidth);
if (cSize.Height > height)
{
height = cSize.Height;
}
if(ParentPanel.level1ColWidths != null && i < ParentPanel.level1ColWidths.Length)
headWidth -= ParentPanel.level1ColWidths[i];
}
return height;
}
}
public int HeaderWidth
{
get
{
if (Parent != null)
return Parent.HeaderWidth - (Padding.Horizontal + Indent);
else
return ParentPanel.Width - (ParentPanel.Padding.Horizontal + Padding.Horizontal);
}
}
public void Dispose()
{
if (ForePen != null)
ForePen.Dispose();
if (BorderPen != null)
BorderPen.Dispose();
if (BackBrush != null)
BackBrush.Dispose();
if (SelectedBackBrush != null)
SelectedBackBrush.Dispose();
foreach (CustomListRow r in Children)
{
r.Dispose();
}
}
public void DrawSelf(Graphics g, Rectangle bounds)
{
int rowHeight = RowHeight;
int headWidth = HeaderWidth;
using (Brush ParentBackBrush = new SolidBrush(ParentPanel.BackColor))
{
g.FillRectangle(ParentBackBrush, bounds);
}
int top = bounds.Top + Padding.Top;
int left = bounds.Left + Padding.Left;
for(int i = 0; i < Items.Count; i++)
{
CustomListItem item = Items[i];
Size itemSize = item.PreferredSize;
int itemTop = top;
if ((item.Anchor & AnchorStyles.Bottom) > 0)
{
itemTop += rowHeight - itemSize.Height;
}
else if ((item.Anchor & AnchorStyles.Top) == 0)
{
itemTop += Convert.ToInt32(Math.Ceiling(Convert.ToDouble(rowHeight - itemSize.Height) / 2.0d));
}
Rectangle itemBounds;
if (Parent != null && (i == Items.Count - 1 || Items[i+1].InCorrectColumn))
{
int colWidth = 1;
if (ParentPanel.level1ColWidths.Length > i)
{
colWidth = ParentPanel.level1ColWidths[i];
}
itemBounds = new Rectangle(new Point(left, itemTop), item.WrappedSize(headWidth - (left - bounds.Left)));
left += colWidth;
}
else
{
itemBounds = new Rectangle(left, itemTop, itemSize.Width, itemSize.Height);
left += itemSize.Width;
}
if (itemBounds.Right > bounds.Right - Padding.Right)
itemBounds.Width -= itemBounds.Right - (bounds.Right - Padding.Right);
if (itemBounds.Bottom > bounds.Bottom - Padding.Bottom)
itemBounds.Height -= itemBounds.Bottom - (bounds.Bottom - Padding.Bottom);
if (i > 0 && Selected && !string.IsNullOrEmpty(item.Tag.ToString()))
{
if ((i < Items.Count - 1 && !Items[i + 1].InCorrectColumn))
{
g.FillRectangle(SystemBrushes.Highlight, new Rectangle(itemBounds.Left - 2, itemBounds.Top - 3, itemBounds.Width + Items[i + 1].PreferredSize.Width + 4, Items[i + 1].PreferredSize.Height + 2));
}
else if (item.InCorrectColumn)
{
g.FillRectangle(SystemBrushes.Highlight, new Rectangle(itemBounds.Left - 2, itemBounds.Top - 1, itemBounds.Width + 4, itemBounds.Height));
}
}
item.DrawSelf(g, itemBounds, Selected && i > 0 && !(i < Items.Count - 1 && !Items[i + 1].InCorrectColumn));
}
top += rowHeight + Padding.Bottom;
if (DrawChildren)
{
foreach (CustomListRow child in Children)
{
int childHeight = child.RowAndChildrenHeight;
Rectangle childBounds = new Rectangle(bounds.Left + Padding.Left + Indent, top, bounds.Width - (Padding.Horizontal + Indent), childHeight);
child.DrawSelf(g, childBounds);
top += childHeight;
}
}
if (ShowBorder)
{
if (ShowOnlyHorizBorder)
{
int w = 1;
if(ParentPanel.level1ColWidths.Length >= 2)
w = 450;
using (Brush brush = new LinearGradientBrush(Point.Empty, new Point(w, 0), BorderColor, BackColor))
{
g.FillRectangle(brush, bounds.Left, bounds.Top + rowHeight, w, 1);
}
}
else
{
g.DrawRectangle(BorderPen, bounds.Left, bounds.Top, headWidth, rowHeight);
}
if (DrawGroupBox)
g.DrawRectangle(BorderPen, bounds.Left, bounds.Top, headWidth, RowAndChildrenHeight);
}
}
public void AddItem(CustomListItem item)
{
item.Row = this;
this.Items.Add(item);
}
public void AddChild(CustomListRow row)
{
row.Parent = this;
if (this.Children.Count == 0)
row.Padding.Top = 10;
row.ParentPanel = ParentPanel;
Children.Add(row);
}
internal CustomListRow SelectChild(Point point, out Point rowRelativePoint)
{
int top = Padding.Vertical + RowHeight;
foreach (CustomListRow child in Children)
{
int height = child.RowAndChildrenHeight;
if (point.Y >= top && point.Y < top + height)
{
int leftPos = point.X - Padding.Left - Indent;
rowRelativePoint = new Point(leftPos, point.Y - top);
if (leftPos < 0) // off the left hand side of the subrow
return null;
return child;
}
top += height;
}
rowRelativePoint = new Point();
return null;
}
private CustomListItem GetItemFromPosition(Point point, out Point itemRelativePoint)
{
int left = Padding.Left;
for (int i = 0; i < ParentPanel.level1ColWidths.Length; i++)
{
if (i >= Items.Count)
continue;
CustomListItem item = Items[i];
if (item == null)
continue;
int width = item.itemBorder.Horizontal + ParentPanel.level1ColWidths[i];
if (point.X >= left && point.X < left + width)
{
itemRelativePoint = new Point(point.X - left, point.Y - Padding.Top);
return item;
}
left += width;
}
itemRelativePoint = new Point();
return null;
}
public void OnMouseClick(MouseEventArgs e, Point point)
{
if (point.Y > RowHeight + Padding.Vertical)
{
Point rowRelativePoint;
CustomListRow row = SelectChild(point, out rowRelativePoint);
if (row == null)
return;
row.OnMouseClick(e, rowRelativePoint);
}
else
{
Point itemRelativePoint;
CustomListItem item = GetItemFromPosition(point, out itemRelativePoint);
if (item == null)
return;
item.OnMouseClick(e, itemRelativePoint);
}
}
public void OnMouseDoubleClick(MouseEventArgs e, Point point)
{
if (e.Button == MouseButtons.Left)
{
if (DefaultMenuItem != null)
DefaultMenuItem.PerformClick();
}
if (point.Y > RowHeight + Padding.Vertical)
{
Point rowRelativePoint;
CustomListRow row = SelectChild(point, out rowRelativePoint);
if (row == null)
return;
row.OnMouseDoubleClick(e, rowRelativePoint);
}
else
{
Point itemRelativePoint;
CustomListItem item = GetItemFromPosition(point, out itemRelativePoint);
if (item == null)
return;
item.OnMouseDoubleClick(e, itemRelativePoint);
}
}
public void OnMouseDown(Point point)
{
if (point.Y > RowHeight + Padding.Vertical)
{
Point rowRelativePoint;
CustomListRow row = SelectChild(point, out rowRelativePoint);
if (row == null)
{
ParentPanel.ClearSelection();
return;
}
row.OnMouseDown(rowRelativePoint);
}
else
{
if (!Selectable)
return;
ParentPanel.ClearSelection();
Selected = true;
ParentPanel.SelectedRow = this;
ParentPanel.Invalidate();
}
}
/*
* This code is almost identical to the code for tracking mouse movements
* in the CustomGridRow.
*/
private CustomListItem currentItem;
private CustomListRow currentRow;
public virtual void OnMouseEnter(Point point)
{
System.Diagnostics.Trace.Assert(currentItem == null && currentRow == null);
if (point.Y > RowHeight + Padding.Vertical)
{
Point rowRelativePoint;
currentRow = SelectChild(point, out rowRelativePoint);
if (currentRow == null)
return;
currentRow.OnMouseEnter(rowRelativePoint);
}
else
{
Point itemRelativePoint;
currentItem = GetItemFromPosition(point, out itemRelativePoint);
if (currentItem == null)
return;
currentItem.OnMouseEnter(itemRelativePoint);
}
}
public virtual void OnMouseMove(Point point)
{
System.Diagnostics.Trace.Assert(currentItem == null || currentRow == null);
if (point.Y > RowHeight + Padding.Vertical)
{
if (currentItem != null)
{
currentItem.OnMouseLeave();
currentItem = null;
}
Point rowRelativePoint;
CustomListRow row = SelectChild(point, out rowRelativePoint);
if (row != null && currentRow == row)
{
currentRow.OnMouseMove(rowRelativePoint);
return;
}
if (currentRow != null)
currentRow.OnMouseLeave();
currentRow = row;
if (currentRow != null)
currentRow.OnMouseEnter(rowRelativePoint);
}
else
{
if(currentRow != null)
{
currentRow.OnMouseLeave();
currentRow = null;
}
Point itemRelativePoint;
CustomListItem item = GetItemFromPosition(point, out itemRelativePoint);
if (item != null && currentItem == item)
{
currentItem.OnMouseMove(itemRelativePoint);
return;
}
if (currentItem != null)
currentItem.OnMouseLeave();
currentItem = item;
if (currentItem != null)
currentItem.OnMouseEnter(itemRelativePoint);
}
}
public virtual void OnMouseLeave()
{
System.Diagnostics.Trace.Assert(currentItem == null || currentRow == null);
if (currentItem != null)
{
currentItem.OnMouseLeave();
currentItem = null;
}
if (currentRow != null)
{
currentRow.OnMouseLeave();
currentRow = null;
}
}
}
}