788 lines
21 KiB
C#

using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing.Design;
namespace DevComponents.DotNetBar.SuperGrid
{
/// <summary>
/// Defines the collection of grid columns
/// </summary>
[Editor("DevComponents.SuperGrid.Design.GridColumnCollectionEditor, DevComponents.SuperGrid.Design, Version=14.1.0.37, Culture=neutral, PublicKeyToken=26d81176cfa2b486", typeof(UITypeEditor))]
public class GridColumnCollection : CollectionBase
{
#region Events
/// <summary>
/// Occurs when the collection has changed
/// </summary>
[Description("Occurs when collection has changed.")]
public CollectionChangeEventHandler CollectionChanged;
#endregion
#region Private Variables
private GridElement _ParentItem;
private int[] _DisplayIndexMap;
private bool _IsDisplayIndexValid;
#endregion
#region Public properties
#region FirstSelectableColumn
/// <summary>
/// Gets reference to first selectable column
/// or null if there is no first selectable column.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public GridColumn FirstSelectableColumn
{
get
{
int[] displayMap = DisplayIndexMap;
for (int i = 0; i < displayMap.Length; i++)
{
GridColumn column = this[displayMap[i]];
if (column.Visible == true && column.AllowSelection == true)
return (column);
}
return (null);
}
}
#endregion
#region FirstVisibleColumn
/// <summary>
/// Gets reference to first visible column
/// or null if there is no first visible column.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public GridColumn FirstVisibleColumn
{
get
{
int[] displayMap = DisplayIndexMap;
for (int i = 0; i < displayMap.Length; i++)
{
if (this[displayMap[i]].Visible)
return (this[displayMap[i]]);
}
return (null);
}
}
#endregion
#region Index indexer
/// <summary>
/// Returns reference to the object in collection based on it's index.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public GridColumn this[int index]
{
get { return (GridColumn)(List[index]); }
set { List[index] = value; }
}
#endregion
#region Name indexer
///<summary>
/// Name indexer
///</summary>
///<param name="name"></param>
///<exception cref="Exception"></exception>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public GridColumn this[string name]
{
get
{
int index = FindIndexByName(name);
return (index >= 0 ? this[index] : null);
}
set
{
int index = FindIndexByName(name);
if (index < 0)
throw new Exception("Column Name not defined (" + name + ").");
List[index] = value;
}
}
#region FindIndexByName
private int FindIndexByName(string name)
{
for (int i=0; i<List.Count; i++)
{
GridColumn item = (GridColumn)List[i];
if (name != null)
name = name.ToUpper();
if (item.Name != null && item.Name.ToUpper().Equals(name))
return (i);
}
return (-1);
}
#endregion
#endregion
#region LastSelectableColumn
/// <summary>
/// Gets reference to last selectable column
/// or null if there is no last selectable column.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public GridColumn LastSelectableColumn
{
get
{
int[] displayMap = DisplayIndexMap;
for (int i = displayMap.Length - 1; i >= 0; i--)
{
GridColumn column = this[displayMap[i]];
if (column.Visible == true && column.AllowSelection == true)
return (column);
}
return (null);
}
}
#endregion
#region LastVisibleColumn
/// <summary>
/// Gets reference to last visible column
/// or null if there is no last visible column.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public GridColumn LastVisibleColumn
{
get
{
int[] displayMap = DisplayIndexMap;
for (int i = displayMap.Length - 1; i >= 0; i--)
{
if (this[displayMap[i]].Visible)
return (this[displayMap[i]]);
}
return (null);
}
}
#endregion
#region ParentItem
/// <summary>
/// Gets or sets the node this collection is associated with.
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public GridElement ParentItem
{
get { return _ParentItem; }
internal set
{
_ParentItem = value;
OnParentItemChanged();
}
}
private void OnParentItemChanged()
{
}
#endregion
#endregion
#region Add
/// <summary>
/// Adds new object to the collection.
/// </summary>
/// <param name="value">Object to add.</param>
/// <returns>Index of newly added object.</returns>
public int Add(GridColumn value)
{
value.ColumnIndex = List.Add(value);
return (value.ColumnIndex);
}
#endregion
#region Insert
/// <summary>
/// Inserts new object into the collection.
/// </summary>
/// <param name="index">Position of the object.</param>
/// <param name="value">Object to insert.</param>
public void Insert(int index, GridColumn value)
{
List.Insert(index, value);
for (int i = 0; i < Count; i++)
((GridColumn)List[i]).ColumnIndex = i;
}
#endregion
#region IndexOf
/// <summary>
/// Returns index of the object inside of the collection.
/// </summary>
/// <param name="value">Reference to the object.</param>
/// <returns>Index of the object.</returns>
public int IndexOf(GridColumn value)
{
return (List.IndexOf(value));
}
#endregion
#region Contains
/// <summary>
/// Returns whether collection contains specified object.
/// </summary>
/// <param name="value">Object to look for.</param>
/// <returns>true if object is part of the collection, otherwise false.</returns>
public bool Contains(GridColumn value)
{
return (List.Contains(value));
}
/// <summary>
/// Returns whether collection contains specified object.
/// </summary>
/// <param name="name">Name of the object to look for.</param>
/// <returns>true if object is part of the collection, otherwise false.</returns>
public bool Contains(string name)
{
foreach (GridColumn column in List)
{
if (column.Name.Equals(name) == true)
return (true);
}
return (false);
}
#endregion
#region Remove
/// <summary>
/// Removes specified object from the collection.
/// </summary>
/// <param name="value"></param>
public void Remove(GridColumn value)
{
List.Remove(value);
for (int i = 0; i < Count; i++)
((GridColumn)List[i]).ColumnIndex = i;
}
#endregion
#region OnRemoveComplete
/// <summary>
/// Called when remove of an item is completed.
/// </summary>
/// <param name="index">Index of removed item</param>
/// <param name="value">Removed item.</param>
protected override void OnRemoveComplete(int index, object value)
{
if (value is GridColumn)
{
GridColumn column = (GridColumn)value;
GridPanel panel = column.GridPanel;
ResetColumn(panel, column);
}
OnCollectionChanged(CollectionChangeAction.Remove, value);
base.OnRemoveComplete(index, value);
}
#endregion
#region Clear
/// <summary>
/// Clears all objects from the collection.
/// </summary>
public new void Clear()
{
foreach (GridColumn column in this)
ResetColumn(column.GridPanel, column);
List.Clear();
}
#endregion
#region OnClearComplete
/// <summary>
/// OnClearComplete
/// </summary>
protected override void OnClearComplete()
{
InvalidateDisplayIndexes();
InvalidateLayout();
base.OnClearComplete();
}
#endregion
#region ResetColumn
private void ResetColumn(GridPanel panel, GridColumn column)
{
column.DisplayIndexChanged -= ColumnDisplayIndexChanged;
if (panel.DataSource != null)
panel.DataBinder.DataResetCount++;
GridCell cell = column.SuperGrid.ActiveElement as GridCell;
if (cell != null)
{
if (cell.ColumnIndex == column.ColumnIndex)
column.SuperGrid.ActiveElement = null;
}
if (panel.SortColumns.Contains(column))
panel.SortColumns.Remove(column);
if (panel.GroupColumns.Contains(column))
panel.GroupColumns.Remove(column);
FilterPanel fp = column.SuperGrid.ActiveFilterPanel;
if (fp != null && fp.GridColumn == column)
fp.EndEdit();
}
#endregion
#region OnInsertComplete
/// <summary>
/// Called when insertion of an item is completed.
/// </summary>
/// <param name="index">Insert index.</param>
/// <param name="value">Inserted item.</param>
protected override void OnInsertComplete(int index, object value)
{
if (value is GridColumn)
{
GridColumn column = (GridColumn)value;
if (column.Parent != null && column.Parent != _ParentItem)
throw new Exception("Column is already a member of another Column collection.");
column.DisplayIndexChanged += ColumnDisplayIndexChanged;
column.Parent = _ParentItem;
}
OnCollectionChanged(CollectionChangeAction.Add, value);
base.OnInsertComplete(index, value);
}
#endregion
#region OnCollectionChanged
private void OnCollectionChanged(
CollectionChangeAction action, object value)
{
for (int i = 0; i < Count; i++)
((GridColumn)List[i]).ColumnIndex = i;
if (action == CollectionChangeAction.Remove)
{
GridColumn rcol = (GridColumn)value;
GridPanel panel = rcol.GridPanel;
if (rcol.DisplayIndex >= 0)
{
foreach (GridColumn col in panel.Columns)
{
if (col.DisplayIndex > rcol.DisplayIndex)
col.DisplayIndex--;
}
}
}
InvalidateDisplayIndexes();
InvalidateLayout();
if (CollectionChanged != null)
{
CollectionChangeEventArgs e = new
CollectionChangeEventArgs(action, value);
CollectionChanged(this, e);
}
}
#endregion
#region ColumnDisplayIndexChanged
private void ColumnDisplayIndexChanged(object sender, EventArgs e)
{
InvalidateDisplayIndexes();
InvalidateLayout();
}
#endregion
#region InvalidateDisplayIndexes
/// <summary>
/// Invalidates the display indexes and
/// causes them to be re-evaluated on next layout.
/// </summary>
public void InvalidateDisplayIndexes()
{
_IsDisplayIndexValid = false;
}
#endregion
#region InvalidateLayout
private void InvalidateLayout()
{
if (_ParentItem != null)
{
_ParentItem.InvalidateLayout();
if (_ParentItem.SuperGrid != null)
{
_ParentItem.SuperGrid.NeedMergeLayout = true;
_ParentItem.SuperGrid.DisplayedMergeLayoutCount++;
}
}
}
#endregion
#region CopyTo
/// <summary>
/// Copies collection into the specified array.
/// </summary>
/// <param name="array">Array to copy collection to.</param>
/// <param name="index">Starting index.</param>
public void CopyTo(GridColumn[] array, int index)
{
List.CopyTo(array, index);
}
/// <summary>
/// Copies contained items to the ColumnHeader array.
/// </summary>
/// <param name="array">Array to copy to.</param>
internal void CopyTo(GridColumn[] array)
{
List.CopyTo(array, 0);
}
#endregion
#region OnClear
/// <summary>
/// Called when collection is cleared.
/// </summary>
protected override void OnClear()
{
if (Count > 0)
{
GridPanel panel = this[0].Parent as GridPanel;
if (panel != null)
{
panel.SuperGrid.ActiveElement = null;
foreach (GridElement item in panel.Rows)
{
GridRow row = item as GridRow;
if (row != null)
{
foreach (GridCell cell in row.Cells)
{
cell.EditControl = null;
cell.RenderControl = null;
}
}
}
}
}
foreach (GridColumn item in this)
{
item.EditControl = null;
item.RenderControl = null;
}
base.OnClear();
}
#endregion
#region DisplayIndexMap
/// <summary>
/// A map of display index (key) to index in the column collection
/// (value). Used to quickly find a column from its display index.
/// </summary>
internal int[] DisplayIndexMap
{
get
{
if (!_IsDisplayIndexValid)
UpdateDisplayIndexMap();
return (_DisplayIndexMap);
}
}
#endregion
#region GetDisplayIndex
/// <summary>
/// Gets the display index for specified column.
/// </summary>
/// <param name="column">Column that is part of ColumnHeaderCollection</param>
/// <returns>Display index or -1 column is not part of this collection.</returns>
public int GetDisplayIndex(GridColumn column)
{
return (GetDisplayIndex(IndexOf(column)));
}
///<summary>
/// Gets the display index for specified column.
///</summary>
///<param name="index">Column index</param>
///<returns>Display index or -1 column is not part of this collection.</returns>
public int GetDisplayIndex(int index)
{
UpdateDisplayIndexMap();
for (int i = 0; i < _DisplayIndexMap.Length; i++)
{
if (_DisplayIndexMap[i] == index)
return (i);
}
return (-1);
}
#endregion
#region ColumnAtDisplayIndex
/// <summary>
/// Returns the column that is displayed at specified display index.
/// </summary>
/// <param name="displayIndex">0 based display index.</param>
/// <returns>ColumnHeader</returns>
public GridColumn ColumnAtDisplayIndex(int displayIndex)
{
UpdateDisplayIndexMap();
return (this[_DisplayIndexMap[displayIndex]]);
}
#endregion
#region UpdateDisplayIndexMap
private void UpdateDisplayIndexMap()
{
if (_IsDisplayIndexValid == false)
{
_IsDisplayIndexValid = true;
_DisplayIndexMap = new int[Count];
for (int i = 0; i < Count; i++)
_DisplayIndexMap[i] = -1;
for (int i = 0; i < Count; i++)
{
int di = this[i].DisplayIndex;
if (di != -1)
AddIndexToMap(i, di);
}
int n = 0;
for (int i = 0; i < Count; i++)
{
int di = this[i].DisplayIndex;
if (di == -1)
AddIndexToMap(i, n++);
}
}
}
private void AddIndexToMap(int i, int di)
{
for (int j = 0; j < Count; j++)
{
int n = (di + j) % Count;
if (_DisplayIndexMap[n] == -1)
{
_DisplayIndexMap[n] = i;
break;
}
}
}
#endregion
#region GetNextVisibleColumn
/// <summary>
/// Gets reference to next visible column
/// or null if there is no next visible column
/// </summary>
public GridColumn GetNextVisibleColumn(GridColumn column)
{
return (GetNextVisibleColumn(GetDisplayIndex(column)));
}
internal GridColumn GetNextVisibleColumn(int displayIndex)
{
int[] displayMap = DisplayIndexMap;
while (++displayIndex < Count)
{
if (this[displayMap[displayIndex]].Visible)
return (this[displayMap[displayIndex]]);
}
return (null);
}
#endregion
#region GetPrevVisibleColumn
/// <summary>
/// Gets reference to previous visible column
/// or null if there is no last visible previous column
/// </summary>
public GridColumn GetPrevVisibleColumn(GridColumn column)
{
return (GetPrevVisibleColumn(GetDisplayIndex(column)));
}
internal GridColumn GetPrevVisibleColumn(int displayIndex)
{
int[] displayMap = DisplayIndexMap;
while (--displayIndex >= 0)
{
if (this[displayMap[displayIndex]].Visible)
return (this[displayMap[displayIndex]]);
}
return (null);
}
#endregion
#region GetLastVisibleFrozenColumn
/// <summary>
/// Gets reference to the last visible frozen column
/// or null if there is none
/// </summary>
public GridColumn GetLastVisibleFrozenColumn()
{
int[] displayMap = DisplayIndexMap;
if (displayMap.Length > 0)
{
GridPanel panel = this[displayMap[0]].GridPanel;
if (panel != null &&
panel.FrozenColumnCount > 0 && panel.IsSubPanel == false)
{
for (int i = displayMap.Length - 1; i >= 0; i--)
{
GridColumn column = this[displayMap[i]];
if (column.Visible == true)
{
if (column.IsHFrozen == true)
return (column);
}
}
}
}
return (null);
}
#endregion
}
}