using System; using System.Drawing; using DevComponents.DotNetBar.SuperGrid.Style; namespace DevComponents.DotNetBar.SuperGrid { /// /// Defines a merged cell range, comprised /// of a starting and ending row,column index pair. /// public class CellRange : DisplayRange { #region Private variables private Cs _States; private CellRangeData _CellRangeData; private object _Tag; private string _ToolTip; private ushort _StyleUpdateCount; #endregion #region Constructors /// /// Defines a merged cell range, comprised /// of a starting and ending row,column index pair. /// public CellRange() { AllowSuspend = true; AllowSelection = true; } /// /// Defines a merged cell range, comprised /// of a starting and ending row,column index pair. /// ///Initial start and end row index ///Initial start and end column index public CellRange(int rowIndex, int columnIndex) : this() { RowStart = rowIndex; ColumnStart = columnIndex; RowCount = 1; ColumnCount = 1; } /// /// Defines a merged cell range, comprised /// of a starting and ending row,column index pair. /// ///Starting row index ///Starting column index ///Row count ///Column count public CellRange(int startRowIndex, int startColumnIndex, int rowCount, int columnCount) : this() { RowStart = startRowIndex; ColumnStart = startColumnIndex; RowCount = rowCount; ColumnCount = columnCount; } #endregion #region Public properties #region AllowSelection /// /// Gets or sets whether the range can be selected /// public bool AllowSelection { get { return (TestState(Cs.AllowSelection)); } set { SetState(Cs.AllowSelection, value); } } #endregion #region AllowSuspend /// /// Gets or sets whether the merged cell range can be temporarily /// suspended when either the user double clicks the displayed range /// or the application initiates a cell.SuspendMerge(). /// public bool AllowSuspend { get { return (TestState(Cs.AllowSuspend)); } set { SetState(Cs.AllowSuspend, value); } } #endregion #region AlwaysDisplayFormattedValue /// /// Gets or sets whether the 'FormattedValue' value will be /// displayed for all cell types when merged, or only for Modal Cells. /// public bool AlwaysDisplayFormattedValue { get { return (TestState(Cs.AlwaysDisplayFormattedValue)); } set { SetState(Cs.AlwaysDisplayFormattedValue, value); } } #endregion #region BackBounds /// /// Gets the range display bounds /// public Rectangle BackBounds { get { return (RangeData.BackBounds); } internal set { RangeData.BackBounds = value; } } #endregion #region CellStyles /// /// Gets or sets the visual styles assigned to the cell /// public CellVisualStyles CellStyles { get { if (RangeData.CellStyles == null) RangeData.CellStyles = new CellVisualStyles(); return (RangeData.CellStyles); } set { RangeData.CellStyles = value; } } #endregion #region FormattedValue /// /// Gets or sets the formatted value for the range display. This value will /// be displayed by default for all Modal Cells - all other cells will /// have their default cell rendering displayed when merged /// (unless 'AlwaysDisplayFormattedValue' is set to true). /// public string FormattedValue { get { return (RangeData.FormattedValue); } set { RangeData.FormattedValue = value; } } #endregion #region Tag /// /// Gets or sets user-defined data associated with the object /// public object Tag { get { return (_Tag); } set { _Tag = value; } } #endregion #region ToolTip /// /// Gets or sets the ToolTip text for the cell range. /// public string ToolTip { get { return (_ToolTip); } set { _ToolTip = value; } } #endregion #endregion #region Internal properties #region Modified internal bool Modified { get { return (TestState(Cs.Modified)); } set { SetState(Cs.Modified, value); } } #endregion #region RenderCount internal int RenderCount { get { return (RangeData.RenderCount); } set { RangeData.RenderCount = value; } } #endregion #region SelectionUpdateCount internal int SelectionUpdateCount { get { return (RangeData.SelectionUpdateCount); } set { RangeData.SelectionUpdateCount = value; } } #endregion #region Suspended internal bool Suspended { get { return (TestState(Cs.Suspended)); } set { SetState(Cs.Suspended, value); } } #endregion #endregion #region Private properties #region EffectiveStyles /// /// Gets or sets the 'effective' visual styles assigned to the range /// private CellVisualStyles EffectiveStyles { get { return (RangeData.EffectiveStyles); } set { RangeData.EffectiveStyles = value; } } #endregion #region RangeData private CellRangeData RangeData { get { if (_CellRangeData == null) _CellRangeData = new CellRangeData(); return (_CellRangeData); } } #endregion #endregion #region TestState private bool TestState(Cs state) { return ((_States & state) == state); } #endregion #region SetState private void SetState(Cs state, bool value) { if (value == true) _States |= state; else _States &= ~state; } #endregion #region GetEffectiveStyle internal CellVisualStyle GetEffectiveStyle(GridContainer cont, StyleState cellState) { switch (cellState) { case StyleState.MouseOver: return (GetStyle(cont, StyleType.MouseOver)); case StyleState.Selected: return (GetStyle(cont, StyleType.Selected)); case StyleState.Selected | StyleState.MouseOver: return (GetStyle(cont, StyleType.SelectedMouseOver)); case StyleState.ReadOnly: return (GetStyle(cont, StyleType.ReadOnly)); case StyleState.ReadOnly | StyleState.MouseOver: return (GetStyle(cont, StyleType.ReadOnlyMouseOver)); case StyleState.ReadOnly | StyleState.Selected: return (GetStyle(cont, StyleType.ReadOnlySelected)); case StyleState.ReadOnly | StyleState.MouseOver | StyleState.Selected: return (GetStyle(cont, StyleType.ReadOnlySelectedMouseOver)); default: return (GetStyle(cont, StyleType.Default)); } } #region GetStyle private CellVisualStyle GetStyle(GridContainer cont, StyleType e) { GridPanel panel = cont.GridPanel; ValidateStyle(panel); CellVisualStyles cvs = EffectiveStyles ?? new CellVisualStyles(); if (cvs.IsValid(e) == false) { CellVisualStyle style = new CellVisualStyle(); StyleType[] css = style.GetApplyStyleTypes(e); if (css != null) { int cindex = panel.Columns.DisplayIndexMap[ColumnStart]; GridRow row = null; GridColumn column = panel.Columns.ColumnAtDisplayIndex(ColumnStart); if (RowCount == 1) { GridCell cell = cont.GetCell(RowStart, cindex); if (cell != null) row = cell.GridRow; } foreach (StyleType cs in css) { if (column != null) column.ApplyCellStyle(style, cs); if (row != null) row.ApplyCellStyle(style, cs); panel.ApplyMergedCellStyle(style, cs); if (RangeData.CellStyles != null) style.ApplyStyle(RangeData.CellStyles[cs]); } } panel.SuperGrid.DoGetMergedCellStyleEvent(panel, this, e, ref style); if (style.Background == null || style.Background.IsEmpty == true) style.Background = new Background(Color.White); if (style.Font == null) style.Font = SystemFonts.DefaultFont; cvs[e] = style; } EffectiveStyles = cvs; return (EffectiveStyles[e]); } #endregion #region ValidateStyle private void ValidateStyle(GridPanel panel) { if (_StyleUpdateCount != panel.SuperGrid.StyleUpdateCount) ClearEffectiveStyles(); _StyleUpdateCount = panel.SuperGrid.StyleUpdateCount; } #endregion #region InvalidateStyle /// ///Invalidates the cached Style ///definition for all defined StyleTypes /// public void InvalidateStyle() { ClearEffectiveStyles(); } /// ///Invalidate the cached Style ///definition for the given StyleType /// /// public void InvalidateStyle(StyleType type) { if (EffectiveStyles != null) EffectiveStyles[type] = null; } #endregion #region ClearEffectiveStyles internal void ClearEffectiveStyles() { if (EffectiveStyles != null) { EffectiveStyles.Dispose(); EffectiveStyles = null; } } #endregion #endregion #region IsSelected internal bool IsSelected(GridPanel panel, GridContainer cont) { if (AllowSelection == true) { if (panel.AllowSelection == true) { if (RangeData.SelectionUpdateCount != panel.SelectionUpdateCount) { RangeData.SelectionUpdateCount = panel.SelectionUpdateCount; SetState(Cs.Selected, IsMergeSelected(panel, cont)); } return (TestState(Cs.Selected)); } } return (false); } #region IsMergeSelected private bool IsMergeSelected(GridPanel panel, GridContainer cont) { int rowCount = GetRowCount(panel, cont); if (RowIsSelected(panel, cont, rowCount)) return (true); if (ColumnIsSelected(panel)) return (true); return (CellIsSelected(panel, cont, rowCount)); } #region RowIsSelected private bool RowIsSelected(GridPanel panel, GridContainer cont, int rowCount) { for (int i = RowStart; i < RowEnd; i++) { if (i < rowCount) { GridContainer row = GetRow(panel, cont, i); if (row != null) { if (row.IsSelected == true) return (true); } } } return (false); } #endregion #region ColumnIsSelected private bool ColumnIsSelected(GridPanel panel) { int[] map = panel.Columns.DisplayIndexMap; for (int i = ColumnStart; i < ColumnEnd; i++) { if (i < panel.Columns.Count) { if (panel.Columns[map[i]].IsSelected == true) return (true); } } return (false); } #endregion #region CellIsSelected private bool CellIsSelected(GridPanel panel, GridContainer cont, int rowCount) { int[] map = panel.Columns.DisplayIndexMap; for (int i = RowStart; i < RowEnd; i++) { if (i < rowCount) { GridRow row = GetRow(panel, cont, i) as GridRow; if (row != null) { for (int j = ColumnStart; j < ColumnEnd; j++) { if (j < panel.Columns.Count) { GridCell cell = row.GetCell(map[j]); if (cell != null) { if (panel.IsItemSelectedEx(cell) == true) return (true); } } } } } } return (false); } #endregion #region GetRowCount private int GetRowCount(GridPanel panel, GridContainer cont) { if (panel.VirtualMode == true) return (panel.VirtualRowCount); return (cont.Rows.Count); } #endregion #region GetRow private GridContainer GetRow(GridPanel panel, GridContainer cont, int index) { return (panel.VirtualMode == true) ? panel.VirtualRows[index] : cont.Rows[index] as GridContainer; } #endregion #endregion #endregion #region CellStates [Flags] private enum Cs { AllowSelection = (1 << 0), AllowSuspend = (1 << 1), AlwaysDisplayFormattedValue = (1 << 2), Modified = (1 << 3), Selected = (1 << 4), Suspended = (1 << 5), } #endregion #region CellRangeData private class CellRangeData { #region Private data private int _RenderCount; private int _SelectionUpdateCount; private Rectangle _BackBounds; private string _FormattedValue; private CellVisualStyles _CellStyles; private CellVisualStyles _EffectiveStyles; #endregion #region public properties #region BackBounds public Rectangle BackBounds { get { return (_BackBounds); } set { _BackBounds = value; } } #endregion #region CellStyles public CellVisualStyles CellStyles { get { return (_CellStyles); } set { _CellStyles = value; } } #endregion #region EffectiveStyles public CellVisualStyles EffectiveStyles { get { return (_EffectiveStyles); } set { _EffectiveStyles = value; } } #endregion #region FormattedValue public string FormattedValue { get { return (_FormattedValue); } set { _FormattedValue = value; } } #endregion #region RenderCount public int RenderCount { get { return (_RenderCount); } set { _RenderCount = value; } } #endregion #region SelectionUpdateCount public int SelectionUpdateCount { get { return (_SelectionUpdateCount); } set { _SelectionUpdateCount = value; } } #endregion #endregion } #endregion } #region DisplayRange /// ///Row/Column display index range /// public class DisplayRange { #region Private variables private int _RowStart; private int _RowCount; private int _ColumnStart; private int _ColumnCount; #endregion #region Public properties #region ColumnCount /// ///Number of columns /// public int ColumnCount { get { return (_ColumnCount); } set { if (value < 0) throw new ArgumentException(@"ColumnCount cannot be negative", "value"); _ColumnCount = value; } } #endregion #region ColumnEnd /// ///Ending column display index (exclusive) /// public int ColumnEnd { get { return (_ColumnStart + _ColumnCount); } set { int count = value - _ColumnStart; if (count < 0) throw new ArgumentException(@"ColumnEnd cannot be less than ColumnStart", "value"); ColumnCount = count; } } #endregion #region ColumnStart /// ///Starting column display index /// public int ColumnStart { get { return (_ColumnStart); } set { _ColumnStart = value; } } #endregion #region Contains internal bool Contains(int rowIndex, int columnIndex) { return ((rowIndex >= _RowStart && rowIndex < RowEnd) && (columnIndex >= _ColumnStart && columnIndex < ColumnEnd)); } #endregion #region RowCount /// ///Number of rows /// public int RowCount { get { return (_RowCount); } set { if (value < 0) throw new ArgumentException(@"RowCount cannot be negative", "value"); _RowCount = value; } } #endregion #region RowEnd /// ///Ending row index (exclusive) /// public int RowEnd { get { return (_RowStart + _RowCount); } set { int count = value - _RowStart; if (count < 0) throw new ArgumentException(@"RowEnd cannot be less than RowStart", "value"); RowCount = count; } } #endregion #region RowStart /// ///Starting row index /// public int RowStart { get { return (_RowStart); } set { _RowStart = value; } } #endregion #endregion #region IsRangeEqualTo /// ///Returns whether the display range is ///logically equal to the given item's display range. /// /// /// public bool IsRangeEqualTo(DisplayRange dr) { if (dr != null) { return (dr.RowStart == _RowStart && dr.ColumnStart == _ColumnStart && dr.RowCount == _RowCount && dr.ColumnCount == _ColumnCount); } return (false); } #endregion #region ToString /// /// ToString /// /// public override string ToString() { return ("RowStart = " + RowStart + ", RowEnd = " + RowEnd + " ColStart = " + ColumnStart + " ColEnd = " + ColumnEnd); } #endregion } #endregion }