2014-08-06 01:32:27 +00:00
using System ;
using System.Collections.Generic ;
2014-08-07 14:55:55 +00:00
using System.ComponentModel ;
using System.Drawing ;
2014-08-06 01:32:27 +00:00
using System.Linq ;
using System.Windows.Forms ;
2014-08-07 18:32:09 +00:00
using BizHawk.Client.EmuHawk.CustomControls ;
2014-08-23 14:30:12 +00:00
using System.Collections ;
2014-08-07 18:32:09 +00:00
2014-08-06 01:32:27 +00:00
namespace BizHawk.Client.EmuHawk
{
public class InputRoll : Control
{
2014-08-09 13:13:24 +00:00
private readonly GDIRenderer Gdi ;
2014-08-23 13:14:25 +00:00
private readonly RollColumns _columns = new RollColumns ( ) ;
2014-08-12 11:07:21 +00:00
private readonly List < Cell > SelectedItems = new List < Cell > ( ) ;
2014-08-09 13:13:24 +00:00
2014-08-18 21:38:02 +00:00
private readonly VScrollBar VBar ;
2014-08-15 00:42:03 +00:00
2014-08-18 21:38:02 +00:00
private readonly HScrollBar HBar ;
2014-08-15 00:42:03 +00:00
2014-08-09 13:13:24 +00:00
private int _horizontalOrientedColumnWidth = 0 ;
2014-08-18 21:38:02 +00:00
private int _itemCount = 0 ;
2014-08-09 16:11:25 +00:00
private Size _charSize ;
2014-08-09 13:13:24 +00:00
2014-08-06 01:32:27 +00:00
public InputRoll ( )
{
2014-08-18 21:38:02 +00:00
VBar = new VScrollBar
{
Location = new Point ( Width - 16 , 0 ) ,
Visible = false ,
2014-08-21 21:09:21 +00:00
Anchor = AnchorStyles . Top | AnchorStyles . Right | AnchorStyles . Bottom ,
SmallChange = 1 ,
LargeChange = 5
2014-08-18 21:38:02 +00:00
} ;
HBar = new HScrollBar
{
Location = new Point ( 0 , Height - 16 ) ,
Visible = false ,
2014-08-21 21:09:21 +00:00
Anchor = AnchorStyles . Bottom | AnchorStyles . Left | AnchorStyles . Right ,
SmallChange = 1 ,
LargeChange = 5
2014-08-18 21:38:02 +00:00
} ;
2014-08-23 14:30:12 +00:00
GridLines = true ;
2014-08-07 18:32:09 +00:00
CellPadding = 3 ;
2014-08-10 22:23:14 +00:00
CurrentCell = null ;
Font = new Font ( "Courier New" , 8 ) ; // Only support fixed width
2014-08-06 01:32:27 +00:00
SetStyle ( ControlStyles . AllPaintingInWmPaint , true ) ;
2014-08-10 18:49:17 +00:00
SetStyle ( ControlStyles . UserPaint , true ) ;
2014-08-07 21:52:22 +00:00
SetStyle ( ControlStyles . SupportsTransparentBackColor , true ) ;
2014-08-08 13:36:37 +00:00
SetStyle ( ControlStyles . Opaque , true ) ;
2014-08-08 13:42:05 +00:00
2014-08-10 18:49:17 +00:00
Gdi = new GDIRenderer ( ) ;
using ( var g = CreateGraphics ( ) )
2014-08-10 22:23:14 +00:00
using ( var LCK = Gdi . LockGraphics ( g ) )
{
_charSize = Gdi . MeasureString ( "A" , this . Font ) ;
}
2014-08-18 21:38:02 +00:00
this . Controls . Add ( VBar ) ;
this . Controls . Add ( HBar ) ;
2014-08-19 00:37:38 +00:00
VBar . ValueChanged + = VerticalBar_ValueChanged ;
HBar . ValueChanged + = HorizontalBar_ValueChanged ;
2014-08-18 21:38:02 +00:00
RecalculateScrollBars ( ) ;
2014-08-23 13:14:25 +00:00
_columns . ChangedCallback = ColumnChangedCallback ;
2014-08-06 01:32:27 +00:00
}
2014-08-07 14:55:55 +00:00
2014-08-09 17:15:05 +00:00
protected override void Dispose ( bool disposing )
{
Gdi . Dispose ( ) ;
base . Dispose ( disposing ) ;
}
2014-08-07 14:55:55 +00:00
#region Properties
2014-08-07 18:32:09 +00:00
/// <summary>
/// Gets or sets the amount of padding on the text inside a cell
/// </summary>
[DefaultValue(3)]
2014-08-10 22:23:14 +00:00
[Category("Behavior")]
2014-08-07 18:32:09 +00:00
public int CellPadding { get ; set ; }
2014-08-23 14:30:12 +00:00
// TODO: remove these, it is put here for more convenient replacing of a virtuallistview in tools and minimize the amount of code to refactor, but these properties are useless
2014-08-07 14:55:55 +00:00
public bool VirtualMode { get ; set ; }
2014-08-23 13:14:25 +00:00
public bool BlazingFast { get ; set ; }
2014-08-23 14:30:12 +00:00
public bool SelectAllInProgress { get ; set ; }
public System . Windows . Forms . View View { get ; set ; }
public int selectedItem { get ; set ; }
2014-08-23 13:14:25 +00:00
// ********************************************************
2014-08-07 14:55:55 +00:00
2014-08-23 14:30:12 +00:00
// TODO: implement this
/// <summary>
/// Displays grid lines around cells
/// </summary>
[Category("Appearance")]
[DefaultValue(true)]
public bool GridLines { get ; set ; }
2014-08-07 14:55:55 +00:00
/// <summary>
/// Gets or sets whether the control is horizontal or vertical
/// </summary>
[Category("Behavior")]
public bool HorizontalOrientation { get ; set ; }
/// <summary>
/// Gets or sets the sets the virtual number of items to be displayed.
/// </summary>
[Category("Behavior")]
2014-08-18 21:38:02 +00:00
public int ItemCount
{
get
{
return _itemCount ;
}
set
{
_itemCount = value ;
RecalculateScrollBars ( ) ;
}
}
2014-08-07 14:55:55 +00:00
/// <summary>
/// Gets or sets the sets the columns can be resized
/// </summary>
[Category("Behavior")]
public bool AllowColumnResize { get ; set ; }
/// <summary>
/// Gets or sets the sets the columns can be reordered
/// </summary>
[Category("Behavior")]
public bool AllowColumnReorder { get ; set ; }
2014-08-11 11:11:51 +00:00
/// <summary>
/// Indicates whether the entire row will always be selected
/// </summary>
[Category("Appearance")]
2014-08-14 23:10:56 +00:00
[DefaultValue(false)]
2014-08-11 11:11:51 +00:00
public bool FullRowSelect { get ; set ; }
2014-08-14 23:10:56 +00:00
/// <summary>
/// Allows multiple items to be selected
/// </summary>
[Category("Behavior")]
[DefaultValue(true)]
public bool MultiSelect { get ; set ; }
2014-08-23 13:05:28 +00:00
/// <summary>
/// Gets or sets whether or not the control is in input painting mode
/// </summary>
[Category("Behavior")]
[DefaultValue(false)]
public bool InputPaintingMode { get ; set ; }
2014-08-23 13:19:48 +00:00
/// <summary>
/// The columns shown
/// </summary>
[Category("Behavior")]
public RollColumns Columns { get { return _columns ; } }
2014-08-23 14:30:12 +00:00
public void SelectAll ( )
{
var oldFullRowVal = FullRowSelect ;
FullRowSelect = true ;
for ( int i = 0 ; i < ItemCount ; i + + )
{
SelectItem ( i , true ) ;
}
FullRowSelect = oldFullRowVal ;
}
public void DeselectAll ( )
{
SelectedItems . Clear ( ) ;
}
2014-08-07 14:55:55 +00:00
#endregion
#region Event Handlers
/// <summary>
2014-08-10 22:23:14 +00:00
/// Fire the QueryItemText event which requests the text for the passed Listview cell.
2014-08-07 14:55:55 +00:00
/// </summary>
2014-08-10 22:23:14 +00:00
[Category("Virtual")]
public event QueryItemTextHandler QueryItemText ;
2014-08-07 14:55:55 +00:00
/// <summary>
2014-08-10 22:23:14 +00:00
/// Fire the QueryItemBkColor event which requests the background color for the passed Listview cell
2014-08-07 14:55:55 +00:00
/// </summary>
2014-08-10 22:23:14 +00:00
[Category("Virtual")]
public event QueryItemBkColorHandler QueryItemBkColor ;
2014-08-07 14:55:55 +00:00
/// <summary>
2014-08-10 22:23:14 +00:00
/// Fires when the mouse moves from one cell to another (including column header cells)
2014-08-07 14:55:55 +00:00
/// </summary>
2014-08-10 22:23:14 +00:00
[Category("Mouse")]
public event CellChangeEventHandler PointedCellChanged ;
2014-08-07 14:55:55 +00:00
2014-08-14 23:10:56 +00:00
/// <summary>
/// Occurs when a column header is clicked
/// </summary>
2014-08-11 01:49:45 +00:00
[Category("Action")]
2014-08-23 14:36:55 +00:00
public event System . Windows . Forms . ColumnClickEventHandler ColumnClick ;
2014-08-11 01:49:45 +00:00
2014-08-14 23:10:56 +00:00
/// <summary>
/// Occurs whenever the 'SelectedItems' property for this control changes
/// </summary>
[Category("Behavior")]
2014-08-23 14:36:55 +00:00
public event System . EventHandler SelectedIndexChanged ;
2014-08-14 23:10:56 +00:00
2014-08-23 13:05:28 +00:00
/// <summary>
/// Occurs whenever the mouse wheel is scrolled while the right mouse button is held
/// </summary>
[Category("Behavior")]
public event RightMouseScrollEventHandler RightMouseScrolled ;
2014-08-07 14:55:55 +00:00
/// <summary>
2014-08-10 22:23:14 +00:00
/// Retrieve the text for a cell
2014-08-07 14:55:55 +00:00
/// </summary>
2014-08-10 22:23:14 +00:00
public delegate void QueryItemTextHandler ( int index , int column , out string text ) ;
/// <summary>
/// Retrieve the background color for a cell
/// </summary>
public delegate void QueryItemBkColorHandler ( int index , int column , ref Color color ) ;
public delegate void CellChangeEventHandler ( object sender , CellEventArgs e ) ;
2014-08-07 14:55:55 +00:00
2014-08-23 13:05:28 +00:00
public delegate void RightMouseScrollEventHandler ( object sender , MouseEventArgs e ) ;
2014-08-10 15:57:59 +00:00
public class CellEventArgs
{
public CellEventArgs ( Cell oldCell , Cell newCell )
{
OldCell = oldCell ;
NewCell = newCell ;
}
public Cell OldCell { get ; private set ; }
public Cell NewCell { get ; private set ; }
}
2014-08-07 14:55:55 +00:00
#endregion
2014-08-11 00:24:38 +00:00
#region Api
2014-08-07 14:55:55 +00:00
2014-08-23 14:30:12 +00:00
// TODO: rename this, it is named this for legacy support from VirtualListVIew
public void SelectItem ( int index , bool val )
{
if ( _columns . Any ( ) )
{
if ( val )
{
SelectCell ( new Cell
{
RowIndex = index ,
Column = _columns [ 0 ]
} ) ;
}
else
{
var items = SelectedItems . Where ( i = > i . RowIndex = = index ) ;
SelectedItems . RemoveAll ( x = > items . Contains ( x ) ) ;
}
}
}
2014-08-23 13:50:47 +00:00
[Browsable(false)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
public int? LastSelectedIndex
{
get
{
if ( SelectedIndices . Any ( ) )
{
return SelectedIndices
. OrderBy ( x = > x )
. Last ( ) ;
}
return null ;
}
}
2014-08-11 00:24:38 +00:00
[Browsable(false)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
2014-08-10 15:57:59 +00:00
public Cell CurrentCell { get ; set ; }
2014-08-23 13:05:28 +00:00
[Browsable(false)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
public Cell LastCell { get ; set ; }
[Browsable(false)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
public bool IsPaintDown { get ; set ; }
2014-08-11 00:24:38 +00:00
[Browsable(false)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
public bool UseCustomBackground { get ; set ; }
2014-08-23 13:05:28 +00:00
[Browsable(false)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
public bool RightButtonHeld { get ; set ; }
2014-08-07 14:55:55 +00:00
public string UserSettingsSerialized ( )
{
return string . Empty ; // TODO
}
2014-08-23 13:50:47 +00:00
// TODO: remove
2014-08-08 18:30:57 +00:00
public void AddColumns ( IEnumerable < RollColumn > columns )
{
2014-08-23 13:14:25 +00:00
_columns . AddRange ( columns ) ;
2014-08-08 18:30:57 +00:00
ColumnChanged ( ) ;
}
2014-08-23 13:50:47 +00:00
// TODO: remove
2014-08-08 18:30:57 +00:00
public void AddColumn ( RollColumn column )
{
2014-08-23 13:14:25 +00:00
_columns . Add ( column ) ;
2014-08-08 18:30:57 +00:00
ColumnChanged ( ) ;
}
2014-08-23 13:50:47 +00:00
// TODO: remove
2014-08-11 01:49:45 +00:00
public RollColumn GetColumn ( int index )
{
2014-08-23 13:14:25 +00:00
return _columns [ index ] ;
2014-08-11 01:49:45 +00:00
}
2014-08-23 13:50:47 +00:00
/// <summary>
/// Gets or sets the first visiable row index, if scrolling is needed
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
public int ScrollPosition
{
get
{
if ( HorizontalOrientation )
{
if ( NeedsHScrollbar )
{
return HBar . Value ;
}
}
if ( NeedsVScrollbar )
{
return VBar . Value ;
}
return 0 ;
}
set
{
if ( HorizontalOrientation )
{
if ( NeedsHScrollbar )
{
HBar . Value = value ;
}
}
if ( NeedsVScrollbar )
{
VBar . Value = value ;
}
}
}
/// <summary>
/// Returns the number of rows currently visible
/// </summary>
[Browsable(false)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
public int VisibleRows
{
get
{
if ( HorizontalOrientation )
{
return ( Width - _horizontalOrientedColumnWidth ) / CellWidth ;
}
return ( Height / CellHeight ) - 1 ;
}
}
2014-08-23 14:30:12 +00:00
// TODO: make IEnumerable, IList is for legacy support
2014-08-12 11:07:21 +00:00
[Browsable(false)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
2014-08-23 14:30:12 +00:00
public IList < int > SelectedIndices
2014-08-12 11:07:21 +00:00
{
get
{
return SelectedItems
. Where ( cell = > cell . RowIndex . HasValue )
2014-08-14 23:10:56 +00:00
. Select ( cell = > cell . RowIndex . Value )
2014-08-23 14:30:12 +00:00
. Distinct ( )
. ToList ( ) ;
2014-08-12 11:07:21 +00:00
}
}
2014-08-07 14:55:55 +00:00
#endregion
#region Paint
2014-08-10 22:23:14 +00:00
protected override void OnPaint ( PaintEventArgs e )
2014-08-07 18:32:09 +00:00
{
2014-08-18 21:38:02 +00:00
VBar . Location = new Point ( Width - 16 , 0 ) ;
2014-08-10 22:23:14 +00:00
using ( var LCK = Gdi . LockGraphics ( e . Graphics ) )
2014-08-07 18:32:09 +00:00
{
2014-08-18 00:23:09 +00:00
Gdi . StartOffScreenBitmap ( Width , Height ) ;
2014-08-10 22:23:14 +00:00
// Header
2014-08-23 13:14:25 +00:00
if ( _columns . Any ( ) )
2014-08-09 16:11:25 +00:00
{
2014-08-10 22:23:14 +00:00
DrawColumnBg ( e ) ;
DrawColumnText ( e ) ;
2014-08-09 16:11:25 +00:00
}
2014-08-07 18:32:09 +00:00
2014-08-10 22:23:14 +00:00
// Background
DrawBg ( e ) ;
2014-08-07 18:32:09 +00:00
2014-08-10 22:23:14 +00:00
// ForeGround
DrawData ( e ) ;
2014-08-18 00:23:09 +00:00
Gdi . CopyToScreen ( ) ;
Gdi . EndOffScreenBitmap ( ) ;
2014-08-07 18:32:09 +00:00
}
}
2014-08-07 14:55:55 +00:00
protected override void OnPaintBackground ( PaintEventArgs pevent )
{
2014-08-08 13:42:05 +00:00
// Do nothing, and this should never be called
2014-08-07 14:55:55 +00:00
}
2014-08-10 22:23:14 +00:00
private void DrawColumnText ( PaintEventArgs e )
2014-08-08 02:09:59 +00:00
{
if ( HorizontalOrientation )
{
int start = 0 ;
2014-08-10 22:23:14 +00:00
Gdi . PrepDrawString ( this . Font , this . ForeColor ) ;
2014-08-23 13:14:25 +00:00
foreach ( var column in _columns )
2014-08-08 02:09:59 +00:00
{
2014-08-09 16:50:38 +00:00
var point = new Point ( CellPadding , start + CellPadding ) ;
2014-08-11 01:23:53 +00:00
if ( IsHoveringOnColumnCell & & column = = CurrentCell . Column )
{
Gdi . PrepDrawString ( this . Font , SystemColors . HighlightText ) ;
Gdi . DrawString ( column . Text , point ) ;
Gdi . PrepDrawString ( this . Font , this . ForeColor ) ;
}
else
{
Gdi . DrawString ( column . Text , point ) ;
}
2014-08-08 02:09:59 +00:00
start + = CellHeight ;
}
}
else
{
2014-08-09 13:13:24 +00:00
int start = CellPadding ;
2014-08-10 22:23:14 +00:00
Gdi . PrepDrawString ( this . Font , this . ForeColor ) ;
2014-08-23 13:14:25 +00:00
foreach ( var column in _columns )
2014-08-08 02:09:59 +00:00
{
2014-08-09 13:13:24 +00:00
var point = new Point ( start + CellPadding , CellPadding ) ;
2014-08-11 01:23:53 +00:00
if ( IsHoveringOnColumnCell & & column = = CurrentCell . Column )
{
Gdi . PrepDrawString ( this . Font , SystemColors . HighlightText ) ;
Gdi . DrawString ( column . Text , point ) ;
Gdi . PrepDrawString ( this . Font , this . ForeColor ) ;
}
else
{
Gdi . DrawString ( column . Text , point ) ;
}
2014-08-09 16:11:25 +00:00
start + = CalcWidth ( column ) ;
2014-08-08 02:09:59 +00:00
}
}
}
2014-08-10 22:23:14 +00:00
private void DrawData ( PaintEventArgs e )
2014-08-09 17:15:05 +00:00
{
2014-08-09 21:27:05 +00:00
if ( QueryItemText ! = null )
{
if ( HorizontalOrientation )
{
2014-08-23 12:30:21 +00:00
int startIndex = NeedsHScrollbar ? HBar . Value : 0 ;
int endIndex = startIndex + ( Width / CellWidth ) ;
if ( endIndex > = ItemCount )
2014-08-19 00:37:38 +00:00
{
2014-08-23 12:30:21 +00:00
endIndex = ItemCount ;
2014-08-19 00:37:38 +00:00
}
2014-08-23 12:30:21 +00:00
int range = endIndex - startIndex ;
2014-08-10 22:23:14 +00:00
Gdi . PrepDrawString ( this . Font , this . ForeColor ) ;
2014-08-23 12:30:21 +00:00
for ( int i = 0 ; i < range ; i + + )
2014-08-10 13:21:26 +00:00
{
2014-08-23 13:14:25 +00:00
for ( int j = 0 ; j < _columns . Count ; j + + )
2014-08-10 13:21:26 +00:00
{
string text ;
int x = _horizontalOrientedColumnWidth + CellPadding + ( CellWidth * i ) ;
int y = j * CellHeight ;
var point = new Point ( x , y ) ;
2014-08-23 12:30:21 +00:00
QueryItemText ( i + startIndex , j , out text ) ;
2014-08-10 22:23:14 +00:00
Gdi . DrawString ( text , point ) ;
2014-08-10 13:21:26 +00:00
}
}
2014-08-09 21:27:05 +00:00
}
else
{
2014-08-23 12:30:21 +00:00
int startIndex = NeedsVScrollbar ? VBar . Value : 0 ;
2014-08-22 00:39:56 +00:00
int endIndex = startIndex + ( Height / CellHeight ) ;
if ( endIndex > = ItemCount )
2014-08-19 00:37:38 +00:00
{
2014-08-22 00:39:56 +00:00
endIndex = ItemCount ;
2014-08-19 00:37:38 +00:00
}
2014-08-22 00:39:56 +00:00
int range = endIndex - startIndex ;
2014-08-10 22:23:14 +00:00
Gdi . PrepDrawString ( this . Font , this . ForeColor ) ;
2014-08-22 00:39:56 +00:00
for ( int i = 0 ; i < range ; i + + )
2014-08-09 21:27:05 +00:00
{
int x = 1 ;
2014-08-23 13:14:25 +00:00
for ( int j = 0 ; j < _columns . Count ; j + + )
2014-08-09 21:27:05 +00:00
{
string text ;
2014-08-22 00:39:56 +00:00
var point = new Point ( x + CellPadding , ( i + 1 ) * CellHeight ) ; // +1 accounts for the column header
QueryItemText ( i + startIndex , j , out text ) ;
2014-08-10 22:23:14 +00:00
Gdi . DrawString ( text , point ) ;
2014-08-23 13:14:25 +00:00
x + = CalcWidth ( _columns [ j ] ) ;
2014-08-09 21:27:05 +00:00
}
}
}
}
2014-08-09 17:15:05 +00:00
}
2014-08-08 13:42:05 +00:00
2014-08-10 22:23:14 +00:00
private void DrawColumnBg ( PaintEventArgs e )
2014-08-07 14:55:55 +00:00
{
2014-08-10 22:23:14 +00:00
Gdi . SetBrush ( SystemColors . ControlLight ) ;
Gdi . SetSolidPen ( Color . Black ) ;
if ( HorizontalOrientation )
2014-08-08 02:09:59 +00:00
{
2014-08-11 00:08:16 +00:00
Gdi . DrawRectangle ( 0 , 0 , _horizontalOrientedColumnWidth + 1 , Height ) ;
Gdi . FillRectangle ( 1 , 1 , _horizontalOrientedColumnWidth , Height - 3 ) ;
2014-08-10 22:23:14 +00:00
int start = 0 ;
2014-08-23 13:14:25 +00:00
foreach ( var column in _columns )
2014-08-10 22:23:14 +00:00
{
start + = CellHeight ;
2014-08-11 00:08:16 +00:00
Gdi . Line ( 1 , start , _horizontalOrientedColumnWidth , start ) ;
2014-08-10 22:23:14 +00:00
}
}
else
{
Gdi . DrawRectangle ( 0 , 0 , Width , CellHeight ) ;
2014-08-11 00:08:16 +00:00
Gdi . FillRectangle ( 1 , 1 , Width - 2 , CellHeight ) ;
2014-08-10 22:23:14 +00:00
int start = 0 ;
2014-08-23 13:14:25 +00:00
foreach ( var column in _columns )
2014-08-10 18:49:17 +00:00
{
2014-08-10 22:23:14 +00:00
start + = CalcWidth ( column ) ;
Gdi . Line ( start , 0 , start , CellHeight ) ;
2014-08-10 18:49:17 +00:00
}
2014-08-10 22:23:14 +00:00
}
2014-08-11 01:23:53 +00:00
// If the user is hovering over a column
if ( IsHoveringOnColumnCell )
{
if ( HorizontalOrientation )
{
2014-08-23 13:14:25 +00:00
for ( int i = 0 ; i < _columns . Count ; i + + )
2014-08-11 01:23:53 +00:00
{
2014-08-23 13:14:25 +00:00
if ( _columns [ i ] = = CurrentCell . Column )
2014-08-11 01:23:53 +00:00
{
Gdi . SetBrush ( SystemColors . Highlight ) ;
Gdi . FillRectangle (
1 ,
( i * CellHeight ) + 1 ,
_horizontalOrientedColumnWidth - 1 ,
CellHeight - 1 ) ;
}
}
}
else
{
int start = 0 ;
2014-08-23 13:14:25 +00:00
for ( int i = 0 ; i < _columns . Count ; i + + )
2014-08-11 01:23:53 +00:00
{
2014-08-23 13:14:25 +00:00
var width = CalcWidth ( _columns [ i ] ) ;
if ( _columns [ i ] = = CurrentCell . Column )
2014-08-11 01:23:53 +00:00
{
Gdi . SetBrush ( SystemColors . Highlight ) ;
Gdi . FillRectangle ( start + 1 , 1 , width - 1 , CellHeight - 1 ) ;
}
start + = width ;
}
}
}
2014-08-10 22:23:14 +00:00
}
2014-08-08 02:09:59 +00:00
2014-08-10 22:23:14 +00:00
private void DrawBg ( PaintEventArgs e )
{
var startPoint = StartBg ( ) ;
2014-08-08 13:42:05 +00:00
2014-08-10 22:23:14 +00:00
Gdi . SetBrush ( Color . White ) ;
Gdi . SetSolidPen ( Color . Black ) ;
Gdi . DrawRectangle ( startPoint . X , startPoint . Y , Width , Height ) ;
Gdi . SetSolidPen ( SystemColors . ControlLight ) ;
if ( HorizontalOrientation )
{
// Columns
for ( int i = 1 ; i < Width / CellWidth ; i + + )
{
2014-08-11 00:08:16 +00:00
var x = _horizontalOrientedColumnWidth + 1 + ( i * CellWidth ) ;
2014-08-23 13:14:25 +00:00
var y2 = ( _columns . Count * CellHeight ) - 1 ;
2014-08-19 00:37:38 +00:00
if ( y2 > Height )
{
y2 = Height - 2 ;
}
Gdi . Line ( x , 1 , x , y2 ) ;
2014-08-10 22:23:14 +00:00
}
// Rows
2014-08-23 13:14:25 +00:00
for ( int i = 1 ; i < _columns . Count + 1 ; i + + )
2014-08-10 22:23:14 +00:00
{
2014-08-11 00:08:16 +00:00
Gdi . Line ( _horizontalOrientedColumnWidth + 1 , i * CellHeight , Width - 2 , i * CellHeight ) ;
2014-08-10 22:23:14 +00:00
}
}
else
{
// Columns
int x = 0 ;
2014-08-11 00:08:16 +00:00
int y = CellHeight + 1 ;
2014-08-23 13:14:25 +00:00
foreach ( var column in _columns )
2014-08-10 22:23:14 +00:00
{
x + = CalcWidth ( column ) ;
Gdi . Line ( x , y , x , Height - 1 ) ;
}
// Rows
2014-08-19 00:37:38 +00:00
for ( int i = 2 ; i < ( Height / CellHeight ) + 1 ; i + + )
2014-08-10 22:23:14 +00:00
{
Gdi . Line ( 1 , ( i * CellHeight ) + 1 , Width - 2 , ( i * CellHeight ) + 1 ) ;
}
2014-08-10 18:49:17 +00:00
}
2014-08-11 00:08:16 +00:00
2014-08-11 00:24:38 +00:00
if ( QueryItemBkColor ! = null & & UseCustomBackground )
2014-08-11 00:08:16 +00:00
{
2014-08-14 22:48:59 +00:00
DoBackGroundCallback ( e ) ;
}
if ( SelectedItems . Any ( ) )
{
DoSelectionBG ( e ) ;
}
}
private void DoSelectionBG ( PaintEventArgs e )
{
foreach ( var cell in SelectedItems )
{
DrawCellBG ( SystemColors . Highlight , cell ) ;
}
}
private void DrawCellBG ( Color color , Cell cell )
{
int x = 0 ,
y = 0 ,
w = 0 ,
h = 0 ;
if ( HorizontalOrientation )
{
x = ( cell . RowIndex . Value * CellWidth ) + 2 + _horizontalOrientedColumnWidth ;
w = CellWidth - 1 ;
2014-08-23 13:14:25 +00:00
y = ( CellHeight * _columns . IndexOf ( cell . Column ) ) + 1 ; // We can't draw without row and column, so assume they exist and fail catastrophically if they don't
2014-08-14 22:48:59 +00:00
h = CellHeight - 1 ;
}
else
{
2014-08-23 13:14:25 +00:00
foreach ( var column in _columns )
2014-08-11 00:08:16 +00:00
{
2014-08-14 22:48:59 +00:00
if ( cell . Column = = column )
2014-08-11 00:08:16 +00:00
{
2014-08-14 22:48:59 +00:00
w = CalcWidth ( column ) - 1 ;
break ;
}
else
{
x + = CalcWidth ( column ) ;
}
}
x + = 1 ;
y = ( CellHeight * ( cell . RowIndex . Value + 1 ) ) + 2 ; // We can't draw without row and column, so assume they exist and fail catastrophically if they don't
h = CellHeight - 1 ;
}
Gdi . SetBrush ( color ) ;
Gdi . FillRectangle ( x , y , w , h ) ;
}
private void DoBackGroundCallback ( PaintEventArgs e )
{
if ( HorizontalOrientation )
{
2014-08-23 13:50:47 +00:00
for ( int i = 0 ; i < VisibleRows ; i + + )
2014-08-14 22:48:59 +00:00
{
2014-08-23 13:14:25 +00:00
for ( int j = 0 ; j < _columns . Count ; j + + )
2014-08-14 22:48:59 +00:00
{
Color color = Color . White ;
QueryItemBkColor ( i , j , ref color ) ;
// TODO: refactor to use DrawCellBG
if ( color ! = Color . White ) // An easy optimization, don't draw unless the user specified something other than the default
2014-08-11 00:08:16 +00:00
{
2014-08-14 22:48:59 +00:00
Gdi . SetBrush ( color ) ;
Gdi . FillRectangle (
_horizontalOrientedColumnWidth + ( i * CellWidth ) + 2 ,
( j * CellHeight ) + 1 ,
CellWidth - 1 ,
CellHeight - 1 ) ;
2014-08-11 00:08:16 +00:00
}
}
}
2014-08-14 22:48:59 +00:00
}
else
{
2014-08-23 13:50:47 +00:00
for ( int i = 1 ; i < VisibleRows ; i + + )
2014-08-11 00:08:16 +00:00
{
2014-08-14 22:48:59 +00:00
int x = 1 ;
2014-08-23 13:14:25 +00:00
for ( int j = 0 ; j < _columns . Count ; j + + )
2014-08-11 00:08:16 +00:00
{
2014-08-14 22:48:59 +00:00
Color color = Color . White ;
QueryItemBkColor ( i , j , ref color ) ;
2014-08-11 00:08:16 +00:00
2014-08-23 13:14:25 +00:00
var width = CalcWidth ( _columns [ j ] ) ;
2014-08-14 22:48:59 +00:00
if ( color ! = Color . White ) // An easy optimization, don't draw unless the user specified something other than the default
{
Gdi . SetBrush ( color ) ;
Gdi . FillRectangle ( x , ( i * CellHeight ) + 2 , width - 1 , CellHeight - 1 ) ;
2014-08-11 00:08:16 +00:00
}
2014-08-14 22:48:59 +00:00
x + = width ;
2014-08-11 00:08:16 +00:00
}
}
}
2014-08-07 14:55:55 +00:00
}
#endregion
#region Mouse and Key Events
protected override void OnKeyDown ( KeyEventArgs e )
{
if ( e . Control & & ! e . Alt & & ! e . Shift & & e . KeyCode = = Keys . R ) // Ctrl + R
{
HorizontalOrientation ^ = true ;
2014-08-10 14:25:59 +00:00
Refresh ( ) ;
2014-08-07 14:55:55 +00:00
}
base . OnKeyDown ( e ) ;
}
2014-08-10 22:23:14 +00:00
protected override void OnMouseMove ( MouseEventArgs e )
{
CalculatePointedCell ( e . X , e . Y ) ;
base . OnMouseMove ( e ) ;
}
protected override void OnMouseEnter ( EventArgs e )
{
CurrentCell = new Cell
{
Column = null ,
RowIndex = null
} ;
base . OnMouseEnter ( e ) ;
}
protected override void OnMouseLeave ( EventArgs e )
{
CurrentCell = null ;
2014-08-23 13:05:28 +00:00
IsPaintDown = false ;
2014-08-11 01:23:53 +00:00
Refresh ( ) ;
2014-08-10 22:23:14 +00:00
base . OnMouseLeave ( e ) ;
}
2014-08-11 01:49:45 +00:00
protected override void OnMouseClick ( MouseEventArgs e )
{
if ( IsHoveringOnColumnCell )
{
ColumnClickEvent ( ColumnAtX ( e . X ) ) ;
}
2014-08-12 11:07:21 +00:00
else if ( IsHoveringOnDataCell )
{
2014-08-14 23:10:56 +00:00
if ( ModifierKeys = = Keys . Alt )
2014-08-14 22:48:59 +00:00
{
MessageBox . Show ( "Alt click logic is not yet implemented" ) ;
}
2014-08-14 23:10:56 +00:00
else if ( ModifierKeys = = Keys . Shift )
2014-08-12 11:07:21 +00:00
{
2014-08-14 22:48:59 +00:00
if ( SelectedItems . Any ( ) )
{
MessageBox . Show ( "Shift click logic is not yet implemented" ) ;
}
else
{
2014-08-14 23:10:56 +00:00
SelectCell ( CurrentCell ) ;
2014-08-14 22:48:59 +00:00
}
}
2014-08-14 23:10:56 +00:00
else if ( ModifierKeys = = Keys . Control )
2014-08-14 22:48:59 +00:00
{
2014-08-14 23:10:56 +00:00
SelectCell ( CurrentCell ) ;
2014-08-12 11:07:21 +00:00
}
else
{
2014-08-14 22:48:59 +00:00
SelectedItems . Clear ( ) ;
2014-08-14 23:10:56 +00:00
SelectCell ( CurrentCell ) ;
2014-08-12 11:07:21 +00:00
}
Refresh ( ) ;
}
2014-08-11 01:49:45 +00:00
base . OnMouseClick ( e ) ;
}
2014-08-23 13:05:28 +00:00
protected override void OnMouseDown ( MouseEventArgs e )
{
if ( e . Button = = MouseButtons . Left & & InputPaintingMode )
{
IsPaintDown = true ;
}
if ( e . Button = = MouseButtons . Right )
{
RightButtonHeld = true ;
}
base . OnMouseDown ( e ) ;
}
protected override void OnMouseUp ( MouseEventArgs e )
{
IsPaintDown = false ;
RightButtonHeld = false ;
base . OnMouseUp ( e ) ;
}
protected override void OnMouseWheel ( MouseEventArgs e )
{
if ( RightButtonHeld )
{
DoRightMouseScroll ( this , e ) ;
}
else
{
base . OnMouseWheel ( e ) ;
}
}
2014-08-10 22:23:14 +00:00
#endregion
2014-08-18 21:38:02 +00:00
#region Change Events
protected override void OnResize ( EventArgs e )
{
RecalculateScrollBars ( ) ;
base . OnResize ( e ) ;
Refresh ( ) ;
}
#endregion
2014-08-10 22:23:14 +00:00
#region Helpers
2014-08-23 13:05:28 +00:00
private void DoRightMouseScroll ( object sender , MouseEventArgs e )
{
if ( RightMouseScrolled ! = null )
{
RightMouseScrolled ( sender , e ) ;
}
}
2014-08-19 00:37:38 +00:00
private void VerticalBar_ValueChanged ( object sender , EventArgs e )
{
Refresh ( ) ;
}
private void HorizontalBar_ValueChanged ( object sender , EventArgs e )
{
Refresh ( ) ;
}
2014-08-18 23:50:50 +00:00
private void ColumnChangedCallback ( )
{
RecalculateScrollBars ( ) ;
}
2014-08-18 21:38:02 +00:00
private void RecalculateScrollBars ( )
{
if ( NeedsVScrollbar )
{
2014-08-21 21:09:21 +00:00
int max ;
2014-08-18 21:38:02 +00:00
if ( HorizontalOrientation )
{
2014-08-23 13:14:25 +00:00
max = ( ( ( _columns . Count * CellHeight ) - Height ) / CellHeight ) + 1 ;
2014-08-18 21:38:02 +00:00
}
else
{
2014-08-21 21:09:21 +00:00
max = ( ( ( ItemCount * CellHeight ) - Height ) / CellHeight ) + 1 ;
2014-08-18 21:38:02 +00:00
}
2014-08-21 21:09:21 +00:00
if ( VBar . Value > max )
{
VBar . Value = max ;
}
VBar . Maximum = max + VBar . LargeChange ; // TODO: why can't it be 1?
VBar . Size = new Size ( VBar . Width , Height ) ;
VBar . Visible = true ;
2014-08-18 21:38:02 +00:00
}
else
{
VBar . Visible = false ;
}
if ( NeedsHScrollbar )
{
HBar . Visible = true ;
if ( HorizontalOrientation )
{
2014-08-23 13:14:25 +00:00
HBar . Maximum = ( _columns . Sum ( c = > CalcWidth ( c ) ) - Width ) / CellWidth ;
2014-08-18 21:38:02 +00:00
}
else
{
2014-08-19 00:37:38 +00:00
HBar . Maximum = ( ( ItemCount * CellWidth ) - Width ) / CellWidth ;
2014-08-18 21:38:02 +00:00
}
}
else
{
HBar . Visible = false ;
}
}
2014-08-14 23:10:56 +00:00
private void SelectCell ( Cell cell )
{
if ( ! MultiSelect )
{
SelectedItems . Clear ( ) ;
}
if ( FullRowSelect )
{
2014-08-23 13:14:25 +00:00
foreach ( var column in _columns )
2014-08-14 23:10:56 +00:00
{
SelectedItems . Add ( new Cell
{
RowIndex = cell . RowIndex ,
Column = column
} ) ;
}
}
else
{
SelectedItems . Add ( CurrentCell ) ;
}
SelectedIndexChanged ( this , new EventArgs ( ) ) ;
}
2014-08-11 01:23:53 +00:00
private bool IsHoveringOnColumnCell
{
get
{
return CurrentCell ! = null & &
CurrentCell . Column ! = null & &
! CurrentCell . RowIndex . HasValue ;
}
}
2014-08-12 11:07:21 +00:00
private bool IsHoveringOnDataCell
{
get
{
return CurrentCell ! = null & &
CurrentCell . Column ! = null & &
CurrentCell . RowIndex . HasValue ;
}
}
2014-08-10 15:57:59 +00:00
private void CalculatePointedCell ( int x , int y )
{
2014-08-11 01:23:53 +00:00
bool wasHoveringColumnCell = IsHoveringOnColumnCell ;
2014-08-10 15:57:59 +00:00
var newCell = new Cell ( ) ;
// If pointing to a column header
2014-08-23 13:14:25 +00:00
if ( _columns . Any ( ) )
2014-08-10 15:57:59 +00:00
{
if ( HorizontalOrientation )
{
if ( x < _horizontalOrientedColumnWidth )
{
newCell . RowIndex = null ;
}
else
{
newCell . RowIndex = ( x - _horizontalOrientedColumnWidth ) / CellWidth ;
}
int colIndex = ( y / CellHeight ) ;
2014-08-23 13:14:25 +00:00
if ( colIndex > = 0 & & colIndex < _columns . Count )
2014-08-10 15:57:59 +00:00
{
2014-08-23 13:14:25 +00:00
newCell . Column = _columns [ colIndex ] ;
2014-08-10 15:57:59 +00:00
}
}
else
{
if ( y < CellHeight )
{
newCell . RowIndex = null ;
}
else
{
newCell . RowIndex = ( y / CellHeight ) - 1 ;
}
int start = 0 ;
//for (int i = 0; i < Columns.Count; i++)
2014-08-23 13:14:25 +00:00
foreach ( var column in _columns )
2014-08-10 15:57:59 +00:00
{
if ( x > start )
{
start + = CalcWidth ( column ) ;
if ( x < = start )
{
newCell . Column = column ;
break ;
}
}
}
}
}
2014-08-10 22:23:14 +00:00
if ( ! newCell . Equals ( CurrentCell ) )
2014-08-10 15:57:59 +00:00
{
CellChanged ( CurrentCell , newCell ) ;
2014-08-23 13:05:28 +00:00
LastCell = CurrentCell ;
2014-08-10 15:57:59 +00:00
CurrentCell = newCell ;
2014-08-11 01:23:53 +00:00
if ( IsHoveringOnColumnCell | |
( wasHoveringColumnCell & & ! IsHoveringOnColumnCell ) )
{
Refresh ( ) ;
}
2014-08-10 15:57:59 +00:00
}
}
private void CellChanged ( Cell oldCell , Cell newCell )
{
if ( PointedCellChanged ! = null )
{
PointedCellChanged ( this , new CellEventArgs ( oldCell , newCell ) ) ;
}
}
2014-08-11 01:49:45 +00:00
private void ColumnClickEvent ( RollColumn column )
{
if ( ColumnClick ! = null )
{
2014-08-23 13:14:25 +00:00
ColumnClick ( this , new ColumnClickEventArgs ( _columns . IndexOf ( column ) ) ) ;
2014-08-11 01:49:45 +00:00
}
}
2014-08-07 14:55:55 +00:00
private bool NeedToUpdateScrollbar ( )
{
return true ;
}
2014-08-10 22:23:14 +00:00
// TODO: Calculate this on Orientation change instead of call it every time
2014-08-09 13:13:24 +00:00
private Point StartBg ( )
2014-08-07 18:32:09 +00:00
{
2014-08-23 13:14:25 +00:00
if ( _columns . Any ( ) )
2014-08-07 18:32:09 +00:00
{
2014-08-09 13:13:24 +00:00
if ( HorizontalOrientation )
2014-08-07 18:32:09 +00:00
{
2014-08-11 00:08:16 +00:00
var x = _horizontalOrientedColumnWidth ;
2014-08-09 13:13:24 +00:00
var y = 0 ;
return new Point ( x , y ) ;
}
else
{
2014-08-11 00:08:16 +00:00
var y = CellHeight ;
2014-08-10 22:23:14 +00:00
return new Point ( 0 , y ) ;
2014-08-07 18:32:09 +00:00
}
}
2014-08-09 13:13:24 +00:00
return new Point ( 0 , 0 ) ;
2014-08-07 23:10:41 +00:00
}
2014-08-10 22:23:14 +00:00
// TODO: calculate this on Cell Padding change instead of calculate it every time
2014-08-08 02:09:59 +00:00
private int CellHeight
2014-08-07 14:55:55 +00:00
{
get
{
2014-08-09 16:11:25 +00:00
return _charSize . Height + ( CellPadding * 2 ) ;
2014-08-07 14:55:55 +00:00
}
}
2014-08-10 22:23:14 +00:00
// TODO: calculate this on Cell Padding change instead of calculate it every time
2014-08-09 16:11:25 +00:00
private int CellWidth
2014-08-07 14:55:55 +00:00
{
get
{
2014-08-09 16:11:25 +00:00
return _charSize . Width + ( CellPadding * 4 ) ; // Double the padding for horizontal because it looks better
2014-08-07 14:55:55 +00:00
}
}
2014-08-15 00:42:03 +00:00
private bool NeedsVScrollbar
{
get
{
if ( HorizontalOrientation )
{
2014-08-23 13:14:25 +00:00
return _columns . Count > Height / CellHeight ;
2014-08-15 00:42:03 +00:00
}
return ItemCount > Height / CellHeight ;
}
}
private bool NeedsHScrollbar
2014-08-07 14:55:55 +00:00
{
get
{
if ( HorizontalOrientation )
{
2014-08-15 00:42:03 +00:00
return ItemCount > ( Width - _horizontalOrientedColumnWidth ) / CellWidth ;
2014-08-07 14:55:55 +00:00
}
2014-08-23 13:14:25 +00:00
return _columns . Sum ( column = > CalcWidth ( column ) ) > Width ;
2014-08-07 14:55:55 +00:00
}
}
2014-08-08 18:30:57 +00:00
private void ColumnChanged ( )
{
2014-08-23 13:14:25 +00:00
var text = _columns . Max ( c = > c . Text . Length ) ;
2014-08-09 16:11:25 +00:00
_horizontalOrientedColumnWidth = ( text * _charSize . Width ) + ( CellPadding * 2 ) ;
}
2014-08-10 22:23:14 +00:00
// On Column Change calculate this for every column
2014-08-09 16:11:25 +00:00
private int CalcWidth ( RollColumn col )
{
return col . Width ? ? ( ( col . Text . Length * _charSize . Width ) + ( CellPadding * 4 ) ) ;
2014-08-08 18:30:57 +00:00
}
2014-08-11 01:49:45 +00:00
private RollColumn ColumnAtX ( int x )
{
int start = 0 ;
2014-08-23 13:14:25 +00:00
foreach ( var column in _columns )
2014-08-11 01:49:45 +00:00
{
start + = CalcWidth ( column ) ;
if ( start > x )
{
return column ;
}
}
return null ;
}
2014-08-07 14:55:55 +00:00
#endregion
2014-08-11 00:08:16 +00:00
#region Classes
public class RollColumns : List < RollColumn >
2014-08-07 14:55:55 +00:00
{
2014-08-23 14:30:12 +00:00
// For legacy support
public void Add ( ColumnHeader column )
{
Add ( new RollColumn
{
Group = "" ,
Width = column . Width ,
Name = column . Name ,
Text = column . Text ,
Type = RollColumn . InputType . Text ,
} ) ;
}
// For legacy support
public void AddRange ( ColumnHeader [ ] columns )
{
foreach ( var column in columns )
{
Add ( column ) ; // TODO: this fires the change event each time, convert to an AddRange Call
}
}
2014-08-23 13:19:48 +00:00
public RollColumn this [ string name ]
{
get
{
return this . SingleOrDefault ( column = > column . Name = = name ) ;
}
}
2014-08-18 23:50:50 +00:00
public Action ChangedCallback { get ; set ; }
private void DoChangeCallback ( )
2014-08-07 14:55:55 +00:00
{
2014-08-18 23:50:50 +00:00
if ( ChangedCallback ! = null )
2014-08-11 00:08:16 +00:00
{
2014-08-18 23:50:50 +00:00
ChangedCallback ( ) ;
}
}
public new void Add ( RollColumn column )
{
if ( this . Any ( c = > c . Name = = column . Name ) )
{
throw new InvalidOperationException ( "A column with this name already exists." ) ;
}
base . Add ( column ) ;
ChangedCallback ( ) ;
}
public new void AddRange ( IEnumerable < RollColumn > collection )
{
foreach ( var column in collection )
{
if ( this . Any ( c = > c . Name = = column . Name ) )
{
throw new InvalidOperationException ( "A column with this name already exists." ) ;
}
}
base . AddRange ( collection ) ;
ChangedCallback ( ) ;
}
public new void Insert ( int index , RollColumn column )
{
if ( this . Any ( c = > c . Name = = column . Name ) )
{
throw new InvalidOperationException ( "A column with this name already exists." ) ;
}
base . Insert ( index , column ) ;
ChangedCallback ( ) ;
}
public new void InsertRange ( int index , IEnumerable < RollColumn > collection )
{
foreach ( var column in collection )
{
if ( this . Any ( c = > c . Name = = column . Name ) )
{
throw new InvalidOperationException ( "A column with this name already exists." ) ;
}
}
base . InsertRange ( index , collection ) ;
ChangedCallback ( ) ;
}
public new bool Remove ( RollColumn column )
{
var result = base . Remove ( column ) ;
ChangedCallback ( ) ;
return result ;
}
public new int RemoveAll ( Predicate < RollColumn > match )
{
var result = base . RemoveAll ( match ) ;
ChangedCallback ( ) ;
return result ;
}
public new void RemoveAt ( int index )
{
base . RemoveAt ( index ) ;
ChangedCallback ( ) ;
}
public new void RemoveRange ( int index , int count )
{
base . RemoveRange ( index , count ) ;
ChangedCallback ( ) ;
}
public new void Clear ( )
{
base . Clear ( ) ;
ChangedCallback ( ) ;
2014-08-11 00:08:16 +00:00
}
2014-08-09 16:11:25 +00:00
2014-08-11 00:08:16 +00:00
public IEnumerable < string > Groups
2014-08-09 16:11:25 +00:00
{
2014-08-11 00:08:16 +00:00
get
{
return this
. Select ( x = > x . Group )
. Distinct ( ) ;
}
2014-08-09 16:11:25 +00:00
}
}
2014-08-07 14:55:55 +00:00
2014-08-11 00:08:16 +00:00
public class RollColumn
{
public enum InputType { Boolean , Float , Text , Image }
2014-08-07 18:32:09 +00:00
2014-08-11 00:08:16 +00:00
public string Group { get ; set ; }
public int? Width { get ; set ; }
public string Name { get ; set ; }
public string Text { get ; set ; }
public InputType Type { get ; set ; }
2014-08-23 13:50:47 +00:00
public static bool operator = = ( RollColumn column , string name )
{
return column . Name = = name ;
}
public static bool operator ! = ( RollColumn column , string name )
{
return column . Name ! = name ;
}
public override int GetHashCode ( )
{
return Name . GetHashCode ( ) ;
}
public override bool Equals ( object obj )
{
if ( obj is string )
{
return Name = = ( string ) obj ;
}
return base . Equals ( obj ) ;
}
2014-08-11 00:08:16 +00:00
}
2014-08-10 15:57:59 +00:00
2014-08-11 00:08:16 +00:00
public class Cell
{
public RollColumn Column { get ; set ; }
public int? RowIndex { get ; set ; }
2014-08-10 15:57:59 +00:00
2014-08-11 00:08:16 +00:00
public Cell ( ) { }
2014-08-10 15:57:59 +00:00
2014-08-11 00:08:16 +00:00
public Cell ( Cell cell )
{
Column = cell . Column ;
RowIndex = cell . RowIndex ;
}
2014-08-10 15:57:59 +00:00
2014-08-11 00:08:16 +00:00
public override bool Equals ( object obj )
2014-08-10 15:57:59 +00:00
{
2014-08-11 00:08:16 +00:00
if ( obj is Cell )
{
var cell = obj as Cell ;
return this . Column = = cell . Column & & this . RowIndex = = cell . RowIndex ;
}
return base . Equals ( obj ) ;
2014-08-10 15:57:59 +00:00
}
2014-08-11 00:08:16 +00:00
public override int GetHashCode ( )
{
return Column . GetHashCode ( ) + RowIndex . GetHashCode ( ) ;
}
2014-08-10 15:57:59 +00:00
}
2014-08-11 00:08:16 +00:00
#endregion
2014-08-10 15:57:59 +00:00
}
2014-08-06 01:32:27 +00:00
}