859 lines
21 KiB
C#
859 lines
21 KiB
C#
using System;
|
|
using System.Drawing;
|
|
using DevComponents.DotNetBar.SuperGrid.Style;
|
|
|
|
namespace DevComponents.DotNetBar.SuperGrid
|
|
{
|
|
///<summary>
|
|
/// Defines a merged cell range, comprised
|
|
/// of a starting and ending row,column index pair.
|
|
///</summary>
|
|
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
|
|
|
|
///<summary>
|
|
/// Defines a merged cell range, comprised
|
|
/// of a starting and ending row,column index pair.
|
|
///</summary>
|
|
public CellRange()
|
|
{
|
|
AllowSuspend = true;
|
|
AllowSelection = true;
|
|
}
|
|
|
|
///<summary>
|
|
/// Defines a merged cell range, comprised
|
|
/// of a starting and ending row,column index pair.
|
|
///</summary>
|
|
///<param name="rowIndex">Initial start and end row index</param>
|
|
///<param name="columnIndex">Initial start and end column index</param>
|
|
public CellRange(int rowIndex, int columnIndex)
|
|
: this()
|
|
{
|
|
RowStart = rowIndex;
|
|
ColumnStart = columnIndex;
|
|
|
|
RowCount = 1;
|
|
ColumnCount = 1;
|
|
}
|
|
|
|
///<summary>
|
|
/// Defines a merged cell range, comprised
|
|
/// of a starting and ending row,column index pair.
|
|
///</summary>
|
|
///<param name="startRowIndex">Starting row index</param>
|
|
///<param name="startColumnIndex">Starting column index</param>
|
|
///<param name="rowCount">Row count</param>
|
|
///<param name="columnCount">Column count</param>
|
|
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
|
|
|
|
///<summary>
|
|
/// Gets or sets whether the range can be selected
|
|
///</summary>
|
|
public bool AllowSelection
|
|
{
|
|
get { return (TestState(Cs.AllowSelection)); }
|
|
set { SetState(Cs.AllowSelection, value); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region AllowSuspend
|
|
|
|
///<summary>
|
|
/// 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().
|
|
///</summary>
|
|
public bool AllowSuspend
|
|
{
|
|
get { return (TestState(Cs.AllowSuspend)); }
|
|
set { SetState(Cs.AllowSuspend, value); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region AlwaysDisplayFormattedValue
|
|
|
|
///<summary>
|
|
/// Gets or sets whether the 'FormattedValue' value will be
|
|
/// displayed for all cell types when merged, or only for Modal Cells.
|
|
///</summary>
|
|
public bool AlwaysDisplayFormattedValue
|
|
{
|
|
get { return (TestState(Cs.AlwaysDisplayFormattedValue)); }
|
|
set { SetState(Cs.AlwaysDisplayFormattedValue, value); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region BackBounds
|
|
|
|
///<summary>
|
|
/// Gets the range display bounds
|
|
///</summary>
|
|
public Rectangle BackBounds
|
|
{
|
|
get { return (RangeData.BackBounds); }
|
|
internal set { RangeData.BackBounds = value; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region CellStyles
|
|
|
|
/// <summary>
|
|
/// Gets or sets the visual styles assigned to the cell
|
|
/// </summary>
|
|
public CellVisualStyles CellStyles
|
|
{
|
|
get
|
|
{
|
|
if (RangeData.CellStyles == null)
|
|
RangeData.CellStyles = new CellVisualStyles();
|
|
|
|
return (RangeData.CellStyles);
|
|
}
|
|
|
|
set { RangeData.CellStyles = value; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region FormattedValue
|
|
|
|
///<summary>
|
|
/// 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).
|
|
///</summary>
|
|
public string FormattedValue
|
|
{
|
|
get { return (RangeData.FormattedValue); }
|
|
set { RangeData.FormattedValue = value; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Tag
|
|
|
|
///<summary>
|
|
/// Gets or sets user-defined data associated with the object
|
|
///</summary>
|
|
public object Tag
|
|
{
|
|
get { return (_Tag); }
|
|
set { _Tag = value; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ToolTip
|
|
|
|
///<summary>
|
|
/// Gets or sets the ToolTip text for the cell range.
|
|
///</summary>
|
|
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
|
|
|
|
/// <summary>
|
|
/// Gets or sets the 'effective' visual styles assigned to the range
|
|
/// </summary>
|
|
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
|
|
|
|
///<summary>
|
|
///Invalidates the cached Style
|
|
///definition for all defined StyleTypes
|
|
///</summary>
|
|
public void InvalidateStyle()
|
|
{
|
|
ClearEffectiveStyles();
|
|
}
|
|
|
|
///<summary>
|
|
///Invalidate the cached Style
|
|
///definition for the given StyleType
|
|
///</summary>
|
|
///<param name="type"></param>
|
|
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
|
|
|
|
///<summary>
|
|
///Row/Column display index range
|
|
///</summary>
|
|
public class DisplayRange
|
|
{
|
|
#region Private variables
|
|
|
|
private int _RowStart;
|
|
private int _RowCount;
|
|
|
|
private int _ColumnStart;
|
|
private int _ColumnCount;
|
|
|
|
#endregion
|
|
|
|
#region Public properties
|
|
|
|
#region ColumnCount
|
|
|
|
///<summary>
|
|
///Number of columns
|
|
///</summary>
|
|
public int ColumnCount
|
|
{
|
|
get { return (_ColumnCount); }
|
|
|
|
set
|
|
{
|
|
if (value < 0)
|
|
throw new ArgumentException(@"ColumnCount cannot be negative", "value");
|
|
|
|
_ColumnCount = value;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ColumnEnd
|
|
|
|
///<summary>
|
|
///Ending column display index (exclusive)
|
|
///</summary>
|
|
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
|
|
|
|
///<summary>
|
|
///Starting column display index
|
|
///</summary>
|
|
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
|
|
|
|
///<summary>
|
|
///Number of rows
|
|
///</summary>
|
|
public int RowCount
|
|
{
|
|
get { return (_RowCount); }
|
|
|
|
set
|
|
{
|
|
if (value < 0)
|
|
throw new ArgumentException(@"RowCount cannot be negative", "value");
|
|
|
|
_RowCount = value;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region RowEnd
|
|
|
|
///<summary>
|
|
///Ending row index (exclusive)
|
|
///</summary>
|
|
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
|
|
|
|
///<summary>
|
|
///Starting row index
|
|
///</summary>
|
|
public int RowStart
|
|
{
|
|
get { return (_RowStart); }
|
|
set { _RowStart = value; }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region IsRangeEqualTo
|
|
|
|
///<summary>
|
|
///Returns whether the display range is
|
|
///logically equal to the given item's display range.
|
|
///</summary>
|
|
///<param name="dr"></param>
|
|
///<returns></returns>
|
|
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
|
|
|
|
/// <summary>
|
|
/// ToString
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public override string ToString()
|
|
{
|
|
return ("RowStart = " + RowStart + ", RowEnd = " + RowEnd +
|
|
" ColStart = " + ColumnStart + " ColEnd = " + ColumnEnd);
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
#endregion
|
|
}
|