1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2005,2006 Novell, Inc. (http://www.novell.com)
23 // Jordi Mas i Hernandez <jordi@ximian.com>
24 // Chris Toshok <toshok@ximian.com>
32 using System.ComponentModel;
35 using System.Runtime.InteropServices;
36 using System.Collections;
39 namespace System.Windows.Forms
41 internal class DataGridRelationshipRow {
44 public DataGridRelationshipRow (DataGrid owner)
52 relation_area = Rectangle.Empty;
57 /* this needs to be a property so that the Autosize
58 * example from the Windows.Forms FAQ will work */
60 get { return height; }
62 if (height != value) {
64 owner.UpdateRowsFrom (this);
69 public bool IsSelected;
70 public bool IsExpanded;
71 public int VerticalOffset;
72 public int RelationHeight;
73 public Rectangle relation_area; /* the Y coordinate of this rectangle is updated as needed */
76 internal class DataGridDataSource
78 public DataGrid owner;
79 public CurrencyManager list_manager;
80 public DataRowView view;
81 public string data_member;
82 public object data_source;
83 public DataGridCell current;
85 public DataGridDataSource (DataGrid owner, CurrencyManager list_manager, object data_source, string data_member, DataRowView view, DataGridCell current)
88 this.list_manager = list_manager;
90 this.data_source = data_source;
91 this.data_member = data_member;
92 this.current = current;
95 DataGridRelationshipRow[] rows;
96 public DataGridRelationshipRow[] Rows {
101 Hashtable selected_rows;
102 public Hashtable SelectedRows {
103 get { return selected_rows; }
104 set { selected_rows = value; }
108 public int SelectionStart {
109 get { return selection_start; }
110 set { selection_start = value; }
114 [DefaultEvent("Navigate")]
115 [DefaultProperty("DataSource")]
116 [Designer("System.Windows.Forms.Design.DataGridDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
117 public class DataGrid : Control, ISupportInitialize, IDataGridEditingService
121 public enum HitTestType
133 public sealed class HitTestInfo
135 public static readonly HitTestInfo Nowhere = null;
139 DataGrid.HitTestType type;
141 #region Private Constructors
142 internal HitTestInfo () : this (-1, -1, HitTestType.None)
146 internal HitTestInfo (int row, int column, DataGrid.HitTestType type)
149 this.column = column;
155 #region Public Instance Properties
157 get { return column; }
163 public DataGrid.HitTestType Type {
166 #endregion //Public Instance Properties
168 public override bool Equals (object o)
170 if (!(o is HitTestInfo))
173 HitTestInfo obj = (HitTestInfo) o;
174 return (obj.Column == column && obj.Row == row && obj.Type ==type);
177 public override int GetHashCode ()
182 public override string ToString ()
184 return "{ " + type + "," + row + "," + column + "}";
189 #region Local Variables
190 /* cached theme defaults */
191 static readonly Color def_background_color = ThemeEngine.Current.DataGridBackgroundColor;
192 static readonly Color def_caption_backcolor = ThemeEngine.Current.DataGridCaptionBackColor;
193 static readonly Color def_caption_forecolor = ThemeEngine.Current.DataGridCaptionForeColor;
194 static readonly Color def_parentrowsback_color = ThemeEngine.Current.DataGridParentRowsBackColor;
195 static readonly Color def_parentrowsfore_color = ThemeEngine.Current.DataGridParentRowsForeColor;
198 Color background_color;
199 Color caption_backcolor;
200 Color caption_forecolor;
201 Color parentrowsback_color;
202 Color parentrowsfore_color;
204 /* flags to determine which areas of the datagrid are shown */
205 bool caption_visible;
206 bool parentrows_visible;
208 GridTableStylesCollection styles_collection;
209 DataGridParentRowsLabelStyle parentrowslabel_style;
210 DataGridTableStyle default_style;
211 DataGridTableStyle grid_style;
212 DataGridTableStyle current_style;
215 DataGridCell current_cell;
216 Hashtable selected_rows;
217 int selection_start; // used for range selection
219 /* layout/rendering */
220 bool allow_navigation;
221 int first_visiblerow;
222 int first_visiblecolumn;
223 int visiblerow_count;
224 int visiblecolumn_count;
228 HScrollBar horiz_scrollbar;
229 VScrollBar vert_scrollbar;
230 int horiz_pixeloffset;
232 internal Bitmap back_button_image;
233 internal Rectangle back_button_rect;
234 internal bool back_button_mouseover;
235 internal bool back_button_active;
236 internal Bitmap parent_rows_button_image;
237 internal Rectangle parent_rows_button_rect;
238 internal bool parent_rows_button_mouseover;
239 internal bool parent_rows_button_active;
244 CurrencyManager list_manager;
246 DataGridRelationshipRow[] rows;
248 /* column resize fields */
249 bool column_resize_active;
251 int resize_column_width_delta;
254 /* row resize fields */
255 bool row_resize_active;
257 int resize_row_height_delta;
260 /* used to make sure we don't endlessly recurse calling set_CurrentCell and OnListManagerPositionChanged */
261 bool from_positionchanged_handler;
264 Control editingControl;
265 bool cursor_in_add_row;
266 bool add_row_changed;
267 bool is_editing; // Current cell is edit mode
270 internal Stack dataSourceStack;
272 #endregion // Local Variables
274 #region Public Constructors
277 allow_navigation = true;
278 background_color = def_background_color;
279 border_style = BorderStyle.Fixed3D;
280 caption_backcolor = def_caption_backcolor;
281 caption_forecolor = def_caption_forecolor;
282 caption_text = string.Empty;
283 caption_visible = true;
284 datamember = string.Empty;
285 parentrowsback_color = def_parentrowsback_color;
286 parentrowsfore_color = def_parentrowsfore_color;
287 parentrows_visible = true;
288 current_cell = new DataGridCell ();
289 parentrowslabel_style = DataGridParentRowsLabelStyle.Both;
290 selected_rows = new Hashtable ();
291 selection_start = -1;
292 rows = new DataGridRelationshipRow [0];
294 default_style = new DataGridTableStyle (true);
295 grid_style = new DataGridTableStyle ();
297 styles_collection = new GridTableStylesCollection (this);
298 styles_collection.CollectionChanged += new CollectionChangeEventHandler (OnTableStylesCollectionChanged);
300 CurrentTableStyle = grid_style;
302 horiz_scrollbar = new ImplicitHScrollBar ();
303 horiz_scrollbar.Scroll += new ScrollEventHandler (GridHScrolled);
304 vert_scrollbar = new ImplicitVScrollBar ();
305 vert_scrollbar.Scroll += new ScrollEventHandler (GridVScrolled);
307 SetStyle (ControlStyles.UserMouse, true);
309 dataSourceStack = new Stack ();
311 back_button_image = ResourceImageLoader.Get ("go-previous.png");
312 parent_rows_button_image = ResourceImageLoader.Get ("go-top.png");
315 #endregion // Public Constructor
317 #region Public Instance Properties
320 public bool AllowNavigation {
321 get { return allow_navigation; }
323 if (allow_navigation != value) {
324 allow_navigation = value;
325 OnAllowNavigationChanged (EventArgs.Empty);
331 public bool AllowSorting {
332 get { return grid_style.AllowSorting; }
333 set { grid_style.AllowSorting = value; }
336 public Color AlternatingBackColor {
337 get { return grid_style.AlternatingBackColor; }
338 set { grid_style.AlternatingBackColor = value; }
341 public override Color BackColor {
342 get { return grid_style.BackColor; }
343 set { grid_style.BackColor = value; }
346 public Color BackgroundColor {
347 get { return background_color; }
349 if (background_color != value) {
350 background_color = value;
351 OnBackgroundColorChanged (EventArgs.Empty);
358 [EditorBrowsable(EditorBrowsableState.Never)]
359 public override Image BackgroundImage {
360 get { return base.BackgroundImage; }
362 if (base.BackgroundImage == value)
365 base.BackgroundImage = value;
371 [DefaultValue(BorderStyle.Fixed3D)]
372 public BorderStyle BorderStyle {
373 get { return InternalBorderStyle; }
375 InternalBorderStyle = value;
376 CalcAreasAndInvalidate ();
377 OnBorderStyleChanged (EventArgs.Empty);
381 public Color CaptionBackColor {
382 get { return caption_backcolor; }
384 if (caption_backcolor != value) {
385 caption_backcolor = value;
386 InvalidateCaption ();
393 public Font CaptionFont {
395 if (caption_font == null)
401 if (caption_font != null && caption_font.Equals (value))
404 caption_font = value;
405 CalcAreasAndInvalidate ();
409 public Color CaptionForeColor {
410 get { return caption_forecolor; }
412 if (caption_forecolor != value) {
413 caption_forecolor = value;
414 InvalidateCaption ();
421 public string CaptionText {
422 get { return caption_text; }
424 if (caption_text != value) {
425 caption_text = value;
426 InvalidateCaption ();
432 public bool CaptionVisible {
433 get { return caption_visible; }
435 if (caption_visible != value) {
436 caption_visible = value;
437 CalcAreasAndInvalidate ();
438 OnCaptionVisibleChanged (EventArgs.Empty);
444 public bool ColumnHeadersVisible {
445 get { return grid_style.ColumnHeadersVisible; }
446 set { grid_style.ColumnHeadersVisible = value; }
449 bool setting_current_cell;
452 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
453 public DataGridCell CurrentCell {
454 get { return current_cell; }
456 if (setting_current_cell)
458 setting_current_cell = true;
460 if (!IsHandleCreated) {
461 setting_current_cell = false;
462 throw new Exception ("CurrentCell cannot be set at this time.");
465 if (current_cell.Equals (value)) {
466 setting_current_cell = false;
470 /* make sure the new cell fits in the correct bounds for [row,column] */
471 if (ReadOnly && value.RowNumber > RowsCount - 1)
472 value.RowNumber = RowsCount - 1;
473 else if (value.RowNumber > RowsCount)
474 value.RowNumber = RowsCount;
475 if (value.ColumnNumber >= CurrentTableStyle.GridColumnStyles.Count)
476 value.ColumnNumber = CurrentTableStyle.GridColumnStyles.Count == 0 ? 0 : CurrentTableStyle.GridColumnStyles.Count - 1;
478 bool was_changing = is_changing;
480 add_row_changed = add_row_changed || was_changing;
483 if (value.RowNumber != current_cell.RowNumber) {
484 if (!from_positionchanged_handler) {
486 ListManager.EndCurrentEdit ();
488 catch (Exception e) {
489 DialogResult r = MessageBox.Show (String.Format ("{0} Do you wish to correct the value?", e.Message),
490 "Error when committing the row to the original data source",
491 MessageBoxButtons.YesNo);
492 if (r == DialogResult.Yes) {
497 ListManager.CancelCurrentEdit ();
501 if (value.RowNumber == RowsCount && !ListManager.CanAddRows)
504 if (value.RowNumber == RowsCount) {
505 cursor_in_add_row = true;
506 add_row_changed = false;
510 cursor_in_add_row = false;
514 int old_row = current_cell.RowNumber;
516 current_cell = value;
518 EnsureCellVisibility (current_cell);
520 InvalidateRowHeader (old_row);
521 InvalidateRowHeader (current_cell.RowNumber);
523 list_manager.Position = current_cell.RowNumber;
525 OnCurrentCellChanged (EventArgs.Empty);
527 if (!from_positionchanged_handler)
530 setting_current_cell = false;
535 get { return current_cell.RowNumber; }
536 set { CurrentCell = new DataGridCell (value, current_cell.ColumnNumber); }
540 get { return current_cell.ColumnNumber; }
541 set { CurrentCell = new DataGridCell (current_cell.RowNumber, value); }
545 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
546 public int CurrentRowIndex {
548 if (ListManager == null)
553 set { CurrentRow = value; }
557 [EditorBrowsable(EditorBrowsableState.Never)]
558 public override Cursor Cursor {
559 get { return base.Cursor; }
560 set { base.Cursor = value; }
564 [Editor ("System.Windows.Forms.Design.DataMemberListEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
565 public string DataMember {
566 get { return datamember; }
568 SetDataSource (datasource, value);
573 [RefreshProperties(RefreshProperties.Repaint)]
574 [TypeConverter("System.Windows.Forms.Design.DataSourceConverter, " + Consts.AssemblySystem_Design)]
575 public object DataSource {
576 get { return datasource; }
578 SetDataSource (value, ListManager == null ? datamember : string.Empty);
582 protected override Size DefaultSize {
583 get { return new Size (130, 80); }
587 public int FirstVisibleColumn {
588 get { return first_visiblecolumn; }
591 [DefaultValue(false)]
592 public bool FlatMode {
593 get { return flatmode; }
595 if (flatmode != value) {
597 OnFlatModeChanged (EventArgs.Empty);
603 public override Color ForeColor {
604 get { return grid_style.ForeColor; }
605 set { grid_style.ForeColor = value; }
608 public Color GridLineColor {
609 get { return grid_style.GridLineColor; }
611 if (value == Color.Empty)
612 throw new ArgumentException ("Color.Empty value is invalid.");
614 grid_style.GridLineColor = value;
618 [DefaultValue(DataGridLineStyle.Solid)]
619 public DataGridLineStyle GridLineStyle {
620 get { return grid_style.GridLineStyle; }
621 set { grid_style.GridLineStyle = value; }
624 public Color HeaderBackColor {
625 get { return grid_style.HeaderBackColor; }
627 if (value == Color.Empty)
628 throw new ArgumentException ("Color.Empty value is invalid.");
630 grid_style.HeaderBackColor = value;
634 public Font HeaderFont {
635 get { return grid_style.HeaderFont; }
636 set { grid_style.HeaderFont = value; }
639 public Color HeaderForeColor {
640 get { return grid_style.HeaderForeColor; }
641 set { grid_style.HeaderForeColor = value; }
644 protected ScrollBar HorizScrollBar {
645 get { return horiz_scrollbar; }
647 internal ScrollBar HScrollBar {
648 get { return horiz_scrollbar; }
651 internal int HorizPixelOffset {
652 get { return horiz_pixeloffset; }
655 internal bool IsChanging {
656 get { return is_changing; }
659 public object this [DataGridCell cell] {
660 get { return this [cell.RowNumber, cell.ColumnNumber]; }
661 set { this [cell.RowNumber, cell.ColumnNumber] = value; }
664 public object this [int rowIndex, int columnIndex] {
665 get { return CurrentTableStyle.GridColumnStyles[columnIndex].GetColumnValueAtRow (ListManager,
667 set { CurrentTableStyle.GridColumnStyles[columnIndex].SetColumnValueAtRow (ListManager,
671 public Color LinkColor {
672 get { return grid_style.LinkColor; }
673 set { grid_style.LinkColor = value; }
676 internal Font LinkFont {
677 get { return new Font (Font, FontStyle.Underline); }
682 [EditorBrowsable(EditorBrowsableState.Never)]
683 public Color LinkHoverColor {
684 get { return grid_style.LinkHoverColor; }
685 set { grid_style.LinkHoverColor = value; }
689 [EditorBrowsable(EditorBrowsableState.Advanced)]
690 protected internal CurrencyManager ListManager {
692 if (list_manager == null)
693 SetDataSource (DataSource, DataMember);
697 set { throw new NotSupportedException ("Operation is not supported."); }
700 public Color ParentRowsBackColor {
701 get { return parentrowsback_color; }
703 if (parentrowsback_color != value) {
704 parentrowsback_color = value;
705 if (parentrows_visible) {
712 public Color ParentRowsForeColor {
713 get { return parentrowsfore_color; }
715 if (parentrowsfore_color != value) {
716 parentrowsfore_color = value;
717 if (parentrows_visible) {
724 [DefaultValue(DataGridParentRowsLabelStyle.Both)]
725 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
726 public DataGridParentRowsLabelStyle ParentRowsLabelStyle {
727 get { return parentrowslabel_style; }
729 if (parentrowslabel_style != value) {
730 parentrowslabel_style = value;
731 if (parentrows_visible) {
735 OnParentRowsLabelStyleChanged (EventArgs.Empty);
741 public bool ParentRowsVisible {
742 get { return parentrows_visible; }
744 if (parentrows_visible != value) {
745 parentrows_visible = value;
746 CalcAreasAndInvalidate ();
747 OnParentRowsVisibleChanged (EventArgs.Empty);
752 // Settting this property seems to have no effect.
754 [TypeConverter(typeof(DataGridPreferredColumnWidthTypeConverter))]
755 public int PreferredColumnWidth {
756 get { return grid_style.PreferredColumnWidth; }
757 set { grid_style.PreferredColumnWidth = value; }
760 public int PreferredRowHeight {
761 get { return grid_style.PreferredRowHeight; }
762 set { grid_style.PreferredRowHeight = value; }
765 [DefaultValue(false)]
766 public bool ReadOnly {
767 get { return _readonly; }
769 if (_readonly != value) {
771 OnReadOnlyChanged (EventArgs.Empty);
772 CalcAreasAndInvalidate ();
778 public bool RowHeadersVisible {
779 get { return grid_style.RowHeadersVisible; }
780 set { grid_style.RowHeadersVisible = value; }
784 public int RowHeaderWidth {
785 get { return grid_style.RowHeaderWidth; }
786 set { grid_style.RowHeaderWidth = value; }
789 internal DataGridRelationshipRow[] DataGridRows {
794 public Color SelectionBackColor {
795 get { return grid_style.SelectionBackColor; }
796 set { grid_style.SelectionBackColor = value; }
799 public Color SelectionForeColor {
800 get { return grid_style.SelectionForeColor; }
801 set { grid_style.SelectionForeColor = value; }
804 public override ISite Site {
805 get { return base.Site; }
806 set { base.Site = value; }
810 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
811 public GridTableStylesCollection TableStyles {
812 get { return styles_collection; }
817 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
818 [EditorBrowsable(EditorBrowsableState.Never)]
819 public override string Text {
820 get { return base.Text; }
821 set { base.Text = value; }
825 [EditorBrowsable(EditorBrowsableState.Advanced)]
826 protected ScrollBar VertScrollBar {
827 get { return vert_scrollbar; }
829 internal ScrollBar VScrollBar {
830 get { return vert_scrollbar; }
834 public int VisibleColumnCount {
835 get { return visiblecolumn_count; }
839 public int VisibleRowCount {
840 get { return visiblerow_count; }
843 #endregion // Public Instance Properties
845 #region Private Instance Properties
846 internal DataGridTableStyle CurrentTableStyle {
847 get { return current_style; }
849 current_style = value;
850 current_style.DataGrid = this;
851 CalcAreasAndInvalidate ();
855 internal int FirstVisibleRow {
856 get { return first_visiblerow; }
859 internal int RowsCount {
860 get { return ListManager != null ? ListManager.Count : 0; }
863 internal int RowHeight {
865 if (CurrentTableStyle.CurrentPreferredRowHeight > Font.Height + 3 + 1 /* line */)
866 return CurrentTableStyle.CurrentPreferredRowHeight;
868 return Font.Height + 3 + 1 /* line */;
872 internal bool ShowEditRow {
874 if (ListManager != null && !ListManager.CanAddRows)
881 internal bool ShowParentRows {
882 get { return ParentRowsVisible && dataSourceStack.Count > 0; }
885 #endregion Private Instance Properties
887 #region Public Instance Methods
892 CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber].Abort (current_cell.RowNumber);
894 InvalidateRowHeader (current_cell.RowNumber);
899 public bool BeginEdit (DataGridColumnStyle gridColumn, int rowNumber)
904 int column = CurrentTableStyle.GridColumnStyles.IndexOf (gridColumn);
908 CurrentCell = new DataGridCell (rowNumber, column);
910 /* force editing of CurrentCell if we aren't already editing */
916 public void BeginInit ()
920 protected virtual void CancelEditing ()
922 CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber].ConcedeFocus ();
925 if (current_cell.ColumnNumber < CurrentTableStyle.GridColumnStyles.Count)
926 CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber].Abort (current_cell.RowNumber);
927 InvalidateRowHeader (current_cell.RowNumber);
930 if (cursor_in_add_row && !is_changing) {
931 ListManager.CancelCurrentEdit ();
934 editingControl = null;
940 public void Collapse (int row)
942 if (!rows[row].IsExpanded)
946 rows[row].IsExpanded = false;
947 for (int i = 1; i < rows.Length - row; i ++)
948 rows[row + i].VerticalOffset -= rows[row].RelationHeight;
950 rows[row].height -= rows[row].RelationHeight;
951 rows[row].RelationHeight = 0;
952 ResumeLayout (false);
954 /* XX need to redraw from @row down */
955 CalcAreasAndInvalidate ();
958 protected internal virtual void ColumnStartedEditing (Control editingControl)
960 ColumnStartedEditing (editingControl.Bounds);
961 this.editingControl = editingControl;
964 protected internal virtual void ColumnStartedEditing (Rectangle bounds)
966 bool need_invalidate = is_changing == false;
967 // XXX calculate the row header to invalidate
968 // instead of using CurrentRow
971 if (cursor_in_add_row && need_invalidate)
972 RecreateDataGridRows (true);
975 InvalidateRowHeader (CurrentRow);
978 protected override AccessibleObject CreateAccessibilityInstance ()
980 return base.CreateAccessibilityInstance ();
983 protected virtual DataGridColumnStyle CreateGridColumn (PropertyDescriptor prop)
985 return CreateGridColumn (prop, false);
988 protected virtual DataGridColumnStyle CreateGridColumn (PropertyDescriptor prop, bool isDefault)
990 throw new NotImplementedException();
993 protected override void Dispose (bool disposing)
995 base.Dispose (disposing);
998 public bool EndEdit (DataGridColumnStyle gridColumn, int rowNumber, bool shouldAbort)
1000 if (shouldAbort || gridColumn.ParentReadOnly)
1001 gridColumn.Abort (rowNumber);
1003 gridColumn.Commit (ListManager, rowNumber);
1004 gridColumn.ConcedeFocus ();
1007 editingControl = null;
1008 if (is_editing || is_changing) {
1010 is_changing = false;
1011 InvalidateRowHeader (rowNumber);
1016 public void EndInit ()
1020 public void Expand (int row)
1022 if (rows[row].IsExpanded)
1025 rows[row].IsExpanded = true;
1029 string[] relations = CurrentTableStyle.Relations;
1030 StringBuilder relation_builder = new StringBuilder ("");
1032 for (i = 0; i < relations.Length; i ++) {
1034 relation_builder.Append ("\n");
1036 relation_builder.Append (relations[i]);
1038 string relation_text = relation_builder.ToString ();
1040 SizeF measured_area = DeviceContext.MeasureString (relation_text, LinkFont);
1042 rows[row].relation_area = new Rectangle (cells_area.X + 1,
1043 0, /* updated as needed at the usage sites for relation_area */
1044 (int)measured_area.Width + 4,
1045 Font.Height * relations.Length);
1047 for (i = 1; i < rows.Length - row; i ++)
1048 rows[row + i].VerticalOffset += rows[row].relation_area.Height;
1049 rows[row].height += rows[row].relation_area.Height;
1050 rows[row].RelationHeight = rows[row].relation_area.Height;
1052 /* XX need to redraw from @row down */
1053 CalcAreasAndInvalidate ();
1056 public Rectangle GetCellBounds (DataGridCell cell)
1058 return GetCellBounds (cell.RowNumber, cell.ColumnNumber);
1061 public Rectangle GetCellBounds (int row, int col)
1063 Rectangle bounds = new Rectangle ();
1066 bounds.Width = CurrentTableStyle.GridColumnStyles[col].Width;
1067 bounds.Height = rows[row].Height - rows[row].RelationHeight;
1068 bounds.Y = cells_area.Y + rows[row].VerticalOffset - rows[FirstVisibleRow].VerticalOffset;
1069 col_pixel = GetColumnStartingPixel (col);
1070 bounds.X = cells_area.X + col_pixel - horiz_pixeloffset;
1074 public Rectangle GetCurrentCellBounds ()
1076 return GetCellBounds (current_cell.RowNumber, current_cell.ColumnNumber);
1079 protected virtual string GetOutputTextDelimiter ()
1081 return string.Empty;
1084 protected virtual void GridHScrolled (object sender, ScrollEventArgs se)
1086 if (se.NewValue == horiz_pixeloffset ||
1087 se.Type == ScrollEventType.EndScroll) {
1091 ScrollToColumnInPixels (se.NewValue);
1094 protected virtual void GridVScrolled (object sender, ScrollEventArgs se)
1096 int old_first_visiblerow = first_visiblerow;
1097 first_visiblerow = se.NewValue;
1099 if (first_visiblerow == old_first_visiblerow)
1102 UpdateVisibleRowCount ();
1104 if (first_visiblerow == old_first_visiblerow)
1107 ScrollToRow (old_first_visiblerow, first_visiblerow);
1110 public HitTestInfo HitTest (Point position)
1112 return HitTest (position.X, position.Y);
1115 const int RESIZE_HANDLE_HORIZ_SIZE = 5;
1116 const int RESIZE_HANDLE_VERT_SIZE = 3;
1118 // From Point to Cell
1119 public HitTestInfo HitTest (int x, int y)
1121 if (columnhdrs_area.Contains (x, y)) {
1122 int offset_x = x + horiz_pixeloffset;
1124 int column_under_mouse = FromPixelToColumn (offset_x, out column_x);
1126 if ((column_x + CurrentTableStyle.GridColumnStyles[column_under_mouse].Width - offset_x < RESIZE_HANDLE_HORIZ_SIZE)
1127 && column_under_mouse < CurrentTableStyle.GridColumnStyles.Count) {
1129 return new HitTestInfo (-1, column_under_mouse, HitTestType.ColumnResize);
1132 return new HitTestInfo (-1, column_under_mouse, HitTestType.ColumnHeader);
1136 if (rowhdrs_area.Contains (x, y)) {
1138 int rcnt = FirstVisibleRow + VisibleRowCount;
1139 for (int r = FirstVisibleRow; r < rcnt; r++) {
1140 posy = cells_area.Y + rows[r].VerticalOffset - rows[FirstVisibleRow].VerticalOffset;
1141 if (y <= posy + rows[r].Height) {
1142 if ((posy + rows[r].Height) - y < RESIZE_HANDLE_VERT_SIZE) {
1143 return new HitTestInfo (r, -1, HitTestType.RowResize);
1146 return new HitTestInfo (r, -1, HitTestType.RowHeader);
1152 if (caption_area.Contains (x, y)) {
1153 return new HitTestInfo (-1, -1, HitTestType.Caption);
1156 if (parent_rows.Contains (x, y)) {
1157 return new HitTestInfo (-1, -1, HitTestType.ParentRows);
1160 int pos_y, pos_x, width;
1161 int rowcnt = FirstVisibleRow + VisibleRowCount;
1162 for (int row = FirstVisibleRow; row < rowcnt; row++) {
1164 pos_y = cells_area.Y + rows[row].VerticalOffset - rows[FirstVisibleRow].VerticalOffset;
1165 if (y <= pos_y + rows[row].Height) {
1167 int column_cnt = first_visiblecolumn + visiblecolumn_count;
1168 for (int column = first_visiblecolumn; column < column_cnt; column++) {
1169 if (CurrentTableStyle.GridColumnStyles[column].bound == false)
1171 col_pixel = GetColumnStartingPixel (column);
1172 pos_x = cells_area.X + col_pixel - horiz_pixeloffset;
1173 width = CurrentTableStyle.GridColumnStyles[column].Width;
1175 if (x <= pos_x + width) { // Column found
1176 return new HitTestInfo (row, column, HitTestType.Cell);
1184 return new HitTestInfo ();
1187 public bool IsExpanded (int rowNumber)
1189 return (rows[rowNumber].IsExpanded);
1192 public bool IsSelected (int row)
1194 return rows[row].IsSelected;
1198 public void NavigateBack ()
1200 if (dataSourceStack.Count == 0)
1203 DataGridDataSource source = (DataGridDataSource)dataSourceStack.Pop ();
1204 list_manager = source.list_manager;
1206 selected_rows = source.SelectedRows;
1207 selection_start = source.SelectionStart;
1208 SetDataSource (source.data_source, source.data_member);
1210 CurrentCell = source.current;
1214 public void NavigateTo (int rowNumber, string relationName)
1216 if (allow_navigation == false)
1219 DataGridDataSource previous_source = new DataGridDataSource (this, list_manager, datasource, datamember, (DataRowView)list_manager.Current, CurrentCell);
1220 previous_source.Rows = rows;
1221 previous_source.SelectedRows = selected_rows;
1222 previous_source.SelectionStart = selection_start;
1224 dataSourceStack.Push (previous_source);
1227 selected_rows = new Hashtable ();
1228 selection_start = -1;
1230 DataMember = String.Format ("{0}.{1}", DataMember, relationName);
1231 OnDataSourceChanged (EventArgs.Empty);
1234 protected virtual void OnAllowNavigationChanged (EventArgs e)
1236 if (AllowNavigationChanged != null) {
1237 AllowNavigationChanged (this, e);
1241 protected void OnBackButtonClicked (object sender, EventArgs e)
1243 if (BackButtonClick != null)
1244 BackButtonClick (sender, e);
1247 protected override void OnBackColorChanged (EventArgs e)
1249 base.OnBackColorChanged (e);
1252 protected virtual void OnBackgroundColorChanged (EventArgs e)
1254 if (BackgroundColorChanged != null)
1255 BackgroundColorChanged (this, e);
1258 protected override void OnBindingContextChanged (EventArgs e)
1260 base.OnBindingContextChanged (e);
1262 SetDataSource (datasource, datamember);
1265 protected virtual void OnBorderStyleChanged (EventArgs e)
1267 if (BorderStyleChanged != null)
1268 BorderStyleChanged (this, e);
1271 protected virtual void OnCaptionVisibleChanged (EventArgs e)
1273 if (CaptionVisibleChanged != null)
1274 CaptionVisibleChanged (this, e);
1277 protected virtual void OnCurrentCellChanged (EventArgs e)
1279 if (CurrentCellChanged != null)
1280 CurrentCellChanged (this, e);
1283 protected virtual void OnDataSourceChanged (EventArgs e)
1285 if (DataSourceChanged != null)
1286 DataSourceChanged (this, e);
1289 protected override void OnEnter (EventArgs e)
1294 protected virtual void OnFlatModeChanged (EventArgs e)
1296 if (FlatModeChanged != null)
1297 FlatModeChanged (this, e);
1300 protected override void OnFontChanged (EventArgs e)
1303 base.OnFontChanged (e);
1306 protected override void OnForeColorChanged (EventArgs e)
1308 base.OnForeColorChanged (e);
1311 protected override void OnHandleCreated (EventArgs e)
1313 base.OnHandleCreated (e);
1317 protected override void OnHandleDestroyed (EventArgs e)
1319 base.OnHandleDestroyed (e);
1322 protected override void OnKeyDown (KeyEventArgs ke)
1324 base.OnKeyDown (ke);
1326 if (ProcessGridKey (ke) == true)
1329 /* TODO: we probably don't need this check,
1330 * since current_cell wouldn't have been set
1331 * to something invalid */
1332 if (CurrentTableStyle.GridColumnStyles.Count > 0) {
1333 CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber].OnKeyDown
1334 (ke, current_cell.RowNumber, current_cell.ColumnNumber);
1338 protected override void OnKeyPress (KeyPressEventArgs kpe)
1340 base.OnKeyPress (kpe);
1343 protected override void OnLayout (LayoutEventArgs levent)
1345 base.OnLayout (levent);
1346 CalcAreasAndInvalidate ();
1349 protected override void OnLeave (EventArgs e)
1354 /* we get an OnLeave call when the
1355 * DataGridTextBox control is focused, so we
1356 * need to ignore that. If we get an OnLeave
1357 * call when a child control is not receiving
1358 * focus, we need to cancel the current
1360 if (cursor_in_add_row) {
1361 ListManager.CancelCurrentEdit ();
1366 protected override void OnMouseDown (MouseEventArgs e)
1368 base.OnMouseDown (e);
1370 bool ctrl_pressed = ((Control.ModifierKeys & Keys.Control) != 0);
1371 bool shift_pressed = ((Control.ModifierKeys & Keys.Shift) != 0);
1373 HitTestInfo testinfo;
1374 testinfo = HitTest (e.X, e.Y);
1376 switch (testinfo.Type) {
1377 case HitTestType.Cell:
1378 if (testinfo.Row < 0 || testinfo.Column < 0)
1381 if (rows[testinfo.Row].IsExpanded) {
1382 Rectangle relation_area = rows[testinfo.Row].relation_area;
1383 relation_area.Y = rows[testinfo.Row].VerticalOffset + cells_area.Y + rows[testinfo.Row].Height - rows[testinfo.Row].RelationHeight;
1384 if (relation_area.Contains (e.X, e.Y)) {
1385 /* the click happened in the relation area, navigate to the new table */
1386 int relative = e.Y - relation_area.Y;
1387 NavigateTo (testinfo.Row, CurrentTableStyle.Relations[relative / LinkFont.Height]);
1392 DataGridCell new_cell = new DataGridCell (testinfo.Row, testinfo.Column);
1394 if ((new_cell.Equals (current_cell) == false) || (!is_editing)) {
1395 EnsureCellVisibility (new_cell);
1396 CurrentCell = new_cell;
1399 CurrentTableStyle.GridColumnStyles[testinfo.Column].OnMouseDown (e, testinfo.Row, testinfo.Column);
1404 case HitTestType.RowHeader:
1405 bool expansion_click = false;
1406 if (CurrentTableStyle.HasRelations) {
1407 if (e.X > rowhdrs_area.X + rowhdrs_area.Width / 2) {
1408 /* it's in the +/- space */
1409 if (IsExpanded (testinfo.Row))
1410 Collapse (testinfo.Row);
1412 Expand (testinfo.Row);
1414 expansion_click = true;
1418 if (!ctrl_pressed &&
1421 ResetSelection (); // Invalidates selected rows
1424 if ((shift_pressed ||
1426 && selection_start != -1) {
1427 ShiftSelection (testinfo.Row);
1428 } else { // ctrl_pressed or single item
1429 selection_start = testinfo.Row;
1430 Select (testinfo.Row);
1434 CurrentRow = testinfo.Row;
1435 OnRowHeaderClick (EventArgs.Empty);
1439 case HitTestType.ColumnHeader:
1440 if (CurrentTableStyle.GridColumnStyles.Count == 0)
1443 if (AllowSorting == false)
1446 if (ListManager.List is IBindingList == false)
1449 ListSortDirection direction = ListSortDirection.Ascending;
1450 PropertyDescriptor prop = CurrentTableStyle.GridColumnStyles[testinfo.Column].PropertyDescriptor;
1451 IBindingList list = (IBindingList) ListManager.List;
1453 if (list.SortProperty != null) {
1454 CurrentTableStyle.GridColumnStyles[list.SortProperty].ArrowDrawingMode
1455 = DataGridColumnStyle.ArrowDrawing.No;
1458 if (prop == list.SortProperty && list.SortDirection == ListSortDirection.Ascending) {
1459 direction = ListSortDirection.Descending;
1462 CurrentTableStyle.GridColumnStyles[testinfo.Column].ArrowDrawingMode =
1463 direction == ListSortDirection.Ascending ?
1464 DataGridColumnStyle.ArrowDrawing.Ascending : DataGridColumnStyle.ArrowDrawing.Descending;
1466 list.ApplySort (prop, direction);
1470 case HitTestType.ColumnResize:
1471 resize_column = testinfo.Column;
1472 column_resize_active = true;
1473 resize_column_x = e.X;
1474 resize_column_width_delta = 0;
1476 DrawResizeLineVert (resize_column_x);
1479 case HitTestType.RowResize:
1480 resize_row = testinfo.Row;
1481 row_resize_active = true;
1483 resize_row_height_delta = 0;
1485 DrawResizeLineHoriz (resize_row_y);
1488 case HitTestType.Caption:
1489 if (back_button_rect.Contains (e.X, e.Y)) {
1490 back_button_active = true;
1491 Invalidate (back_button_rect);
1493 if (parent_rows_button_rect.Contains (e.X, e.Y)) {
1494 parent_rows_button_active = true;
1495 Invalidate (parent_rows_button_rect);
1504 protected override void OnMouseLeave (EventArgs e)
1506 base.OnMouseLeave (e);
1509 protected override void OnMouseMove (MouseEventArgs e)
1511 base.OnMouseMove (e);
1513 if (column_resize_active) {
1514 /* erase the old line */
1515 DrawResizeLineVert (resize_column_x + resize_column_width_delta);
1517 resize_column_width_delta = e.X - resize_column_x;
1519 /* draw the new line */
1520 DrawResizeLineVert (resize_column_x + resize_column_width_delta);
1523 else if (row_resize_active) {
1524 /* erase the old line */
1525 DrawResizeLineHoriz (resize_row_y + resize_row_height_delta);
1527 resize_row_height_delta = e.Y - resize_row_y;
1529 /* draw the new line */
1530 DrawResizeLineHoriz (resize_row_y + resize_row_height_delta);
1534 /* determine the cursor to use */
1535 HitTestInfo testinfo;
1536 testinfo = HitTest (e.X, e.Y);
1538 switch (testinfo.Type) {
1539 case HitTestType.ColumnResize:
1540 Cursor = Cursors.VSplit;
1542 case HitTestType.RowResize:
1543 Cursor = Cursors.HSplit;
1545 case HitTestType.Caption:
1546 Cursor = Cursors.Default;
1547 if (back_button_rect.Contains (e.X, e.Y)) {
1548 if (!back_button_mouseover)
1549 Invalidate (back_button_rect);
1550 back_button_mouseover = true;
1552 else if (back_button_mouseover) {
1553 Invalidate (back_button_rect);
1554 back_button_mouseover = false;
1557 if (parent_rows_button_rect.Contains (e.X, e.Y)) {
1558 if (parent_rows_button_mouseover)
1559 Invalidate (parent_rows_button_rect);
1560 parent_rows_button_mouseover = true;
1562 else if (parent_rows_button_mouseover) {
1563 Invalidate (parent_rows_button_rect);
1564 parent_rows_button_mouseover = false;
1567 case HitTestType.Cell:
1568 if (rows[testinfo.Row].IsExpanded) {
1569 Rectangle relation_area = rows[testinfo.Row].relation_area;
1570 relation_area.Y = rows[testinfo.Row].VerticalOffset + cells_area.Y + rows[testinfo.Row].Height - rows[testinfo.Row].RelationHeight;
1571 if (relation_area.Contains (e.X, e.Y)) {
1572 Cursor = Cursors.Hand;
1577 Cursor = Cursors.Default;
1580 Cursor = Cursors.Default;
1586 protected override void OnMouseUp (MouseEventArgs e)
1590 if (column_resize_active) {
1591 column_resize_active = false;
1592 if (resize_column_width_delta + CurrentTableStyle.GridColumnStyles[resize_column].Width < 0)
1593 resize_column_width_delta = -CurrentTableStyle.GridColumnStyles[resize_column].Width;
1594 CurrentTableStyle.GridColumnStyles[resize_column].Width += resize_column_width_delta;
1595 width_of_all_columns += resize_column_width_delta;
1599 else if (row_resize_active) {
1600 row_resize_active = false;
1602 if (resize_row_height_delta + rows[resize_row].Height < 0)
1603 resize_row_height_delta = -rows[resize_row].Height;
1605 rows[resize_row].height = rows[resize_row].Height + resize_row_height_delta;
1606 for (int i = resize_row + 1; i < rows.Length; i ++)
1607 rows[i].VerticalOffset += resize_row_height_delta;
1610 CalcAreasAndInvalidate ();
1612 else if (back_button_active) {
1613 if (back_button_rect.Contains (e.X, e.Y)) {
1614 Invalidate (back_button_rect);
1616 OnBackButtonClicked (this, EventArgs.Empty);
1618 back_button_active = false;
1620 else if (parent_rows_button_active) {
1621 if (parent_rows_button_rect.Contains (e.X, e.Y)) {
1622 Invalidate (parent_rows_button_rect);
1623 ParentRowsVisible = !ParentRowsVisible;
1624 OnShowParentDetailsButtonClicked (this, EventArgs.Empty);
1626 parent_rows_button_active = false;
1630 protected override void OnMouseWheel (MouseEventArgs e)
1632 base.OnMouseWheel (e);
1634 bool ctrl_pressed = ((Control.ModifierKeys & Keys.Control) != 0);
1637 if (ctrl_pressed) { // scroll horizontally
1640 pixels = Math.Max (horiz_scrollbar.Minimum,
1641 horiz_scrollbar.Value - horiz_scrollbar.LargeChange);
1645 pixels = Math.Min (horiz_scrollbar.Maximum - horiz_scrollbar.LargeChange + 1,
1646 horiz_scrollbar.Value + horiz_scrollbar.LargeChange);
1649 GridHScrolled (this, new ScrollEventArgs (ScrollEventType.ThumbPosition, pixels));
1650 horiz_scrollbar.Value = pixels;
1654 pixels = Math.Max (vert_scrollbar.Minimum,
1655 vert_scrollbar.Value - vert_scrollbar.LargeChange);
1659 pixels = Math.Min (vert_scrollbar.Maximum - vert_scrollbar.LargeChange + 1,
1660 vert_scrollbar.Value + vert_scrollbar.LargeChange);
1663 GridVScrolled (this, new ScrollEventArgs (ScrollEventType.ThumbPosition, pixels));
1664 vert_scrollbar.Value = pixels;
1668 protected void OnNavigate (NavigateEventArgs e)
1670 if (Navigate != null)
1674 protected override void OnPaint (PaintEventArgs pe)
1676 ThemeEngine.Current.DataGridPaint (pe, this);
1679 protected override void OnPaintBackground (PaintEventArgs ebe)
1683 protected virtual void OnParentRowsLabelStyleChanged (EventArgs e)
1685 if (ParentRowsLabelStyleChanged != null)
1686 ParentRowsLabelStyleChanged (this, e);
1689 protected virtual void OnParentRowsVisibleChanged (EventArgs e)
1691 if (ParentRowsVisibleChanged != null)
1692 ParentRowsVisibleChanged (this, e);
1695 protected virtual void OnReadOnlyChanged (EventArgs e)
1697 if (ReadOnlyChanged != null)
1698 ReadOnlyChanged (this, e);
1701 protected override void OnResize (EventArgs e)
1706 protected void OnRowHeaderClick (EventArgs e)
1708 if (RowHeaderClick != null)
1709 RowHeaderClick (this, e);
1712 protected void OnScroll (EventArgs e)
1718 protected void OnShowParentDetailsButtonClicked (object sender, EventArgs e)
1720 if (ShowParentDetailsButtonClick != null)
1721 ShowParentDetailsButtonClick (sender, e);
1724 protected override bool ProcessDialogKey (Keys keyData)
1726 return ProcessGridKey (new KeyEventArgs (keyData));
1729 void UpdateSelectionAfterCursorMove (bool extend_selection)
1731 if (extend_selection) {
1733 ShiftSelection (CurrentRow);
1740 protected bool ProcessGridKey (KeyEventArgs ke)
1742 /* if we have no rows, exit immediately.
1743 XXX is this necessary? */
1747 bool ctrl_pressed = ((ke.Modifiers & Keys.Control) != 0);
1748 bool alt_pressed = ((ke.Modifiers & Keys.Alt) != 0);
1749 bool shift_pressed = ((ke.Modifiers & Keys.Shift) != 0);
1751 switch (ke.KeyCode) {
1763 CurrentTableStyle.GridColumnStyles[CurrentColumn].EnterNullValue ();
1774 if (shift_pressed) {
1775 if (CurrentColumn > 0)
1777 else if ((CurrentRow > 0) && (CurrentColumn == 0))
1778 CurrentCell = new DataGridCell (CurrentRow - 1, CurrentTableStyle.GridColumnStyles.Count - 1);
1781 if (CurrentColumn < CurrentTableStyle.GridColumnStyles.Count - 1)
1783 else if ((CurrentRow <= RowsCount) && (CurrentColumn == CurrentTableStyle.GridColumnStyles.Count - 1))
1784 CurrentCell = new DataGridCell (CurrentRow + 1, 0);
1787 UpdateSelectionAfterCursorMove (false);
1793 CurrentColumn = CurrentTableStyle.GridColumnStyles.Count - 1;
1796 if (CurrentColumn < CurrentTableStyle.GridColumnStyles.Count - 1) {
1798 } else if (CurrentRow < RowsCount - 1
1799 || (CurrentRow == RowsCount - 1
1800 && !cursor_in_add_row)) {
1801 CurrentCell = new DataGridCell (CurrentRow + 1, 0);
1805 UpdateSelectionAfterCursorMove (false);
1814 if (current_cell.ColumnNumber > 0)
1816 else if (CurrentRow > 0)
1817 CurrentCell = new DataGridCell (CurrentRow - 1, CurrentTableStyle.GridColumnStyles.Count - 1);
1820 UpdateSelectionAfterCursorMove (false);
1827 else if (CurrentRow > 0)
1830 UpdateSelectionAfterCursorMove (shift_pressed);
1836 CurrentRow = RowsCount - 1;
1837 else if (CurrentRow < RowsCount - 1)
1839 else if (CurrentRow == RowsCount - 1 && cursor_in_add_row && (add_row_changed || is_changing))
1841 else if (CurrentRow == RowsCount - 1 && !cursor_in_add_row && !shift_pressed)
1844 UpdateSelectionAfterCursorMove (shift_pressed);
1849 if (CurrentRow > VLargeChange)
1850 CurrentRow -= VLargeChange;
1854 UpdateSelectionAfterCursorMove (shift_pressed);
1859 if (CurrentRow < RowsCount - VLargeChange)
1860 CurrentRow += VLargeChange;
1862 CurrentRow = RowsCount - 1;
1864 UpdateSelectionAfterCursorMove (shift_pressed);
1870 CurrentCell = new DataGridCell (0, 0);
1874 UpdateSelectionAfterCursorMove (ctrl_pressed && shift_pressed);
1880 CurrentCell = new DataGridCell (RowsCount - 1, CurrentTableStyle.GridColumnStyles.Count - 1);
1882 CurrentColumn = CurrentTableStyle.GridColumnStyles.Count - 1;
1884 UpdateSelectionAfterCursorMove (ctrl_pressed && shift_pressed);
1889 foreach (int row in selected_rows.Keys) {
1890 ListManager.RemoveAt (row);
1892 selected_rows.Clear ();
1893 CalcAreasAndInvalidate ();
1898 return false; // message not processed
1901 protected override bool ProcessKeyPreview (ref Message m)
1903 if ((Msg)m.Msg == Msg.WM_KEYDOWN) {
1904 Keys key = (Keys) m.WParam.ToInt32 ();
1905 KeyEventArgs ke = new KeyEventArgs (key);
1906 if (ProcessGridKey (ke) == true) {
1911 return base.ProcessKeyPreview (ref m);
1914 protected bool ProcessTabKey (Keys keyData)
1919 public void ResetAlternatingBackColor ()
1921 grid_style.AlternatingBackColor = default_style.AlternatingBackColor;
1924 public override void ResetBackColor ()
1926 grid_style.BackColor = default_style.BackColor;
1929 public override void ResetForeColor ()
1931 base.ResetForeColor ();
1934 public void ResetGridLineColor ()
1936 grid_style.GridLineColor = default_style.GridLineColor;
1939 public void ResetHeaderBackColor ()
1941 grid_style.HeaderBackColor = default_style.HeaderBackColor;
1944 public void ResetHeaderFont ()
1946 grid_style.HeaderFont = default_style.HeaderFont;
1949 public void ResetHeaderForeColor ()
1951 grid_style.HeaderForeColor = default_style.HeaderForeColor;
1954 public void ResetLinkColor ()
1956 grid_style.LinkColor = default_style.LinkColor;
1959 public void ResetLinkHoverColor ()
1961 grid_style.LinkHoverColor = default_style.LinkHoverColor;
1964 protected void ResetSelection ()
1966 InvalidateSelection ();
1967 selected_rows.Clear ();
1968 selection_start = -1;
1971 void InvalidateSelection ()
1973 foreach (int row in selected_rows.Keys) {
1974 rows[row].IsSelected = false;
1975 InvalidateRow (row);
1979 public void ResetSelectionBackColor ()
1981 grid_style.SelectionBackColor = default_style.SelectionBackColor;
1984 public void ResetSelectionForeColor ()
1986 grid_style.SelectionForeColor = default_style.SelectionForeColor;
1989 public void Select (int row)
1991 if (selected_rows.Count == 0)
1992 selection_start = row;
1994 selected_rows[row] = true;
1995 rows[row].IsSelected = true;
1997 InvalidateRow (row);
2000 public void SetDataBinding (object dataSource, string dataMember)
2002 SetDataSource (dataSource, dataMember);
2005 protected virtual bool ShouldSerializeAlternatingBackColor ()
2007 return (grid_style.AlternatingBackColor != default_style.AlternatingBackColor);
2010 protected virtual bool ShouldSerializeBackgroundColor ()
2012 return (background_color != def_background_color);
2015 protected virtual bool ShouldSerializeCaptionBackColor ()
2017 return (caption_backcolor != def_caption_backcolor);
2020 protected virtual bool ShouldSerializeCaptionForeColor ()
2022 return caption_forecolor != def_caption_forecolor;
2025 protected virtual bool ShouldSerializeGridLineColor ()
2027 return grid_style.GridLineColor != default_style.GridLineColor;
2030 protected virtual bool ShouldSerializeHeaderBackColor ()
2032 return grid_style.HeaderBackColor != default_style.HeaderBackColor;
2035 protected bool ShouldSerializeHeaderFont ()
2037 return grid_style.HeaderFont != default_style.HeaderFont;
2040 protected virtual bool ShouldSerializeHeaderForeColor ()
2042 return grid_style.HeaderForeColor != default_style.HeaderForeColor;
2045 protected virtual bool ShouldSerializeLinkHoverColor ()
2047 return grid_style.LinkHoverColor != grid_style.LinkHoverColor;
2050 protected virtual bool ShouldSerializeParentRowsBackColor ()
2052 return parentrowsback_color != def_parentrowsback_color;
2055 protected virtual bool ShouldSerializeParentRowsForeColor ()
2057 return parentrowsback_color != def_parentrowsback_color;
2060 protected bool ShouldSerializePreferredRowHeight ()
2062 return grid_style.PreferredRowHeight != default_style.PreferredRowHeight;
2065 protected bool ShouldSerializeSelectionBackColor ()
2067 return grid_style.SelectionBackColor != default_style.SelectionBackColor;
2070 protected virtual bool ShouldSerializeSelectionForeColor ()
2072 return grid_style.SelectionForeColor != default_style.SelectionForeColor;
2075 public void SubObjectsSiteChange (bool site)
2079 public void UnSelect (int row)
2081 rows[row].IsSelected = false;
2082 selected_rows.Remove (row);
2083 InvalidateRow (row);
2085 #endregion // Public Instance Methods
2087 #region Private Instance Methods
2089 internal void CalcAreasAndInvalidate ()
2095 private void ConnectListManagerEvents ()
2097 list_manager.PositionChanged += new EventHandler (OnListManagerPositionChanged);
2098 list_manager.ItemChanged += new ItemChangedEventHandler (OnListManagerItemChanged);
2101 private void DisconnectListManagerEvents ()
2103 list_manager.PositionChanged -= new EventHandler (OnListManagerPositionChanged);
2104 list_manager.ItemChanged -= new ItemChangedEventHandler (OnListManagerItemChanged);
2107 private void EnsureCellVisibility (DataGridCell cell)
2109 if (cell.ColumnNumber <= first_visiblecolumn ||
2110 cell.ColumnNumber + 1 >= first_visiblecolumn + visiblecolumn_count) {
2112 first_visiblecolumn = GetFirstColumnForColumnVisibility (first_visiblecolumn, cell.ColumnNumber);
2113 int pixel = GetColumnStartingPixel (first_visiblecolumn);
2114 ScrollToColumnInPixels (pixel);
2115 horiz_scrollbar.Value = pixel;
2119 if (cell.RowNumber < first_visiblerow ||
2120 cell.RowNumber + 1 >= first_visiblerow + visiblerow_count) {
2122 if (cell.RowNumber + 1 >= first_visiblerow + visiblerow_count) {
2123 int old_first_visiblerow = first_visiblerow;
2124 first_visiblerow = 1 + cell.RowNumber - visiblerow_count;
2125 UpdateVisibleRowCount ();
2126 ScrollToRow (old_first_visiblerow, first_visiblerow);
2128 int old_first_visiblerow = first_visiblerow;
2129 first_visiblerow = cell.RowNumber;
2130 UpdateVisibleRowCount ();
2131 ScrollToRow (old_first_visiblerow, first_visiblerow);
2134 vert_scrollbar.Value = first_visiblerow;
2138 private void SetDataSource (object source, string member)
2140 SetDataSource (source, member, true);
2143 bool in_setdatasource;
2144 private void SetDataSource (object source, string member, bool recreate_rows)
2146 /* we need this bool flag to work around a
2147 * problem with OnBindingContextChanged. once
2148 * that stuff works properly, remove this
2150 if (in_setdatasource)
2152 in_setdatasource = true;
2155 if (datasource == source && member == datamember)
2159 if (source != null && source as IListSource != null && source as IList != null)
2160 throw new Exception ("Wrong complex data binding source");
2162 datasource = source;
2163 datamember = member;
2168 current_cell = new DataGridCell ();
2170 if (list_manager != null)
2171 DisconnectListManagerEvents ();
2173 list_manager = null;
2175 /* create the new list manager */
2176 if (BindingContext != null && datasource != null)
2177 list_manager = (CurrencyManager) BindingContext [datasource, datamember];
2179 if (list_manager != null)
2180 ConnectListManagerEvents ();
2182 if (list_manager != null) {
2183 string list_name = list_manager.GetListName (null);
2184 if (TableStyles[list_name] == null) {
2185 current_style.GridColumnStyles.Clear ();
2186 current_style.CreateColumnsForTable (false);
2188 else if (CurrentTableStyle.MappingName != list_name) {
2189 // If the style has been defined by the user, use it
2190 CurrentTableStyle = styles_collection[list_name];
2191 current_style.CreateColumnsForTable (true);
2194 current_style.CreateColumnsForTable (true);
2198 current_style.CreateColumnsForTable (false);
2200 /* reset first_visiblerow to 0 here before
2201 * doing anything that'll requires us to
2202 * figure out if we need a scrollbar. */
2203 vert_scrollbar.Value = 0;
2204 horiz_scrollbar.Value = 0;
2205 first_visiblerow = 0;
2208 RecreateDataGridRows (false);
2210 CalcAreasAndInvalidate ();
2212 in_setdatasource = false;
2214 OnDataSourceChanged (EventArgs.Empty);
2217 private void OnListManagerPositionChanged (object sender, EventArgs e)
2219 from_positionchanged_handler = true;
2220 CurrentRow = list_manager.Position;
2221 from_positionchanged_handler = false;
2224 void RecreateDataGridRows (bool recalc)
2226 DataGridRelationshipRow[] new_rows = new DataGridRelationshipRow[RowsCount + (ShowEditRow ? 1 : 0)];
2227 int start_index = 0;
2229 start_index = rows.Length;
2230 Array.Copy (rows, 0, new_rows, 0, rows.Length < new_rows.Length ? rows.Length : new_rows.Length);
2233 for (int i = start_index; i < new_rows.Length; i ++) {
2234 new_rows[i] = new DataGridRelationshipRow (this);
2235 new_rows[i].height = RowHeight;
2237 new_rows[i].VerticalOffset = new_rows[i-1].VerticalOffset + new_rows[i-1].Height;
2243 CalcAreasAndInvalidate ();
2246 internal void UpdateRowsFrom (DataGridRelationshipRow row)
2248 int start_index = Array.IndexOf (rows, row);
2249 if (start_index == -1)
2252 for (int i = start_index + 1; i < rows.Length; i ++) {
2253 rows[i].VerticalOffset = rows[i-1].VerticalOffset + rows[i-1].Height;
2256 CalcAreasAndInvalidate ();
2259 private void OnListManagerItemChanged (object sender, ItemChangedEventArgs e)
2261 if (e.Index == -1) {
2263 if (rows == null || RowsCount != rows.Length - (ShowEditRow ? 1 : 0))
2264 RecreateDataGridRows (true);
2267 InvalidateRow (e.Index);
2271 private void OnTableStylesCollectionChanged (object sender, CollectionChangeEventArgs e)
2273 if (ListManager == null)
2276 string list_name = ListManager.GetListName (null);
2278 case CollectionChangeAction.Add: {
2279 if (e.Element != null && String.Compare (list_name, ((DataGridTableStyle)e.Element).MappingName, true) == 0) {
2280 CurrentTableStyle = (DataGridTableStyle)e.Element;
2281 ((DataGridTableStyle) e.Element).CreateColumnsForTable (false);
2286 case CollectionChangeAction.Remove: {
2287 if (e.Element != null && String.Compare (list_name, ((DataGridTableStyle)e.Element).MappingName, true) == 0) {
2288 CurrentTableStyle = default_style;
2289 current_style.GridColumnStyles.Clear ();
2290 current_style.CreateColumnsForTable (false);
2296 case CollectionChangeAction.Refresh: {
2297 if (CurrentTableStyle == default_style
2298 || String.Compare (list_name, CurrentTableStyle.MappingName, true) != 0) {
2300 DataGridTableStyle style = styles_collection [list_name];
2301 if (style != null) {
2302 CurrentTableStyle = style;
2303 current_style.CreateColumnsForTable (false);
2306 CurrentTableStyle = default_style;
2307 current_style.GridColumnStyles.Clear ();
2308 current_style.CreateColumnsForTable (false);
2315 CalcAreasAndInvalidate ();
2318 private void AddNewRow ()
2320 ListManager.EndCurrentEdit ();
2321 ListManager.AddNew ();
2324 private void Edit ()
2326 if (CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber].bound == false)
2330 is_changing = false;
2332 CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber].Edit (ListManager,
2333 current_cell.RowNumber, GetCellBounds (current_cell.RowNumber, current_cell.ColumnNumber),
2334 _readonly, "", true);
2337 private void EndEdit ()
2339 if (CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber].bound == false)
2342 EndEdit (CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber],
2343 current_cell.RowNumber,
2347 private void ShiftSelection (int index)
2349 // we have to save off selection_start
2350 // because ResetSelection clobbers it
2351 int saved_selection_start = selection_start;
2355 selection_start = saved_selection_start;
2357 if (index >= selection_start) {
2358 start = selection_start;
2363 end = selection_start;
2366 for (int idx = start; idx <= end; idx ++) {
2371 private void ScrollToColumnInPixels (int pixel)
2375 if (pixel > horiz_pixeloffset) // ScrollRight
2376 pixels = -1 * (pixel - horiz_pixeloffset);
2378 pixels = horiz_pixeloffset - pixel;
2380 Rectangle area = cells_area;
2382 if (ColumnHeadersVisible == true) {
2383 area.Y -= ColumnHeadersArea.Height;
2384 area.Height += ColumnHeadersArea.Height;
2387 horiz_pixeloffset = pixel;
2388 UpdateVisibleColumn ();
2392 XplatUI.ScrollWindow (Handle, area, pixels, 0, false);
2394 int pixel_offset = GetColumnStartingPixel (CurrentColumn);
2395 int next_pixel_offset = pixel_offset + CurrentTableStyle.GridColumnStyles[CurrentColumn].Width;
2397 if (pixel_offset >= horiz_pixeloffset
2398 && next_pixel_offset < horiz_pixeloffset + cells_area.Width)
2402 private void ScrollToRow (int old_row, int new_row)
2407 if (new_row > old_row) { // Scrolldown
2408 for (i = old_row; i < new_row; i ++)
2409 pixels -= rows[i].Height;
2412 for (i = new_row; i < old_row; i ++)
2413 pixels += rows[i].Height;
2421 Rectangle rows_area = cells_area; // Cells area - partial rows space
2423 if (RowHeadersVisible) {
2424 rows_area.X -= RowHeaderWidth;
2425 rows_area.Width += RowHeaderWidth;
2428 /* scroll the window */
2429 XplatUI.ScrollWindow (Handle, rows_area, 0, pixels, false);
2431 /* if the row is still */
2432 if (CurrentRow >= first_visiblerow && CurrentRow < first_visiblerow + visiblerow_count)
2436 #endregion Private Instance Methods
2440 public event EventHandler AllowNavigationChanged;
2441 public event EventHandler BackButtonClick;
2442 public event EventHandler BackgroundColorChanged;
2445 [EditorBrowsable(EditorBrowsableState.Never)]
2446 public new event EventHandler BackgroundImageChanged {
2447 add { base.BackgroundImageChanged += value; }
2448 remove { base.BackgroundImageChanged -= value; }
2452 [EditorBrowsable(EditorBrowsableState.Never)]
2453 public new event EventHandler TextChanged {
2454 add { base.TextChanged += value; }
2455 remove { base.TextChanged -= value; }
2459 [EditorBrowsable(EditorBrowsableState.Never)]
2460 public new event EventHandler CursorChanged {
2461 add { base.CursorChanged += value; }
2462 remove { base.CursorChanged -= value; }
2465 public event EventHandler BorderStyleChanged;
2466 public event EventHandler CaptionVisibleChanged;
2467 public event EventHandler CurrentCellChanged;
2468 public event EventHandler DataSourceChanged;
2469 public event EventHandler FlatModeChanged;
2470 public event NavigateEventHandler Navigate;
2471 public event EventHandler ParentRowsLabelStyleChanged;
2472 public event EventHandler ParentRowsVisibleChanged;
2473 public event EventHandler ReadOnlyChanged;
2474 protected event EventHandler RowHeaderClick;
2475 public event EventHandler Scroll;
2476 public event EventHandler ShowParentDetailsButtonClick;
2478 #endregion // Events
2483 #region Code originally in DataGridDrawingLogic.cs
2485 #region Local Variables
2488 Rectangle parent_rows;
2489 int width_of_all_columns;
2491 internal Rectangle caption_area;
2492 internal Rectangle columnhdrs_area; // Used columns header area
2493 internal int columnhdrs_maxwidth; // Total width (max width) for columns headrs
2494 internal Rectangle rowhdrs_area; // Used Headers rows area
2495 internal Rectangle cells_area;
2496 #endregion // Local Variables
2499 #region Public Instance Methods
2501 // Calc the max with of all columns
2502 int CalcAllColumnsWidth ()
2505 int cnt = CurrentTableStyle.GridColumnStyles.Count;
2507 for (int col = 0; col < cnt; col++) {
2508 if (CurrentTableStyle.GridColumnStyles[col].bound == false) {
2511 width += CurrentTableStyle.GridColumnStyles[col].Width;
2516 // Gets a column from a pixel
2517 int FromPixelToColumn (int pixel, out int column_x)
2520 int cnt = CurrentTableStyle.GridColumnStyles.Count;
2526 if (CurrentTableStyle.CurrentRowHeadersVisible) {
2527 width += rowhdrs_area.X + rowhdrs_area.Width;
2528 column_x += rowhdrs_area.X + rowhdrs_area.Width;
2531 for (int col = 0; col < cnt; col++) {
2532 if (CurrentTableStyle.GridColumnStyles[col].bound == false)
2535 width += CurrentTableStyle.GridColumnStyles[col].Width;
2540 column_x += CurrentTableStyle.GridColumnStyles[col].Width;
2546 internal int GetColumnStartingPixel (int my_col)
2549 int cnt = CurrentTableStyle.GridColumnStyles.Count;
2551 for (int col = 0; col < cnt; col++) {
2552 if (CurrentTableStyle.GridColumnStyles[col].bound == false) {
2559 width += CurrentTableStyle.GridColumnStyles[col].Width;
2565 // Which column has to be the first visible column to ensure a column visibility
2566 int GetFirstColumnForColumnVisibility (int current_first_visiblecolumn, int column)
2568 int new_col = column;
2571 if (column > current_first_visiblecolumn) { // Going forward
2572 for (new_col = column; new_col >= 0; new_col--){
2573 if (CurrentTableStyle.GridColumnStyles[new_col].bound == false)
2575 width += CurrentTableStyle.GridColumnStyles[new_col].Width;
2577 if (width >= cells_area.Width)
2579 //return new_col < CurrentTableStyle.GridColumnStyles.Count ? new_col + 1 : CurrentTableStyle.GridColumnStyles.Count;
2587 bool in_calc_grid_areas;
2588 void CalcGridAreas ()
2590 if (IsHandleCreated == false) // Delay calculations until the handle is created
2593 /* make sure we don't happen to end up in this method again */
2594 if (in_calc_grid_areas)
2597 in_calc_grid_areas = true;
2599 /* Order is important. E.g. row headers max. height depends on caption */
2600 horiz_pixeloffset = 0;
2603 CalcParentButtons ();
2604 UpdateVisibleRowCount ();
2606 width_of_all_columns = CalcAllColumnsWidth ();
2607 CalcColumnHeaders ();
2610 bool needHoriz = false;
2611 bool needVert = false;
2613 /* figure out which scrollbars we need, and what the visible areas are */
2614 int visible_cells_width = cells_area.Width;
2615 int visible_cells_height = cells_area.Height;
2616 int allrows = RowsCount;
2618 if (ShowEditRow && RowsCount > 0)
2621 /* use a loop to iteratively calculate whether
2622 * we need horiz/vert scrollbars. */
2623 for (int i = 0; i < 3; i ++) {
2625 visible_cells_width = cells_area.Width - vert_scrollbar.Width;
2627 visible_cells_height = cells_area.Height - horiz_scrollbar.Height;
2629 UpdateVisibleRowCount ();
2631 needHoriz = (width_of_all_columns > visible_cells_width);
2632 needVert = (allrows > visiblerow_count);
2635 int horiz_scrollbar_width = ClientRectangle.Width;
2636 int horiz_scrollbar_maximum = 0;
2637 int vert_scrollbar_height = 0;
2638 int vert_scrollbar_maximum = 0;
2641 SetUpVerticalScrollBar (out vert_scrollbar_height, out vert_scrollbar_maximum);
2644 SetUpHorizontalScrollBar (out horiz_scrollbar_maximum);
2646 cells_area.Width = visible_cells_width;
2647 cells_area.Height = visible_cells_height;
2649 if (needVert && needHoriz) {
2651 parent_rows.Width -= vert_scrollbar.Width;
2653 if (!ShowingColumnHeaders) {
2654 if (columnhdrs_area.X + columnhdrs_area.Width > vert_scrollbar.Location.X) {
2655 columnhdrs_area.Width -= vert_scrollbar.Width;
2659 horiz_scrollbar_width -= vert_scrollbar.Width;
2660 vert_scrollbar_height -= horiz_scrollbar.Height;
2664 if (rowhdrs_area.Y + rowhdrs_area.Height > ClientRectangle.Y + ClientRectangle.Height) {
2665 rowhdrs_area.Height -= horiz_scrollbar.Height;
2668 vert_scrollbar.Size = new Size (vert_scrollbar.Width,
2669 vert_scrollbar_height);
2671 vert_scrollbar.Maximum = vert_scrollbar_maximum;
2672 Controls.Add (vert_scrollbar);
2673 vert_scrollbar.Visible = true;
2676 Controls.Remove (vert_scrollbar);
2677 vert_scrollbar.Visible = false;
2681 horiz_scrollbar.Size = new Size (horiz_scrollbar_width,
2682 horiz_scrollbar.Height);
2684 horiz_scrollbar.Maximum = horiz_scrollbar_maximum;
2685 Controls.Add (horiz_scrollbar);
2686 horiz_scrollbar.Visible = true;
2689 Controls.Remove (horiz_scrollbar);
2690 horiz_scrollbar.Visible = false;
2693 UpdateVisibleColumn ();
2694 UpdateVisibleRowCount ();
2696 in_calc_grid_areas = false;
2701 caption_area.X = ClientRectangle.X;
2702 caption_area.Y = ClientRectangle.Y;
2703 caption_area.Width = ClientRectangle.Width;
2704 if (caption_visible) {
2705 caption_area.Height = CaptionFont.Height;
2706 if (caption_area.Height < back_button_image.Height)
2707 caption_area.Height = back_button_image.Height;
2708 caption_area.Height += 6;
2711 caption_area.Height = 0;
2714 void CalcCellsArea ()
2716 cells_area.X = ClientRectangle.X + rowhdrs_area.Width;
2717 cells_area.Y = columnhdrs_area.Y + columnhdrs_area.Height;
2718 cells_area.Width = ClientRectangle.X + ClientRectangle.Width - cells_area.X;
2719 cells_area.Height = ClientRectangle.Y + ClientRectangle.Height - cells_area.Y;
2722 void CalcColumnHeaders ()
2726 columnhdrs_area.X = ClientRectangle.X;
2727 columnhdrs_area.Y = parent_rows.Y + parent_rows.Height;
2729 // TODO: take into account Scrollbars
2730 columnhdrs_maxwidth = ClientRectangle.X + ClientRectangle.Width - columnhdrs_area.X;
2731 max_width_cols = columnhdrs_maxwidth;
2733 if (CurrentTableStyle.CurrentRowHeadersVisible)
2734 max_width_cols -= RowHeaderWidth;
2736 if (width_of_all_columns > max_width_cols) {
2737 columnhdrs_area.Width = columnhdrs_maxwidth;
2739 columnhdrs_area.Width = width_of_all_columns;
2741 if (CurrentTableStyle.CurrentRowHeadersVisible)
2742 columnhdrs_area.Width += RowHeaderWidth;
2745 if (ShowingColumnHeaders)
2746 columnhdrs_area.Height = CurrentTableStyle.HeaderFont.Height + 6;
2748 columnhdrs_area.Height = 0;
2751 void CalcParentRows ()
2753 parent_rows.X = ClientRectangle.X;
2754 parent_rows.Y = caption_area.Y + caption_area.Height;
2755 parent_rows.Width = ClientRectangle.Width;
2757 parent_rows.Height = (CaptionFont.Height + 3) * dataSourceStack.Count;
2759 parent_rows.Height = 0;
2762 void CalcParentButtons ()
2764 if (dataSourceStack.Count > 0 && CaptionVisible) {
2765 back_button_rect = new Rectangle (ClientRectangle.X + ClientRectangle.Width - 2 * (caption_area.Height - 2) - 8,
2766 caption_area.Height / 2 - back_button_image.Height / 2,
2767 back_button_image.Width, back_button_image.Height);
2768 parent_rows_button_rect = new Rectangle (ClientRectangle.X + ClientRectangle.Width - (caption_area.Height - 2) - 4,
2769 caption_area.Height / 2 - parent_rows_button_image.Height / 2,
2770 parent_rows_button_image.Width, parent_rows_button_image.Height);
2773 back_button_rect = parent_rows_button_rect = Rectangle.Empty;
2778 void CalcRowHeaders ()
2780 rowhdrs_area.X = ClientRectangle.X;
2781 rowhdrs_area.Y = columnhdrs_area.Y + columnhdrs_area.Height;
2782 rowhdrs_area.Height = ClientRectangle.Height + ClientRectangle.Y - rowhdrs_area.Y;
2784 if (CurrentTableStyle.CurrentRowHeadersVisible)
2785 rowhdrs_area.Width = RowHeaderWidth;
2787 rowhdrs_area.Width = 0;
2790 int GetVisibleRowCount (int visibleHeight)
2792 int rows_height = 0;
2794 for (r = FirstVisibleRow; r < rows.Length; r ++) {
2795 if (rows_height + rows[r].Height >= visibleHeight)
2797 rows_height += rows[r].Height;
2800 if (r < rows.Length - 1)
2803 return r - FirstVisibleRow;
2806 void UpdateVisibleColumn ()
2808 if (CurrentTableStyle.GridColumnStyles.Count == 0) {
2809 visiblecolumn_count = 0;
2814 int max_pixel = horiz_pixeloffset + cells_area.Width;
2817 first_visiblecolumn = FromPixelToColumn (horiz_pixeloffset, out unused);
2819 col = FromPixelToColumn (max_pixel, out unused);
2821 visiblecolumn_count = 1 + col - first_visiblecolumn;
2823 visiblecolumn_count = 0;
2824 for (int i = first_visiblecolumn; i <= col; i ++) {
2825 if (CurrentTableStyle.GridColumnStyles[i].bound)
2826 visiblecolumn_count++;
2829 if (first_visiblecolumn + visiblecolumn_count < CurrentTableStyle.GridColumnStyles.Count) {
2830 visiblecolumn_count++; // Partially visible column
2834 void UpdateVisibleRowCount ()
2836 visiblerow_count = GetVisibleRowCount (cells_area.Height);
2838 CalcRowHeaders (); // Height depends on num of visible rows
2842 void InvalidateCaption ()
2844 if (caption_area.IsEmpty)
2847 Invalidate (caption_area);
2850 void InvalidateRow (int row)
2852 if (row < FirstVisibleRow || row > FirstVisibleRow + VisibleRowCount)
2855 Rectangle rect_row = new Rectangle ();
2857 rect_row.X = cells_area.X;
2858 rect_row.Width = width_of_all_columns;
2859 if (rect_row.Width > cells_area.Width)
2860 rect_row.Width = cells_area.Width;
2861 rect_row.Height = rows[row].Height;
2862 rect_row.Y = cells_area.Y + rows[row].VerticalOffset - rows[FirstVisibleRow].VerticalOffset;
2863 Invalidate (rect_row);
2866 void InvalidateRowHeader (int row)
2868 Rectangle rect_rowhdr = new Rectangle ();
2869 rect_rowhdr.X = rowhdrs_area.X;
2870 rect_rowhdr.Width = rowhdrs_area.Width;
2871 rect_rowhdr.Height = rows[row].Height;
2872 rect_rowhdr.Y = rowhdrs_area.Y + rows[row].VerticalOffset - rows[FirstVisibleRow].VerticalOffset;
2873 Invalidate (rect_rowhdr);
2876 internal void InvalidateColumn (DataGridColumnStyle column)
2878 Rectangle rect_col = new Rectangle ();
2882 col = CurrentTableStyle.GridColumnStyles.IndexOf (column);
2887 rect_col.Width = column.Width;
2888 col_pixel = GetColumnStartingPixel (col);
2889 rect_col.X = cells_area.X + col_pixel - horiz_pixeloffset;
2890 rect_col.Y = cells_area.Y;
2891 rect_col.Height = cells_area.Height;
2892 Invalidate (rect_col);
2895 void DrawResizeLineVert (int x)
2897 XplatUI.DrawReversibleRectangle (Handle,
2898 new Rectangle (x, cells_area.Y, 1, cells_area.Height - 3),
2902 void DrawResizeLineHoriz (int y)
2904 XplatUI.DrawReversibleRectangle (Handle,
2905 new Rectangle (cells_area.X, y, cells_area.Width - 3, 1),
2909 void SetUpHorizontalScrollBar (out int maximum)
2911 maximum = width_of_all_columns;
2913 horiz_scrollbar.Location = new Point (ClientRectangle.X, ClientRectangle.Y +
2914 ClientRectangle.Height - horiz_scrollbar.Height);
2916 horiz_scrollbar.LargeChange = cells_area.Width;
2920 void SetUpVerticalScrollBar (out int height, out int maximum)
2924 y = ClientRectangle.Y + parent_rows.Y + parent_rows.Height;
2925 height = ClientRectangle.Height - parent_rows.Y - parent_rows.Height;
2927 vert_scrollbar.Location = new Point (ClientRectangle.X +
2928 ClientRectangle.Width - vert_scrollbar.Width, y);
2930 maximum = RowsCount;
2932 if (ShowEditRow && RowsCount > 0) {
2936 vert_scrollbar.LargeChange = VLargeChange;
2939 #endregion // Public Instance Methods
2941 #region Instance Properties
2942 // Returns the ColumnHeaders area excluding the rectangle shared with RowHeaders
2943 internal Rectangle ColumnHeadersArea {
2945 Rectangle columns_area = columnhdrs_area;
2947 if (CurrentTableStyle.CurrentRowHeadersVisible) {
2948 columns_area.X += RowHeaderWidth;
2949 columns_area.Width -= RowHeaderWidth;
2951 return columns_area;
2955 bool ShowingColumnHeaders {
2956 get { return ColumnHeadersVisible && CurrentTableStyle.GridColumnStyles.Count > 0; }
2959 internal Rectangle RowHeadersArea {
2960 get { return rowhdrs_area; }
2963 internal Rectangle ParentRowsArea {
2964 get { return parent_rows; }
2968 get { return VisibleRowCount; }
2971 #endregion Instance Properties
2973 #endregion // Code originally in DataGridDrawingLogic.cs