mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-05 01:20:42 +00:00
c38affcded
* All renderdoc code up to this point was written by me, history is available by request
625 lines
15 KiB
C#
625 lines
15 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Text;
|
|
using System.Diagnostics;
|
|
|
|
using System.ComponentModel;
|
|
using System.ComponentModel.Design;
|
|
using System.ComponentModel.Design.Serialization;
|
|
using System.Reflection;
|
|
using System.Windows.Forms;
|
|
|
|
// Taken from http://www.codeproject.com/Articles/23746/TreeView-with-Columns with minor tweaks
|
|
// and fixes for my purposes.
|
|
namespace TreelistView
|
|
{
|
|
public class HitInfo
|
|
{
|
|
public enum eHitType
|
|
{
|
|
kColumnHeader = 0x0001,
|
|
kColumnHeaderResize = 0x0002,
|
|
}
|
|
|
|
public eHitType HitType = 0;
|
|
public TreeListColumn Column = null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// DesignTimeVisible(false) prevents the columns from showing in the component tray (bottom of screen)
|
|
/// If the class implement IComponent it must also implement default (void) constructor and when overriding
|
|
/// the collection editors CreateInstance the return object must be used (if implementing IComponent), the reason
|
|
/// is that ISite is needed, and ISite is set when base.CreateInstance is called.
|
|
/// If no default constructor then the object will not be added to the collection in the initialize.
|
|
/// In addition if implementing IComponent then name and generatemember is shown in the property grid
|
|
/// Columns should just be added to the collection, no need for member, so no need to implement IComponent
|
|
/// </summary>
|
|
[DesignTimeVisible(false)]
|
|
[TypeConverter(typeof(ColumnConverter))]
|
|
public class TreeListColumn
|
|
{
|
|
TreeList.TextFormatting m_headerFormat = new TreeList.TextFormatting();
|
|
TreeList.TextFormatting m_cellFormat = new TreeList.TextFormatting();
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
|
|
public TreeList.TextFormatting HeaderFormat
|
|
{
|
|
get { return m_headerFormat; }
|
|
}
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
|
|
public TreeList.TextFormatting CellFormat
|
|
{
|
|
get { return m_cellFormat; }
|
|
}
|
|
|
|
TreeListColumnCollection m_owner = null;
|
|
Rectangle m_calculatedRect;
|
|
int m_visibleIndex = -1;
|
|
int m_colIndex = -1;
|
|
int m_width = 50;
|
|
string m_fieldName = string.Empty;
|
|
string m_caption = string.Empty;
|
|
|
|
bool m_Moving = false;
|
|
|
|
internal TreeListColumnCollection Owner
|
|
{
|
|
get { return m_owner; }
|
|
set { m_owner = value; }
|
|
}
|
|
internal Rectangle internalCalculatedRect
|
|
{
|
|
get { return m_calculatedRect; }
|
|
set { m_calculatedRect = value; }
|
|
}
|
|
internal int internalVisibleIndex
|
|
{
|
|
get { return m_visibleIndex; }
|
|
set { m_visibleIndex = value; }
|
|
}
|
|
internal int internalIndex
|
|
{
|
|
get { return m_colIndex; }
|
|
set { m_colIndex = value; }
|
|
}
|
|
|
|
[Browsable(false)]
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
public bool Moving
|
|
{
|
|
get { return m_Moving; }
|
|
set
|
|
{
|
|
m_Moving = value;
|
|
}
|
|
}
|
|
|
|
[Browsable(false)]
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
public Rectangle CalculatedRect
|
|
{
|
|
get { return internalCalculatedRect; }
|
|
}
|
|
|
|
[Browsable(false)]
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
public TreeListView TreeList
|
|
{
|
|
get
|
|
{
|
|
if (Owner == null)
|
|
return null;
|
|
return Owner.Owner;
|
|
}
|
|
}
|
|
[Browsable(false)]
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
public Font Font
|
|
{
|
|
get { return m_owner.Font; }
|
|
}
|
|
public int Width
|
|
{
|
|
get { return m_width; }
|
|
set
|
|
{
|
|
if (m_width == value)
|
|
return;
|
|
m_width = value;
|
|
if (m_owner != null && m_owner.DesignMode)
|
|
m_owner.RecalcVisibleColumsRect();
|
|
}
|
|
}
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
public string Caption
|
|
{
|
|
get { return m_caption; }
|
|
set
|
|
{
|
|
m_caption = value;
|
|
if (m_owner != null)
|
|
m_owner.Invalidate();
|
|
}
|
|
}
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
public string Fieldname
|
|
{
|
|
get { return m_fieldName; }
|
|
set
|
|
{
|
|
if (m_owner == null || m_owner.DesignMode == false)
|
|
throw new Exception("Fieldname can only be set at design time, Use Constructor to set programatically");
|
|
if (value.Length == 0)
|
|
throw new Exception("empty Fieldname not value");
|
|
if (m_owner[value] != null)
|
|
throw new Exception("fieldname already exist in collection");
|
|
m_fieldName = value;
|
|
}
|
|
}
|
|
|
|
public TreeListColumn(string fieldName)
|
|
{
|
|
m_fieldName = fieldName;
|
|
}
|
|
public TreeListColumn(string fieldName, string caption)
|
|
{
|
|
m_fieldName = fieldName;
|
|
m_caption = caption;
|
|
}
|
|
public TreeListColumn(string fieldName, string caption, int width)
|
|
{
|
|
m_fieldName = fieldName;
|
|
m_caption = caption;
|
|
m_width = width;
|
|
}
|
|
|
|
[Browsable(false)]
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
public int VisibleIndex
|
|
{
|
|
get { return internalVisibleIndex; }
|
|
set
|
|
{
|
|
if (m_owner != null)
|
|
m_owner.SetVisibleIndex(this, value);
|
|
}
|
|
}
|
|
|
|
[Browsable(false)]
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
public int Index
|
|
{
|
|
get { return internalIndex; }
|
|
}
|
|
public bool ishot = false;
|
|
public virtual void Draw(Graphics dc, ColumnHeaderPainter painter, Rectangle r)
|
|
{
|
|
painter.DrawHeader(dc, r, this, this.HeaderFormat, ishot, m_Moving);
|
|
}
|
|
|
|
bool m_autoSize = false;
|
|
float m_autoSizeRatio = 100;
|
|
int m_autoSizeMinSize;
|
|
|
|
[DefaultValue(false)]
|
|
public bool AutoSize
|
|
{
|
|
get { return m_autoSize; }
|
|
set { m_autoSize = value; }
|
|
}
|
|
[DefaultValue(100f)]
|
|
public float AutoSizeRatio
|
|
{
|
|
get { return m_autoSizeRatio; }
|
|
set { m_autoSizeRatio = value; }
|
|
}
|
|
public int AutoSizeMinSize
|
|
{
|
|
get { return m_autoSizeMinSize; }
|
|
set { m_autoSizeMinSize = value; }
|
|
}
|
|
int m_calculatedAutoSize;
|
|
internal int CalculatedAutoSize
|
|
{
|
|
get { return m_calculatedAutoSize; }
|
|
set { m_calculatedAutoSize = value; }
|
|
}
|
|
}
|
|
|
|
[Description("This is the columns collection")]
|
|
//[TypeConverterAttribute(typeof(ColumnsTypeConverter))]
|
|
[Editor(typeof(ColumnCollectionEditor),typeof(System.Drawing.Design.UITypeEditor))]
|
|
public class TreeListColumnCollection : IList<TreeListColumn>, IList
|
|
{
|
|
ColumnHeaderPainter m_painter;
|
|
TreeList.CollumnSetting m_options;
|
|
TreeListView m_owner;
|
|
List<TreeListColumn> m_columns = new List<TreeListColumn>();
|
|
List<TreeListColumn> m_visibleCols = new List<TreeListColumn>();
|
|
Dictionary<string, TreeListColumn> m_columnMap = new Dictionary<string,TreeListColumn>();
|
|
|
|
[Browsable(false)]
|
|
public TreeList.CollumnSetting Options
|
|
{
|
|
get { return m_options; }
|
|
}
|
|
[Browsable(false)]
|
|
public ColumnHeaderPainter Painter
|
|
{
|
|
get { return m_painter; }
|
|
set { m_painter = value; }
|
|
}
|
|
[Browsable(false)]
|
|
public TreeListView Owner
|
|
{
|
|
get { return m_owner; }
|
|
}
|
|
[Browsable(false)]
|
|
public Font Font
|
|
{
|
|
get { return m_owner.Font; }
|
|
}
|
|
[Browsable(false)]
|
|
public TreeListColumn[] VisibleColumns
|
|
{
|
|
get { return m_visibleCols.ToArray(); }
|
|
}
|
|
[Browsable(false)]
|
|
public int ColumnsWidth
|
|
{
|
|
get
|
|
{
|
|
int width = 0;
|
|
foreach (TreeListColumn col in m_visibleCols)
|
|
{
|
|
if (col.AutoSize)
|
|
width += col.CalculatedAutoSize;
|
|
else
|
|
width += col.Width;
|
|
}
|
|
return width;
|
|
}
|
|
}
|
|
public TreeListColumnCollection(TreeListView owner)
|
|
{
|
|
m_owner = owner;
|
|
m_options = new TreeList.CollumnSetting(owner);
|
|
m_painter = new ColumnHeaderPainter(owner);
|
|
}
|
|
public TreeListColumn this[int index]
|
|
{
|
|
get
|
|
{
|
|
return m_columns[index];
|
|
}
|
|
set
|
|
{
|
|
m_columns[index] = value;
|
|
}
|
|
}
|
|
public TreeListColumn this[string fieldname]
|
|
{
|
|
get
|
|
{
|
|
TreeListColumn col;
|
|
m_columnMap.TryGetValue(fieldname, out col);
|
|
return col;
|
|
}
|
|
}
|
|
public void SetVisibleIndex(TreeListColumn col, int index)
|
|
{
|
|
m_visibleCols.Remove(col);
|
|
if (index >= 0)
|
|
{
|
|
if (index < m_visibleCols.Count)
|
|
m_visibleCols.Insert(index, col);
|
|
else
|
|
m_visibleCols.Add(col);
|
|
}
|
|
RecalcVisibleColumsRect();
|
|
}
|
|
public HitInfo CalcHitInfo(Point point, int horzOffset)
|
|
{
|
|
HitInfo info = new HitInfo();
|
|
info.Column = CalcHitColumn(point, horzOffset);
|
|
if ((info.Column != null) && (point.Y < Options.HeaderHeight))
|
|
{
|
|
info.HitType |= HitInfo.eHitType.kColumnHeader;
|
|
int right = info.Column.CalculatedRect.Right - horzOffset;
|
|
if (info.Column.AutoSize == false || info.Column.internalIndex+1 < m_columns.Count)
|
|
{
|
|
if (point.X >= right - 4 && point.X <= right)
|
|
info.HitType |= HitInfo.eHitType.kColumnHeaderResize;
|
|
}
|
|
}
|
|
return info;
|
|
}
|
|
public TreeListColumn CalcHitColumn(Point point, int horzOffset)
|
|
{
|
|
if (point.X < Options.LeftMargin)
|
|
return null;
|
|
foreach (TreeListColumn col in m_visibleCols)
|
|
{
|
|
int left = col.CalculatedRect.Left - horzOffset;
|
|
int right = col.CalculatedRect.Right - horzOffset;
|
|
if (point.X >= left && point.X <= right)
|
|
return col;
|
|
}
|
|
return null;
|
|
}
|
|
public void RecalcVisibleColumsRect()
|
|
{
|
|
RecalcVisibleColumsRect(false);
|
|
}
|
|
public void RecalcVisibleColumsRect(bool isColumnResizing)
|
|
{
|
|
if (IsInitializing)
|
|
return;
|
|
int x = 0;//m_leftMargin;
|
|
if (m_owner.RowOptions.ShowHeader)
|
|
x = m_owner.RowOptions.HeaderWidth;
|
|
int y = 0;
|
|
int h = Options.HeaderHeight;
|
|
int index = 0;
|
|
foreach(TreeListColumn col in m_columns)
|
|
{
|
|
col.internalVisibleIndex = -1;
|
|
col.internalIndex = index++;
|
|
}
|
|
|
|
// calculate size requierd by fix columns and auto adjusted columns
|
|
// at the same time calculate total ratio value
|
|
int widthFixedColumns = 0;
|
|
int widthAutoSizeColumns = 0;
|
|
float totalRatio = 0;
|
|
foreach (TreeListColumn col in m_visibleCols)
|
|
{
|
|
if (col.AutoSize)
|
|
{
|
|
widthAutoSizeColumns += col.AutoSizeMinSize;
|
|
totalRatio += col.AutoSizeRatio;
|
|
}
|
|
else
|
|
widthFixedColumns += col.Width;
|
|
}
|
|
|
|
int clientWidth = m_owner.ClientRectangle.Width - m_owner.RowHeaderWidth();
|
|
// find ratio 'unit' value
|
|
float remainingWidth = clientWidth - (widthFixedColumns + widthAutoSizeColumns);
|
|
float ratioUnit = 0;
|
|
if (totalRatio > 0 && remainingWidth > 0)
|
|
ratioUnit = remainingWidth / totalRatio;
|
|
|
|
for (index = 0; index < m_visibleCols.Count; index++)
|
|
{
|
|
TreeListColumn col = m_visibleCols[index];
|
|
int width = col.Width;
|
|
if (col.AutoSize)
|
|
{
|
|
// if doing column resizing then keep adjustable columns fixed at last width
|
|
if (m_options.FreezeWhileResizing && isColumnResizing)
|
|
width = col.CalculatedAutoSize;
|
|
else
|
|
width = Math.Max(10, col.AutoSizeMinSize + (int)Math.Round(ratioUnit * col.AutoSizeRatio - 1.0f));
|
|
col.CalculatedAutoSize = width;
|
|
}
|
|
col.internalCalculatedRect = new Rectangle(x, y, width, h);
|
|
col.internalVisibleIndex = index;
|
|
x += width;
|
|
}
|
|
Invalidate();
|
|
}
|
|
public void Draw(Graphics dc, Rectangle rect, int horzOffset)
|
|
{
|
|
foreach (TreeListColumn col in m_visibleCols)
|
|
{
|
|
Rectangle r = col.CalculatedRect;
|
|
r.X -= horzOffset;
|
|
if (r.Left > rect.Right)
|
|
break;
|
|
col.Draw(dc, m_painter, r);
|
|
}
|
|
// drwa row header filler
|
|
if (m_owner.RowOptions.ShowHeader)
|
|
{
|
|
Rectangle r = new Rectangle(0, 0, m_owner.RowOptions.HeaderWidth, Options.HeaderHeight);
|
|
m_painter.DrawHeaderFiller(dc, r);
|
|
}
|
|
}
|
|
public void AddRange(IEnumerable<TreeListColumn> columns)
|
|
{
|
|
foreach (TreeListColumn col in columns)
|
|
Add(col);
|
|
}
|
|
/// <summary>
|
|
/// AddRange(Item[]) is required for the designer.
|
|
/// </summary>
|
|
/// <param name="columns"></param>
|
|
public void AddRange(TreeListColumn[] columns)
|
|
{
|
|
foreach (TreeListColumn col in columns)
|
|
Add(col);
|
|
}
|
|
public void Add(TreeListColumn item)
|
|
{
|
|
bool designmode = Owner.DesignMode;
|
|
if (!designmode)
|
|
{
|
|
Debug.Assert(m_columnMap.ContainsKey(item.Fieldname) == false);
|
|
Debug.Assert(item.Owner == null, "column.Owner == null");
|
|
}
|
|
else
|
|
{
|
|
m_columns.Remove(item);
|
|
m_visibleCols.Remove(item);
|
|
}
|
|
|
|
item.Owner = this;
|
|
m_columns.Add(item);
|
|
m_visibleCols.Add(item);
|
|
m_columnMap[item.Fieldname] = item;
|
|
RecalcVisibleColumsRect();
|
|
//return item;
|
|
}
|
|
public void Clear()
|
|
{
|
|
m_columnMap.Clear();
|
|
m_columns.Clear();
|
|
m_visibleCols.Clear();
|
|
}
|
|
public bool Contains(TreeListColumn item)
|
|
{
|
|
return m_columns.Contains(item);
|
|
}
|
|
[Browsable(false)]
|
|
public int Count
|
|
{
|
|
get { return m_columns.Count; }
|
|
}
|
|
[Browsable(false)]
|
|
public bool IsReadOnly
|
|
{
|
|
get { return false; }
|
|
}
|
|
#region IList<TreeListColumn> Members
|
|
|
|
public int IndexOf(TreeListColumn item)
|
|
{
|
|
return m_columns.IndexOf(item);
|
|
}
|
|
|
|
public void Insert(int index, TreeListColumn item)
|
|
{
|
|
m_columns.Insert(index, item);
|
|
}
|
|
|
|
public void RemoveAt(int index)
|
|
{
|
|
if (index >= 0 && index < m_columns.Count)
|
|
{
|
|
TreeListColumn col = m_columns[index];
|
|
SetVisibleIndex(col, -1);
|
|
m_columnMap.Remove(col.Fieldname);
|
|
}
|
|
m_columns.RemoveAt(index);
|
|
}
|
|
|
|
#endregion
|
|
#region ICollection<TreeListColumn> Members
|
|
|
|
|
|
public void CopyTo(TreeListColumn[] array, int arrayIndex)
|
|
{
|
|
m_columns.CopyTo(array, arrayIndex);
|
|
}
|
|
|
|
public bool Remove(TreeListColumn item)
|
|
{
|
|
SetVisibleIndex(item, -1);
|
|
m_columnMap.Remove(item.Fieldname);
|
|
return m_columns.Remove(item);
|
|
}
|
|
|
|
#endregion
|
|
#region IEnumerable<TreeListColumn> Members
|
|
|
|
public IEnumerator<TreeListColumn> GetEnumerator()
|
|
{
|
|
return m_columns.GetEnumerator();
|
|
}
|
|
|
|
#endregion
|
|
#region IEnumerable Members
|
|
IEnumerator IEnumerable.GetEnumerator()
|
|
{
|
|
return GetEnumerator();
|
|
}
|
|
#endregion
|
|
#region IList Members
|
|
int IList.Add(object value)
|
|
{
|
|
Add((TreeListColumn)value);
|
|
return Count - 1;
|
|
}
|
|
bool IList.Contains(object value)
|
|
{
|
|
return Contains((TreeListColumn)value);
|
|
}
|
|
int IList.IndexOf(object value)
|
|
{
|
|
return IndexOf((TreeListColumn)value);
|
|
}
|
|
void IList.Insert(int index, object value)
|
|
{
|
|
Insert(index, (TreeListColumn)value);
|
|
}
|
|
|
|
bool IList.IsFixedSize
|
|
{
|
|
get { return false; }
|
|
}
|
|
|
|
void IList.Remove(object value)
|
|
{
|
|
Remove((TreeListColumn)value);
|
|
}
|
|
|
|
object IList.this[int index]
|
|
{
|
|
get
|
|
{
|
|
throw new Exception("The method or operation is not implemented.");
|
|
}
|
|
set
|
|
{
|
|
throw new Exception("The method or operation is not implemented.");
|
|
}
|
|
}
|
|
#endregion
|
|
#region ICollection Members
|
|
|
|
public void CopyTo(Array array, int index)
|
|
{
|
|
throw new Exception("The method or operation is not implemented.");
|
|
}
|
|
|
|
public bool IsSynchronized
|
|
{
|
|
get { throw new Exception("The method or operation is not implemented."); }
|
|
}
|
|
|
|
public object SyncRoot
|
|
{
|
|
get { throw new Exception("The method or operation is not implemented."); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
internal bool DesignMode
|
|
{
|
|
get
|
|
{
|
|
if (m_owner != null)
|
|
return m_owner.DesignMode;
|
|
return false;
|
|
}
|
|
}
|
|
internal void Invalidate()
|
|
{
|
|
if (m_owner != null)
|
|
m_owner.Invalidate();
|
|
}
|
|
bool IsInitializing = false;
|
|
internal void BeginInit()
|
|
{
|
|
IsInitializing = true;
|
|
}
|
|
internal void EndInit()
|
|
{
|
|
IsInitializing = false;
|
|
RecalcVisibleColumsRect();
|
|
}
|
|
}
|
|
}
|