using System; using System.Collections; using System.ComponentModel; using System.Drawing.Design; namespace DevComponents.DotNetBar.SuperGrid { /// /// Defines the collection of grid columns /// [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 /// /// Occurs when the collection has changed /// [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 /// /// Gets reference to first selectable column /// or null if there is no first selectable column. /// [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 /// /// Gets reference to first visible column /// or null if there is no first visible column. /// [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 /// /// Returns reference to the object in collection based on it's index. /// [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public GridColumn this[int index] { get { return (GridColumn)(List[index]); } set { List[index] = value; } } #endregion #region Name indexer /// /// Name indexer /// /// /// [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 /// Gets reference to last selectable column /// or null if there is no last selectable column. /// [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 /// /// Gets reference to last visible column /// or null if there is no last visible column. /// [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 /// /// Gets or sets the node this collection is associated with. /// [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public GridElement ParentItem { get { return _ParentItem; } internal set { _ParentItem = value; OnParentItemChanged(); } } private void OnParentItemChanged() { } #endregion #endregion #region Add /// /// Adds new object to the collection. /// /// Object to add. /// Index of newly added object. public int Add(GridColumn value) { value.ColumnIndex = List.Add(value); return (value.ColumnIndex); } #endregion #region Insert /// /// Inserts new object into the collection. /// /// Position of the object. /// Object to insert. 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 /// /// Returns index of the object inside of the collection. /// /// Reference to the object. /// Index of the object. public int IndexOf(GridColumn value) { return (List.IndexOf(value)); } #endregion #region Contains /// /// Returns whether collection contains specified object. /// /// Object to look for. /// true if object is part of the collection, otherwise false. public bool Contains(GridColumn value) { return (List.Contains(value)); } /// /// Returns whether collection contains specified object. /// /// Name of the object to look for. /// true if object is part of the collection, otherwise false. public bool Contains(string name) { foreach (GridColumn column in List) { if (column.Name.Equals(name) == true) return (true); } return (false); } #endregion #region Remove /// /// Removes specified object from the collection. /// /// public void Remove(GridColumn value) { List.Remove(value); for (int i = 0; i < Count; i++) ((GridColumn)List[i]).ColumnIndex = i; } #endregion #region OnRemoveComplete /// /// Called when remove of an item is completed. /// /// Index of removed item /// Removed item. 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 /// /// Clears all objects from the collection. /// public new void Clear() { foreach (GridColumn column in this) ResetColumn(column.GridPanel, column); List.Clear(); } #endregion #region OnClearComplete /// /// OnClearComplete /// 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 /// /// Called when insertion of an item is completed. /// /// Insert index. /// Inserted item. 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 /// /// Invalidates the display indexes and /// causes them to be re-evaluated on next layout. /// 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 /// /// Copies collection into the specified array. /// /// Array to copy collection to. /// Starting index. public void CopyTo(GridColumn[] array, int index) { List.CopyTo(array, index); } /// /// Copies contained items to the ColumnHeader array. /// /// Array to copy to. internal void CopyTo(GridColumn[] array) { List.CopyTo(array, 0); } #endregion #region OnClear /// /// Called when collection is cleared. /// 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 /// /// A map of display index (key) to index in the column collection /// (value). Used to quickly find a column from its display index. /// internal int[] DisplayIndexMap { get { if (!_IsDisplayIndexValid) UpdateDisplayIndexMap(); return (_DisplayIndexMap); } } #endregion #region GetDisplayIndex /// /// Gets the display index for specified column. /// /// Column that is part of ColumnHeaderCollection /// Display index or -1 column is not part of this collection. public int GetDisplayIndex(GridColumn column) { return (GetDisplayIndex(IndexOf(column))); } /// /// Gets the display index for specified column. /// ///Column index ///Display index or -1 column is not part of this collection. 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 /// /// Returns the column that is displayed at specified display index. /// /// 0 based display index. /// ColumnHeader 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 /// /// Gets reference to next visible column /// or null if there is no next visible column /// 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 /// /// Gets reference to previous visible column /// or null if there is no last visible previous column /// 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 /// /// Gets reference to the last visible frozen column /// or null if there is none /// 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 } }