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>
29 using System.ComponentModel;
32 using System.Runtime.InteropServices;
33 using System.Collections;
36 namespace System.Windows.Forms
38 internal class DataGridRelationshipRow {
41 public DataGridRelationshipRow (DataGrid owner)
49 relation_area = Rectangle.Empty;
54 /* this needs to be a property so that the Autosize
55 * example from the Windows.Forms FAQ will work */
57 get { return height; }
59 if (height != value) {
61 owner.UpdateRowsFrom (this);
66 public bool IsSelected;
67 public bool IsExpanded;
68 public int VerticalOffset;
69 public int RelationHeight;
70 public Rectangle relation_area; /* the Y coordinate of this rectangle is updated as needed */
73 internal class DataGridDataSource
75 public DataGrid owner;
76 public CurrencyManager list_manager;
78 public string data_member;
79 public object data_source;
80 public DataGridCell current;
82 public DataGridDataSource (DataGrid owner, CurrencyManager list_manager, object data_source, string data_member, object view_data, DataGridCell current)
85 this.list_manager = list_manager;
86 this.view = view_data;
87 this.data_source = data_source;
88 this.data_member = data_member;
89 this.current = current;
92 DataGridRelationshipRow[] rows;
93 public DataGridRelationshipRow[] Rows {
98 Hashtable selected_rows;
99 public Hashtable SelectedRows {
100 get { return selected_rows; }
101 set { selected_rows = value; }
105 public int SelectionStart {
106 get { return selection_start; }
107 set { selection_start = value; }
111 [DefaultEvent("Navigate")]
112 [DefaultProperty("DataSource")]
113 [Designer("System.Windows.Forms.Design.DataGridDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
115 [ComplexBindingProperties ("DataSource", "DataMember")]
116 [ClassInterface (ClassInterfaceType.AutoDispatch)]
119 public class DataGrid : Control, ISupportInitialize, IDataGridEditingService
125 public enum HitTestType
137 public sealed class HitTestInfo
139 public static readonly HitTestInfo Nowhere = null;
143 DataGrid.HitTestType type;
145 #region Private Constructors
146 internal HitTestInfo () : this (-1, -1, HitTestType.None)
150 internal HitTestInfo (int row, int column, DataGrid.HitTestType type)
153 this.column = column;
159 #region Public Instance Properties
161 get { return column; }
167 public DataGrid.HitTestType Type {
170 #endregion //Public Instance Properties
172 public override bool Equals (object o)
174 if (!(o is HitTestInfo))
177 HitTestInfo obj = (HitTestInfo) o;
178 return (obj.Column == column && obj.Row == row && obj.Type ==type);
181 public override int GetHashCode ()
186 public override string ToString ()
188 return "{ " + type + "," + row + "," + column + "}";
193 #region Local Variables
194 /* cached theme defaults */
195 static readonly Color def_background_color = ThemeEngine.Current.DataGridBackgroundColor;
196 static readonly Color def_caption_backcolor = ThemeEngine.Current.DataGridCaptionBackColor;
197 static readonly Color def_caption_forecolor = ThemeEngine.Current.DataGridCaptionForeColor;
198 static readonly Color def_parent_rows_backcolor = ThemeEngine.Current.DataGridParentRowsBackColor;
199 static readonly Color def_parent_rows_forecolor = ThemeEngine.Current.DataGridParentRowsForeColor;
202 // XXX this needs addressing. Control.background_color should not be internal.
203 new Color background_color;
204 Color caption_backcolor;
205 Color caption_forecolor;
206 Color parent_rows_backcolor;
207 Color parent_rows_forecolor;
209 /* flags to determine which areas of the datagrid are shown */
210 bool caption_visible;
211 bool parent_rows_visible;
213 GridTableStylesCollection styles_collection;
214 DataGridParentRowsLabelStyle parent_rows_label_style;
215 DataGridTableStyle default_style;
216 DataGridTableStyle grid_style;
217 DataGridTableStyle current_style;
220 DataGridCell current_cell;
221 Hashtable selected_rows;
222 int selection_start; // used for range selection
224 /* layout/rendering */
225 bool allow_navigation;
226 int first_visible_row;
227 int first_visible_column;
228 int visible_row_count;
229 int visible_column_count;
233 HScrollBar horiz_scrollbar;
234 VScrollBar vert_scrollbar;
235 int horiz_pixeloffset;
237 internal Bitmap back_button_image;
238 internal Rectangle back_button_rect;
239 internal bool back_button_mouseover;
240 internal bool back_button_active;
241 internal Bitmap parent_rows_button_image;
242 internal Rectangle parent_rows_button_rect;
243 internal bool parent_rows_button_mouseover;
244 internal bool parent_rows_button_active;
249 CurrencyManager list_manager;
250 bool refetch_list_manager = true;
252 DataGridRelationshipRow[] rows;
254 /* column resize fields */
255 bool column_resize_active;
257 int resize_column_width_delta;
260 /* row resize fields */
261 bool row_resize_active;
263 int resize_row_height_delta;
266 /* used to make sure we don't endlessly recurse calling set_CurrentCell and OnListManagerPositionChanged */
267 bool from_positionchanged_handler;
270 bool cursor_in_add_row;
271 bool add_row_changed;
272 bool is_editing; // Current cell is edit mode
275 internal Stack data_source_stack;
277 #endregion // Local Variables
279 #region Public Constructors
282 allow_navigation = true;
283 background_color = def_background_color;
284 border_style = BorderStyle.Fixed3D;
285 caption_backcolor = def_caption_backcolor;
286 caption_forecolor = def_caption_forecolor;
287 caption_text = string.Empty;
288 caption_visible = true;
289 datamember = string.Empty;
290 parent_rows_backcolor = def_parent_rows_backcolor;
291 parent_rows_forecolor = def_parent_rows_forecolor;
292 parent_rows_visible = true;
293 current_cell = new DataGridCell ();
294 parent_rows_label_style = DataGridParentRowsLabelStyle.Both;
295 selected_rows = new Hashtable ();
296 selection_start = -1;
297 rows = new DataGridRelationshipRow [0];
299 default_style = new DataGridTableStyle (true);
300 grid_style = new DataGridTableStyle ();
302 styles_collection = new GridTableStylesCollection (this);
303 styles_collection.CollectionChanged += new CollectionChangeEventHandler (OnTableStylesCollectionChanged);
305 CurrentTableStyle = grid_style;
307 horiz_scrollbar = new ImplicitHScrollBar ();
308 horiz_scrollbar.Scroll += new ScrollEventHandler (GridHScrolled);
309 vert_scrollbar = new ImplicitVScrollBar ();
310 vert_scrollbar.Scroll += new ScrollEventHandler (GridVScrolled);
312 SetStyle (ControlStyles.UserMouse, true);
314 data_source_stack = new Stack ();
316 back_button_image = ResourceImageLoader.Get ("go-previous.png");
317 //back_button_image.MakeTransparent (Color.Transparent);
318 parent_rows_button_image = ResourceImageLoader.Get ("go-top.png");
319 //parent_rows_button_image.MakeTransparent (Color.Transparent);
322 #endregion // Public Constructor
324 #region Public Instance Properties
327 public bool AllowNavigation {
328 get { return allow_navigation; }
330 if (allow_navigation != value) {
331 allow_navigation = value;
332 OnAllowNavigationChanged (EventArgs.Empty);
338 public bool AllowSorting {
339 get { return grid_style.AllowSorting; }
340 set { grid_style.AllowSorting = value; }
343 public Color AlternatingBackColor {
344 get { return grid_style.AlternatingBackColor; }
345 set { grid_style.AlternatingBackColor = value; }
348 public override Color BackColor {
349 get { return grid_style.BackColor; }
350 set { grid_style.BackColor = value; }
353 public Color BackgroundColor {
354 get { return background_color; }
356 if (background_color != value) {
357 background_color = value;
358 OnBackgroundColorChanged (EventArgs.Empty);
365 [EditorBrowsable(EditorBrowsableState.Never)]
366 public override Image BackgroundImage {
367 get { return base.BackgroundImage; }
369 if (base.BackgroundImage == value)
372 base.BackgroundImage = value;
378 [DefaultValue(BorderStyle.Fixed3D)]
379 public BorderStyle BorderStyle {
380 get { return InternalBorderStyle; }
382 InternalBorderStyle = value;
383 CalcAreasAndInvalidate ();
384 OnBorderStyleChanged (EventArgs.Empty);
388 public Color CaptionBackColor {
389 get { return caption_backcolor; }
391 if (caption_backcolor != value) {
392 caption_backcolor = value;
393 InvalidateCaption ();
400 public Font CaptionFont {
402 if (caption_font == null)
403 return new Font (Font, FontStyle.Bold);
408 if (caption_font != null && caption_font.Equals (value))
411 caption_font = value;
412 CalcAreasAndInvalidate ();
416 public Color CaptionForeColor {
417 get { return caption_forecolor; }
419 if (caption_forecolor != value) {
420 caption_forecolor = value;
421 InvalidateCaption ();
428 public string CaptionText {
429 get { return caption_text; }
431 if (caption_text != value) {
432 caption_text = value;
433 InvalidateCaption ();
439 public bool CaptionVisible {
440 get { return caption_visible; }
442 if (caption_visible != value) {
444 caption_visible = value;
445 CalcAreasAndInvalidate ();
446 OnCaptionVisibleChanged (EventArgs.Empty);
452 public bool ColumnHeadersVisible {
453 get { return grid_style.ColumnHeadersVisible; }
454 set { grid_style.ColumnHeadersVisible = value; }
457 bool setting_current_cell;
460 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
461 public DataGridCell CurrentCell {
462 get { return current_cell; }
464 if (setting_current_cell)
466 setting_current_cell = true;
468 if (!IsHandleCreated) {
469 setting_current_cell = false;
470 throw new Exception ("CurrentCell cannot be set at this time.");
473 if (current_cell.Equals (value)) {
474 setting_current_cell = false;
478 /* make sure the new cell fits in the correct bounds for [row,column] */
479 if (ReadOnly && value.RowNumber > RowsCount - 1)
480 value.RowNumber = RowsCount - 1;
481 else if (value.RowNumber > RowsCount)
482 value.RowNumber = RowsCount;
483 if (value.ColumnNumber >= CurrentTableStyle.GridColumnStyles.Count)
484 value.ColumnNumber = CurrentTableStyle.GridColumnStyles.Count == 0 ? 0 : CurrentTableStyle.GridColumnStyles.Count - 1;
486 bool was_changing = is_changing;
488 add_row_changed = add_row_changed || was_changing;
491 if (value.RowNumber != current_cell.RowNumber) {
492 if (!from_positionchanged_handler) {
494 ListManager.EndCurrentEdit ();
496 catch (Exception e) {
497 DialogResult r = MessageBox.Show (String.Format ("{0} Do you wish to correct the value?", e.Message),
498 "Error when committing the row to the original data source",
499 MessageBoxButtons.YesNo);
500 if (r == DialogResult.Yes) {
505 ListManager.CancelCurrentEdit ();
509 if (value.RowNumber == RowsCount && !ListManager.CanAddRows)
513 int old_row = current_cell.RowNumber;
515 current_cell = value;
517 EnsureCellVisibility (value);
519 if (CurrentRow == RowsCount && ListManager.CanAddRows) {
520 cursor_in_add_row = true;
521 add_row_changed = false;
525 cursor_in_add_row = false;
528 InvalidateRowHeader (old_row);
529 InvalidateRowHeader (current_cell.RowNumber);
531 list_manager.Position = current_cell.RowNumber;
533 OnCurrentCellChanged (EventArgs.Empty);
535 if (!from_positionchanged_handler)
538 setting_current_cell = false;
543 get { return current_cell.RowNumber; }
544 set { CurrentCell = new DataGridCell (value, current_cell.ColumnNumber); }
548 get { return current_cell.ColumnNumber; }
549 set { CurrentCell = new DataGridCell (current_cell.RowNumber, value); }
553 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
554 public int CurrentRowIndex {
556 if (ListManager == null)
561 set { CurrentRow = value; }
565 [EditorBrowsable(EditorBrowsableState.Never)]
566 public override Cursor Cursor {
567 get { return base.Cursor; }
568 set { base.Cursor = value; }
572 [Editor ("System.Windows.Forms.Design.DataMemberListEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
573 public string DataMember {
574 get { return datamember; }
576 if (BindingContext != null) {
577 SetDataSource (datasource, value);
580 if (list_manager != null)
583 refetch_list_manager = true;
589 [RefreshProperties(RefreshProperties.Repaint)]
591 [AttributeProvider (typeof (IListSource))]
593 [TypeConverter("System.Windows.Forms.Design.DataSourceConverter, " + Consts.AssemblySystem_Design)]
595 public object DataSource {
596 get { return datasource; }
598 if (BindingContext != null) {
599 SetDataSource (value, ListManager == null ? datamember : string.Empty);
603 if (list_manager != null)
604 datamember = string.Empty;
606 if (list_manager != null)
608 refetch_list_manager = true;
613 protected override Size DefaultSize {
614 get { return new Size (130, 80); }
618 public int FirstVisibleColumn {
619 get { return first_visible_column; }
622 [DefaultValue(false)]
623 public bool FlatMode {
624 get { return flatmode; }
626 if (flatmode != value) {
628 OnFlatModeChanged (EventArgs.Empty);
634 public override Color ForeColor {
635 get { return grid_style.ForeColor; }
636 set { grid_style.ForeColor = value; }
639 public Color GridLineColor {
640 get { return grid_style.GridLineColor; }
642 if (value == Color.Empty)
643 throw new ArgumentException ("Color.Empty value is invalid.");
645 grid_style.GridLineColor = value;
649 [DefaultValue(DataGridLineStyle.Solid)]
650 public DataGridLineStyle GridLineStyle {
651 get { return grid_style.GridLineStyle; }
652 set { grid_style.GridLineStyle = value; }
655 public Color HeaderBackColor {
656 get { return grid_style.HeaderBackColor; }
658 if (value == Color.Empty)
659 throw new ArgumentException ("Color.Empty value is invalid.");
661 grid_style.HeaderBackColor = value;
665 public Font HeaderFont {
666 get { return grid_style.HeaderFont; }
667 set { grid_style.HeaderFont = value; }
670 public Color HeaderForeColor {
671 get { return grid_style.HeaderForeColor; }
672 set { grid_style.HeaderForeColor = value; }
675 protected ScrollBar HorizScrollBar {
676 get { return horiz_scrollbar; }
678 internal ScrollBar HScrollBar {
679 get { return horiz_scrollbar; }
682 internal int HorizPixelOffset {
683 get { return horiz_pixeloffset; }
686 internal bool IsChanging {
687 get { return is_changing; }
690 public object this [DataGridCell cell] {
691 get { return this [cell.RowNumber, cell.ColumnNumber]; }
692 set { this [cell.RowNumber, cell.ColumnNumber] = value; }
695 public object this [int rowIndex, int columnIndex] {
696 get { return CurrentTableStyle.GridColumnStyles[columnIndex].GetColumnValueAtRow (ListManager,
698 set { CurrentTableStyle.GridColumnStyles[columnIndex].SetColumnValueAtRow (ListManager,
702 public Color LinkColor {
703 get { return grid_style.LinkColor; }
704 set { grid_style.LinkColor = value; }
707 internal Font LinkFont {
708 get { return new Font (Font, FontStyle.Underline); }
715 [EditorBrowsable(EditorBrowsableState.Never)]
716 public Color LinkHoverColor {
717 get { return grid_style.LinkHoverColor; }
718 set { grid_style.LinkHoverColor = value; }
722 [EditorBrowsable(EditorBrowsableState.Advanced)]
723 protected internal CurrencyManager ListManager {
725 if (list_manager == null && refetch_list_manager) {
726 SetDataSource (datasource, datamember);
727 refetch_list_manager = false;
732 set { throw new NotSupportedException ("Operation is not supported."); }
735 public Color ParentRowsBackColor {
736 get { return parent_rows_backcolor; }
738 if (parent_rows_backcolor != value) {
739 parent_rows_backcolor = value;
740 if (parent_rows_visible) {
747 public Color ParentRowsForeColor {
748 get { return parent_rows_forecolor; }
750 if (parent_rows_forecolor != value) {
751 parent_rows_forecolor = value;
752 if (parent_rows_visible) {
759 [DefaultValue(DataGridParentRowsLabelStyle.Both)]
760 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
761 public DataGridParentRowsLabelStyle ParentRowsLabelStyle {
762 get { return parent_rows_label_style; }
764 if (parent_rows_label_style != value) {
765 parent_rows_label_style = value;
766 if (parent_rows_visible) {
770 OnParentRowsLabelStyleChanged (EventArgs.Empty);
776 public bool ParentRowsVisible {
777 get { return parent_rows_visible; }
779 if (parent_rows_visible != value) {
780 parent_rows_visible = value;
781 CalcAreasAndInvalidate ();
782 OnParentRowsVisibleChanged (EventArgs.Empty);
787 // Settting this property seems to have no effect.
789 [TypeConverter(typeof(DataGridPreferredColumnWidthTypeConverter))]
790 public int PreferredColumnWidth {
791 get { return grid_style.PreferredColumnWidth; }
792 set { grid_style.PreferredColumnWidth = value; }
795 public int PreferredRowHeight {
796 get { return grid_style.PreferredRowHeight; }
797 set { grid_style.PreferredRowHeight = value; }
800 [DefaultValue(false)]
801 public bool ReadOnly {
802 get { return _readonly; }
804 if (_readonly != value) {
806 OnReadOnlyChanged (EventArgs.Empty);
807 CalcAreasAndInvalidate ();
813 public bool RowHeadersVisible {
814 get { return grid_style.RowHeadersVisible; }
815 set { grid_style.RowHeadersVisible = value; }
819 public int RowHeaderWidth {
820 get { return grid_style.RowHeaderWidth; }
821 set { grid_style.RowHeaderWidth = value; }
824 internal DataGridRelationshipRow[] DataGridRows {
829 public Color SelectionBackColor {
830 get { return grid_style.SelectionBackColor; }
831 set { grid_style.SelectionBackColor = value; }
834 public Color SelectionForeColor {
835 get { return grid_style.SelectionForeColor; }
836 set { grid_style.SelectionForeColor = value; }
839 public override ISite Site {
840 get { return base.Site; }
841 set { base.Site = value; }
845 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
846 public GridTableStylesCollection TableStyles {
847 get { return styles_collection; }
852 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
853 [EditorBrowsable(EditorBrowsableState.Never)]
854 public override string Text {
855 get { return base.Text; }
856 set { base.Text = value; }
860 [EditorBrowsable(EditorBrowsableState.Advanced)]
861 protected ScrollBar VertScrollBar {
862 get { return vert_scrollbar; }
864 internal ScrollBar VScrollBar {
865 get { return vert_scrollbar; }
869 public int VisibleColumnCount {
870 get { return visible_column_count; }
874 public int VisibleRowCount {
875 get { return visible_row_count; }
878 #endregion // Public Instance Properties
880 #region Private Instance Properties
881 internal DataGridTableStyle CurrentTableStyle {
882 get { return current_style; }
884 if (current_style != value) {
885 if (current_style != null)
886 DisconnectTableStyleEvents ();
888 current_style = value;
890 if (current_style != null) {
891 current_style.DataGrid = this;
892 ConnectTableStyleEvents ();
894 CalcAreasAndInvalidate ();
899 internal int FirstVisibleRow {
900 get { return first_visible_row; }
903 internal int RowsCount {
904 get { return ListManager != null ? ListManager.Count : 0; }
907 internal int RowHeight {
909 if (CurrentTableStyle.CurrentPreferredRowHeight > Font.Height + 3 + 1 /* line */)
910 return CurrentTableStyle.CurrentPreferredRowHeight;
912 return Font.Height + 3 + 1 /* line */;
916 internal bool ShowEditRow {
918 if (ListManager != null && !ListManager.CanAddRows)
925 internal bool ShowParentRows {
926 get { return ParentRowsVisible && data_source_stack.Count > 0; }
929 #endregion Private Instance Properties
931 #region Public Instance Methods
936 CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber].Abort (current_cell.RowNumber);
938 InvalidateRowHeader (current_cell.RowNumber);
943 public bool BeginEdit (DataGridColumnStyle gridColumn, int rowNumber)
948 int column = CurrentTableStyle.GridColumnStyles.IndexOf (gridColumn);
952 CurrentCell = new DataGridCell (rowNumber, column);
954 /* force editing of CurrentCell if we aren't already editing */
960 public void BeginInit ()
964 protected virtual void CancelEditing ()
966 if (CurrentTableStyle.GridColumnStyles.Count == 0)
969 CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber].ConcedeFocus ();
972 if (current_cell.ColumnNumber < CurrentTableStyle.GridColumnStyles.Count)
973 CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber].Abort (current_cell.RowNumber);
974 InvalidateRowHeader (current_cell.RowNumber);
977 if (cursor_in_add_row && !is_changing) {
978 ListManager.CancelCurrentEdit ();
986 public void Collapse (int row)
988 if (!rows[row].IsExpanded)
992 rows[row].IsExpanded = false;
993 for (int i = 1; i < rows.Length - row; i ++)
994 rows[row + i].VerticalOffset -= rows[row].RelationHeight;
996 rows[row].height -= rows[row].RelationHeight;
997 rows[row].RelationHeight = 0;
998 ResumeLayout (false);
1000 /* XX need to redraw from @row down */
1001 CalcAreasAndInvalidate ();
1004 protected internal virtual void ColumnStartedEditing (Control editingControl)
1006 ColumnStartedEditing (editingControl.Bounds);
1009 protected internal virtual void ColumnStartedEditing (Rectangle bounds)
1011 bool need_invalidate = is_changing == false;
1012 // XXX calculate the row header to invalidate
1013 // instead of using CurrentRow
1016 if (cursor_in_add_row && need_invalidate)
1017 RecreateDataGridRows (true);
1019 if (need_invalidate)
1020 InvalidateRowHeader (CurrentRow);
1023 protected override AccessibleObject CreateAccessibilityInstance ()
1025 return base.CreateAccessibilityInstance ();
1028 protected virtual DataGridColumnStyle CreateGridColumn (PropertyDescriptor prop)
1030 return CreateGridColumn (prop, false);
1033 protected virtual DataGridColumnStyle CreateGridColumn (PropertyDescriptor prop, bool isDefault)
1035 throw new NotImplementedException();
1038 protected override void Dispose (bool disposing)
1040 base.Dispose (disposing);
1043 public bool EndEdit (DataGridColumnStyle gridColumn, int rowNumber, bool shouldAbort)
1045 if (shouldAbort || (_readonly || gridColumn.TableStyleReadOnly || gridColumn.ReadOnly))
1046 gridColumn.Abort (rowNumber);
1048 gridColumn.Commit (ListManager, rowNumber);
1049 gridColumn.ConcedeFocus ();
1052 if (is_editing || is_changing) {
1054 is_changing = false;
1055 InvalidateRowHeader (rowNumber);
1060 public void EndInit ()
1064 public void Expand (int row)
1066 if (rows[row].IsExpanded)
1069 rows[row].IsExpanded = true;
1073 string[] relations = CurrentTableStyle.Relations;
1074 StringBuilder relation_builder = new StringBuilder ("");
1076 for (i = 0; i < relations.Length; i ++) {
1078 relation_builder.Append ("\n");
1080 relation_builder.Append (relations[i]);
1082 string relation_text = relation_builder.ToString ();
1084 SizeF measured_area = DeviceContext.MeasureString (relation_text, LinkFont);
1086 rows[row].relation_area = new Rectangle (cells_area.X + 1,
1087 0, /* updated as needed at the usage sites for relation_area */
1088 (int)measured_area.Width + 4,
1089 Font.Height * relations.Length);
1091 for (i = 1; i < rows.Length - row; i ++)
1092 rows[row + i].VerticalOffset += rows[row].relation_area.Height;
1093 rows[row].height += rows[row].relation_area.Height;
1094 rows[row].RelationHeight = rows[row].relation_area.Height;
1096 /* XX need to redraw from @row down */
1097 CalcAreasAndInvalidate ();
1100 public Rectangle GetCellBounds (DataGridCell cell)
1102 return GetCellBounds (cell.RowNumber, cell.ColumnNumber);
1105 public Rectangle GetCellBounds (int row, int col)
1107 Rectangle bounds = new Rectangle ();
1110 bounds.Width = CurrentTableStyle.GridColumnStyles[col].Width;
1111 bounds.Height = rows[row].Height - rows[row].RelationHeight;
1112 bounds.Y = cells_area.Y + rows[row].VerticalOffset - rows[FirstVisibleRow].VerticalOffset;
1113 col_pixel = GetColumnStartingPixel (col);
1114 bounds.X = cells_area.X + col_pixel - horiz_pixeloffset;
1118 public Rectangle GetCurrentCellBounds ()
1120 return GetCellBounds (current_cell.RowNumber, current_cell.ColumnNumber);
1123 protected virtual string GetOutputTextDelimiter ()
1125 return string.Empty;
1128 protected virtual void GridHScrolled (object sender, ScrollEventArgs se)
1130 if (se.NewValue == horiz_pixeloffset ||
1131 se.Type == ScrollEventType.EndScroll) {
1135 ScrollToColumnInPixels (se.NewValue);
1138 protected virtual void GridVScrolled (object sender, ScrollEventArgs se)
1140 int old_first_visible_row = first_visible_row;
1141 first_visible_row = se.NewValue;
1143 if (first_visible_row == old_first_visible_row)
1146 UpdateVisibleRowCount ();
1148 if (first_visible_row == old_first_visible_row)
1151 ScrollToRow (old_first_visible_row, first_visible_row);
1154 public HitTestInfo HitTest (Point position)
1156 return HitTest (position.X, position.Y);
1159 const int RESIZE_HANDLE_HORIZ_SIZE = 5;
1160 const int RESIZE_HANDLE_VERT_SIZE = 3;
1162 // From Point to Cell
1163 public HitTestInfo HitTest (int x, int y)
1165 if (column_headers_area.Contains (x, y)) {
1166 int offset_x = x + horiz_pixeloffset;
1168 int column_under_mouse = FromPixelToColumn (offset_x, out column_x);
1170 if ((column_x + CurrentTableStyle.GridColumnStyles[column_under_mouse].Width - offset_x < RESIZE_HANDLE_HORIZ_SIZE)
1171 && column_under_mouse < CurrentTableStyle.GridColumnStyles.Count) {
1173 return new HitTestInfo (-1, column_under_mouse, HitTestType.ColumnResize);
1176 return new HitTestInfo (-1, column_under_mouse, HitTestType.ColumnHeader);
1180 if (row_headers_area.Contains (x, y)) {
1182 int rcnt = FirstVisibleRow + VisibleRowCount;
1183 for (int r = FirstVisibleRow; r < rcnt; r++) {
1184 posy = cells_area.Y + rows[r].VerticalOffset - rows[FirstVisibleRow].VerticalOffset;
1185 if (y <= posy + rows[r].Height) {
1186 if ((posy + rows[r].Height) - y < RESIZE_HANDLE_VERT_SIZE) {
1187 return new HitTestInfo (r, -1, HitTestType.RowResize);
1190 return new HitTestInfo (r, -1, HitTestType.RowHeader);
1196 if (caption_area.Contains (x, y)) {
1197 return new HitTestInfo (-1, -1, HitTestType.Caption);
1200 if (parent_rows.Contains (x, y)) {
1201 return new HitTestInfo (-1, -1, HitTestType.ParentRows);
1204 int pos_y, pos_x, width;
1205 int rowcnt = FirstVisibleRow + VisibleRowCount;
1206 for (int row = FirstVisibleRow; row < rowcnt; row++) {
1208 pos_y = cells_area.Y + rows[row].VerticalOffset - rows[FirstVisibleRow].VerticalOffset;
1209 if (y <= pos_y + rows[row].Height) {
1211 int column_cnt = first_visible_column + visible_column_count;
1212 if (column_cnt > 0) {
1213 for (int column = first_visible_column; column < column_cnt; column++) {
1214 if (CurrentTableStyle.GridColumnStyles[column].bound == false)
1216 col_pixel = GetColumnStartingPixel (column);
1217 pos_x = cells_area.X + col_pixel - horiz_pixeloffset;
1218 width = CurrentTableStyle.GridColumnStyles[column].Width;
1220 if (x <= pos_x + width) { // Column found
1221 return new HitTestInfo (row, column, HitTestType.Cell);
1225 else if (CurrentTableStyle.HasRelations) {
1226 /* XXX this needs checking against MS somehow... */
1227 if (x < rows[row].relation_area.X + rows[row].relation_area.Width)
1228 return new HitTestInfo (row, 0/*XXX?*/, HitTestType.Cell);
1235 return new HitTestInfo ();
1238 public bool IsExpanded (int rowNumber)
1240 return (rows[rowNumber].IsExpanded);
1243 public bool IsSelected (int row)
1245 return rows[row].IsSelected;
1249 public void NavigateBack ()
1251 if (data_source_stack.Count == 0)
1254 DataGridDataSource source = (DataGridDataSource)data_source_stack.Pop ();
1255 list_manager = source.list_manager;
1257 selected_rows = source.SelectedRows;
1258 selection_start = source.SelectionStart;
1259 SetDataSource (source.data_source, source.data_member);
1261 CurrentCell = source.current;
1265 public void NavigateTo (int rowNumber, string relationName)
1267 if (allow_navigation == false)
1270 DataGridDataSource previous_source = new DataGridDataSource (this, list_manager, datasource, datamember, list_manager.Current, CurrentCell);
1271 previous_source.Rows = rows;
1272 previous_source.SelectedRows = selected_rows;
1273 previous_source.SelectionStart = selection_start;
1275 data_source_stack.Push (previous_source);
1278 selected_rows = new Hashtable ();
1279 selection_start = -1;
1281 DataMember = String.Format ("{0}.{1}", DataMember, relationName);
1282 OnDataSourceChanged (EventArgs.Empty);
1285 protected virtual void OnAllowNavigationChanged (EventArgs e)
1287 EventHandler eh = (EventHandler)(Events [AllowNavigationChangedEvent]);
1292 protected void OnBackButtonClicked (object sender, EventArgs e)
1294 EventHandler eh = (EventHandler)(Events [BackButtonClickEvent]);
1299 protected override void OnBackColorChanged (EventArgs e)
1301 base.OnBackColorChanged (e);
1304 protected virtual void OnBackgroundColorChanged (EventArgs e)
1306 EventHandler eh = (EventHandler)(Events [BackgroundColorChangedEvent]);
1311 protected override void OnBindingContextChanged (EventArgs e)
1313 base.OnBindingContextChanged (e);
1315 SetDataSource (datasource, datamember);
1318 protected virtual void OnBorderStyleChanged (EventArgs e)
1320 EventHandler eh = (EventHandler)(Events [BorderStyleChangedEvent]);
1325 protected virtual void OnCaptionVisibleChanged (EventArgs e)
1327 EventHandler eh = (EventHandler)(Events [CaptionVisibleChangedEvent]);
1332 protected virtual void OnCurrentCellChanged (EventArgs e)
1334 EventHandler eh = (EventHandler)(Events [CurrentCellChangedEvent]);
1339 protected virtual void OnDataSourceChanged (EventArgs e)
1341 EventHandler eh = (EventHandler)(Events [DataSourceChangedEvent]);
1346 protected override void OnEnter (EventArgs e)
1352 protected virtual void OnFlatModeChanged (EventArgs e)
1354 EventHandler eh = (EventHandler)(Events [FlatModeChangedEvent]);
1359 protected override void OnFontChanged (EventArgs e)
1362 base.OnFontChanged (e);
1365 protected override void OnForeColorChanged (EventArgs e)
1367 base.OnForeColorChanged (e);
1370 protected override void OnHandleCreated (EventArgs e)
1372 base.OnHandleCreated (e);
1373 SetDataSource (datasource, datamember);
1376 protected override void OnHandleDestroyed (EventArgs e)
1378 base.OnHandleDestroyed (e);
1381 protected override void OnKeyDown (KeyEventArgs ke)
1383 base.OnKeyDown (ke);
1385 if (ProcessGridKey (ke) == true)
1388 /* TODO: we probably don't need this check,
1389 * since current_cell wouldn't have been set
1390 * to something invalid */
1391 if (CurrentTableStyle.GridColumnStyles.Count > 0) {
1392 CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber].OnKeyDown
1393 (ke, current_cell.RowNumber, current_cell.ColumnNumber);
1397 protected override void OnKeyPress (KeyPressEventArgs kpe)
1399 base.OnKeyPress (kpe);
1402 protected override void OnLayout (LayoutEventArgs levent)
1404 base.OnLayout (levent);
1405 CalcAreasAndInvalidate ();
1408 protected override void OnLeave (EventArgs e)
1412 if (cursor_in_add_row) {
1413 ListManager.CancelCurrentEdit ();
1417 protected override void OnMouseDown (MouseEventArgs e)
1419 base.OnMouseDown (e);
1421 bool ctrl_pressed = ((Control.ModifierKeys & Keys.Control) != 0);
1422 bool shift_pressed = ((Control.ModifierKeys & Keys.Shift) != 0);
1424 HitTestInfo testinfo;
1425 testinfo = HitTest (e.X, e.Y);
1427 switch (testinfo.Type) {
1428 case HitTestType.Cell:
1429 if (testinfo.Row < 0 || testinfo.Column < 0)
1432 if (rows[testinfo.Row].IsExpanded) {
1433 Rectangle relation_area = rows[testinfo.Row].relation_area;
1434 relation_area.Y = rows[testinfo.Row].VerticalOffset + cells_area.Y + rows[testinfo.Row].Height - rows[testinfo.Row].RelationHeight;
1435 if (relation_area.Contains (e.X, e.Y)) {
1436 /* the click happened in the relation area, navigate to the new table */
1437 int relative = e.Y - relation_area.Y;
1438 NavigateTo (testinfo.Row, CurrentTableStyle.Relations[relative / LinkFont.Height]);
1443 DataGridCell new_cell = new DataGridCell (testinfo.Row, testinfo.Column);
1445 if ((new_cell.Equals (current_cell) == false) || (!is_editing)) {
1446 CurrentCell = new_cell;
1449 CurrentTableStyle.GridColumnStyles[testinfo.Column].OnMouseDown (e, testinfo.Row, testinfo.Column);
1454 case HitTestType.RowHeader:
1455 bool expansion_click = false;
1456 if (CurrentTableStyle.HasRelations) {
1457 if (e.X > row_headers_area.X + row_headers_area.Width / 2) {
1458 /* it's in the +/- space */
1459 if (IsExpanded (testinfo.Row))
1460 Collapse (testinfo.Row);
1462 Expand (testinfo.Row);
1464 expansion_click = true;
1468 if (!ctrl_pressed &&
1471 ResetSelection (); // Invalidates selected rows
1474 if ((shift_pressed ||
1476 && selection_start != -1) {
1477 ShiftSelection (testinfo.Row);
1478 } else { // ctrl_pressed or single item
1479 selection_start = testinfo.Row;
1480 Select (testinfo.Row);
1484 CurrentRow = testinfo.Row;
1485 OnRowHeaderClick (EventArgs.Empty);
1489 case HitTestType.ColumnHeader:
1490 if (CurrentTableStyle.GridColumnStyles.Count == 0)
1493 if (AllowSorting == false)
1496 if (ListManager.List is IBindingList == false)
1499 ListSortDirection direction = ListSortDirection.Ascending;
1500 PropertyDescriptor prop = CurrentTableStyle.GridColumnStyles[testinfo.Column].PropertyDescriptor;
1501 IBindingList list = (IBindingList) ListManager.List;
1503 if (list.SortProperty != null) {
1504 CurrentTableStyle.GridColumnStyles[list.SortProperty].ArrowDrawingMode
1505 = DataGridColumnStyle.ArrowDrawing.No;
1508 if (prop == list.SortProperty && list.SortDirection == ListSortDirection.Ascending) {
1509 direction = ListSortDirection.Descending;
1512 CurrentTableStyle.GridColumnStyles[testinfo.Column].ArrowDrawingMode =
1513 direction == ListSortDirection.Ascending ?
1514 DataGridColumnStyle.ArrowDrawing.Ascending : DataGridColumnStyle.ArrowDrawing.Descending;
1516 list.ApplySort (prop, direction);
1520 case HitTestType.ColumnResize:
1521 if (e.Clicks == 2) {
1522 // double click column resize goes here
1525 resize_column = testinfo.Column;
1526 column_resize_active = true;
1527 resize_column_x = e.X;
1528 resize_column_width_delta = 0;
1530 DrawResizeLineVert (resize_column_x);
1534 case HitTestType.RowResize:
1535 if (e.Clicks == 2) {
1536 // double click row resize goes here
1539 resize_row = testinfo.Row;
1540 row_resize_active = true;
1542 resize_row_height_delta = 0;
1544 DrawResizeLineHoriz (resize_row_y);
1548 case HitTestType.Caption:
1549 if (back_button_rect.Contains (e.X, e.Y)) {
1550 back_button_active = true;
1551 Invalidate (back_button_rect);
1553 if (parent_rows_button_rect.Contains (e.X, e.Y)) {
1554 parent_rows_button_active = true;
1555 Invalidate (parent_rows_button_rect);
1564 protected override void OnMouseLeave (EventArgs e)
1566 base.OnMouseLeave (e);
1569 protected override void OnMouseMove (MouseEventArgs e)
1571 base.OnMouseMove (e);
1573 if (column_resize_active) {
1574 /* erase the old line */
1575 DrawResizeLineVert (resize_column_x + resize_column_width_delta);
1577 resize_column_width_delta = e.X - resize_column_x;
1579 /* draw the new line */
1580 DrawResizeLineVert (resize_column_x + resize_column_width_delta);
1583 else if (row_resize_active) {
1584 /* erase the old line */
1585 DrawResizeLineHoriz (resize_row_y + resize_row_height_delta);
1587 resize_row_height_delta = e.Y - resize_row_y;
1589 /* draw the new line */
1590 DrawResizeLineHoriz (resize_row_y + resize_row_height_delta);
1594 /* determine the cursor to use */
1595 HitTestInfo testinfo;
1596 testinfo = HitTest (e.X, e.Y);
1598 switch (testinfo.Type) {
1599 case HitTestType.ColumnResize:
1600 Cursor = Cursors.VSplit;
1602 case HitTestType.RowResize:
1603 Cursor = Cursors.HSplit;
1605 case HitTestType.Caption:
1606 Cursor = Cursors.Default;
1607 if (back_button_rect.Contains (e.X, e.Y)) {
1608 if (!back_button_mouseover)
1609 Invalidate (back_button_rect);
1610 back_button_mouseover = true;
1612 else if (back_button_mouseover) {
1613 Invalidate (back_button_rect);
1614 back_button_mouseover = false;
1617 if (parent_rows_button_rect.Contains (e.X, e.Y)) {
1618 if (parent_rows_button_mouseover)
1619 Invalidate (parent_rows_button_rect);
1620 parent_rows_button_mouseover = true;
1622 else if (parent_rows_button_mouseover) {
1623 Invalidate (parent_rows_button_rect);
1624 parent_rows_button_mouseover = false;
1627 case HitTestType.Cell:
1628 if (rows[testinfo.Row].IsExpanded) {
1629 Rectangle relation_area = rows[testinfo.Row].relation_area;
1630 relation_area.Y = rows[testinfo.Row].VerticalOffset + cells_area.Y + rows[testinfo.Row].Height - rows[testinfo.Row].RelationHeight;
1631 if (relation_area.Contains (e.X, e.Y)) {
1632 Cursor = Cursors.Hand;
1637 Cursor = Cursors.Default;
1640 Cursor = Cursors.Default;
1646 protected override void OnMouseUp (MouseEventArgs e)
1650 if (column_resize_active) {
1651 column_resize_active = false;
1652 if (resize_column_width_delta + CurrentTableStyle.GridColumnStyles[resize_column].Width < 0)
1653 resize_column_width_delta = -CurrentTableStyle.GridColumnStyles[resize_column].Width;
1654 CurrentTableStyle.GridColumnStyles[resize_column].Width += resize_column_width_delta;
1655 width_of_all_columns += resize_column_width_delta;
1659 else if (row_resize_active) {
1660 row_resize_active = false;
1662 if (resize_row_height_delta + rows[resize_row].Height < 0)
1663 resize_row_height_delta = -rows[resize_row].Height;
1665 rows[resize_row].height = rows[resize_row].Height + resize_row_height_delta;
1666 for (int i = resize_row + 1; i < rows.Length; i ++)
1667 rows[i].VerticalOffset += resize_row_height_delta;
1670 CalcAreasAndInvalidate ();
1672 else if (back_button_active) {
1673 if (back_button_rect.Contains (e.X, e.Y)) {
1674 Invalidate (back_button_rect);
1676 OnBackButtonClicked (this, EventArgs.Empty);
1678 back_button_active = false;
1680 else if (parent_rows_button_active) {
1681 if (parent_rows_button_rect.Contains (e.X, e.Y)) {
1682 Invalidate (parent_rows_button_rect);
1683 ParentRowsVisible = !ParentRowsVisible;
1684 OnShowParentDetailsButtonClicked (this, EventArgs.Empty);
1686 parent_rows_button_active = false;
1690 protected override void OnMouseWheel (MouseEventArgs e)
1692 base.OnMouseWheel (e);
1694 bool ctrl_pressed = ((Control.ModifierKeys & Keys.Control) != 0);
1697 if (ctrl_pressed) { // scroll horizontally
1698 if (!horiz_scrollbar.Visible)
1703 pixels = Math.Max (horiz_scrollbar.Minimum,
1704 horiz_scrollbar.Value - horiz_scrollbar.LargeChange);
1708 pixels = Math.Min (horiz_scrollbar.Maximum - horiz_scrollbar.LargeChange + 1,
1709 horiz_scrollbar.Value + horiz_scrollbar.LargeChange);
1712 GridHScrolled (this, new ScrollEventArgs (ScrollEventType.ThumbPosition, pixels));
1713 horiz_scrollbar.Value = pixels;
1715 if (!vert_scrollbar.Visible)
1720 pixels = Math.Max (vert_scrollbar.Minimum,
1721 vert_scrollbar.Value - vert_scrollbar.LargeChange);
1725 pixels = Math.Min (vert_scrollbar.Maximum - vert_scrollbar.LargeChange + 1,
1726 vert_scrollbar.Value + vert_scrollbar.LargeChange);
1729 GridVScrolled (this, new ScrollEventArgs (ScrollEventType.ThumbPosition, pixels));
1730 vert_scrollbar.Value = pixels;
1734 protected void OnNavigate (NavigateEventArgs e)
1736 EventHandler eh = (EventHandler)(Events [NavigateEvent]);
1741 protected override void OnPaint (PaintEventArgs pe)
1743 ThemeEngine.Current.DataGridPaint (pe, this);
1746 protected override void OnPaintBackground (PaintEventArgs ebe)
1750 protected virtual void OnParentRowsLabelStyleChanged (EventArgs e)
1752 EventHandler eh = (EventHandler)(Events [ParentRowsLabelStyleChangedEvent]);
1757 protected virtual void OnParentRowsVisibleChanged (EventArgs e)
1759 EventHandler eh = (EventHandler)(Events [ParentRowsVisibleChangedEvent]);
1764 protected virtual void OnReadOnlyChanged (EventArgs e)
1766 EventHandler eh = (EventHandler)(Events [ReadOnlyChangedEvent]);
1771 protected override void OnResize (EventArgs e)
1776 protected void OnRowHeaderClick (EventArgs e)
1778 EventHandler eh = (EventHandler)(Events [RowHeaderClickEvent]);
1783 protected void OnScroll (EventArgs e)
1785 EventHandler eh = (EventHandler)(Events [ScrollEvent]);
1790 protected void OnShowParentDetailsButtonClicked (object sender, EventArgs e)
1792 EventHandler eh = (EventHandler)(Events [ShowParentDetailsButtonClickEvent]);
1797 protected override bool ProcessDialogKey (Keys keyData)
1799 return ProcessGridKey (new KeyEventArgs (keyData));
1802 void UpdateSelectionAfterCursorMove (bool extend_selection)
1804 if (extend_selection) {
1806 ShiftSelection (CurrentRow);
1813 protected bool ProcessGridKey (KeyEventArgs ke)
1815 /* if we have no rows, exit immediately.
1816 XXX is this necessary? */
1820 bool ctrl_pressed = ((ke.Modifiers & Keys.Control) != 0);
1821 //bool alt_pressed = ((ke.Modifiers & Keys.Alt) != 0);
1822 bool shift_pressed = ((ke.Modifiers & Keys.Shift) != 0);
1824 switch (ke.KeyCode) {
1836 CurrentTableStyle.GridColumnStyles[CurrentColumn].EnterNullValue ();
1847 if (shift_pressed) {
1848 if (CurrentColumn > 0)
1850 else if ((CurrentRow > 0) && (CurrentColumn == 0))
1851 CurrentCell = new DataGridCell (CurrentRow - 1, CurrentTableStyle.GridColumnStyles.Count - 1);
1854 if (CurrentColumn < CurrentTableStyle.GridColumnStyles.Count - 1)
1856 else if ((CurrentRow <= RowsCount) && (CurrentColumn == CurrentTableStyle.GridColumnStyles.Count - 1))
1857 CurrentCell = new DataGridCell (CurrentRow + 1, 0);
1860 UpdateSelectionAfterCursorMove (false);
1866 CurrentColumn = CurrentTableStyle.GridColumnStyles.Count - 1;
1869 if (CurrentColumn < CurrentTableStyle.GridColumnStyles.Count - 1) {
1871 } else if (CurrentRow < RowsCount - 1
1872 || (CurrentRow == RowsCount - 1
1873 && !cursor_in_add_row)) {
1874 CurrentCell = new DataGridCell (CurrentRow + 1, 0);
1878 UpdateSelectionAfterCursorMove (false);
1887 if (current_cell.ColumnNumber > 0)
1889 else if (CurrentRow > 0)
1890 CurrentCell = new DataGridCell (CurrentRow - 1, CurrentTableStyle.GridColumnStyles.Count - 1);
1893 UpdateSelectionAfterCursorMove (false);
1900 else if (CurrentRow > 0)
1903 UpdateSelectionAfterCursorMove (shift_pressed);
1909 CurrentRow = RowsCount - 1;
1910 else if (CurrentRow < RowsCount - 1)
1912 else if (CurrentRow == RowsCount - 1 && cursor_in_add_row && (add_row_changed || is_changing))
1914 else if (CurrentRow == RowsCount - 1 && !cursor_in_add_row && !shift_pressed)
1917 UpdateSelectionAfterCursorMove (shift_pressed);
1922 if (CurrentRow > VLargeChange)
1923 CurrentRow -= VLargeChange;
1927 UpdateSelectionAfterCursorMove (shift_pressed);
1932 if (CurrentRow < RowsCount - VLargeChange)
1933 CurrentRow += VLargeChange;
1935 CurrentRow = RowsCount - 1;
1937 UpdateSelectionAfterCursorMove (shift_pressed);
1943 CurrentCell = new DataGridCell (0, 0);
1947 UpdateSelectionAfterCursorMove (ctrl_pressed && shift_pressed);
1953 CurrentCell = new DataGridCell (RowsCount - 1, CurrentTableStyle.GridColumnStyles.Count - 1);
1955 CurrentColumn = CurrentTableStyle.GridColumnStyles.Count - 1;
1957 UpdateSelectionAfterCursorMove (ctrl_pressed && shift_pressed);
1964 else if (selected_rows.Keys.Count > 0) {
1965 foreach (int row in selected_rows.Keys) {
1966 ListManager.RemoveAt (row);
1968 selected_rows.Clear ();
1969 CalcAreasAndInvalidate ();
1975 return false; // message not processed
1978 protected override bool ProcessKeyPreview (ref Message m)
1980 if ((Msg)m.Msg == Msg.WM_KEYDOWN) {
1981 Keys key = (Keys) m.WParam.ToInt32 ();
1982 KeyEventArgs ke = new KeyEventArgs (key);
1983 if (ProcessGridKey (ke) == true) {
1988 return base.ProcessKeyPreview (ref m);
1991 protected bool ProcessTabKey (Keys keyData)
1996 public void ResetAlternatingBackColor ()
1998 grid_style.AlternatingBackColor = default_style.AlternatingBackColor;
2001 public override void ResetBackColor ()
2003 grid_style.BackColor = default_style.BackColor;
2006 public override void ResetForeColor ()
2008 grid_style.ForeColor = default_style.ForeColor;
2011 public void ResetGridLineColor ()
2013 grid_style.GridLineColor = default_style.GridLineColor;
2016 public void ResetHeaderBackColor ()
2018 grid_style.HeaderBackColor = default_style.HeaderBackColor;
2021 public void ResetHeaderFont ()
2023 grid_style.HeaderFont = default_style.HeaderFont;
2026 public void ResetHeaderForeColor ()
2028 grid_style.HeaderForeColor = default_style.HeaderForeColor;
2031 public void ResetLinkColor ()
2033 grid_style.LinkColor = default_style.LinkColor;
2036 public void ResetLinkHoverColor ()
2038 grid_style.LinkHoverColor = default_style.LinkHoverColor;
2041 protected void ResetSelection ()
2043 InvalidateSelection ();
2044 selected_rows.Clear ();
2045 selection_start = -1;
2048 void InvalidateSelection ()
2050 foreach (int row in selected_rows.Keys) {
2051 rows[row].IsSelected = false;
2052 InvalidateRow (row);
2056 public void ResetSelectionBackColor ()
2058 grid_style.SelectionBackColor = default_style.SelectionBackColor;
2061 public void ResetSelectionForeColor ()
2063 grid_style.SelectionForeColor = default_style.SelectionForeColor;
2066 public void Select (int row)
2068 if (selected_rows.Count == 0)
2069 selection_start = row;
2071 selected_rows[row] = true;
2072 rows[row].IsSelected = true;
2074 InvalidateRow (row);
2077 public void SetDataBinding (object dataSource, string dataMember)
2079 SetDataSource (dataSource, dataMember);
2082 protected virtual bool ShouldSerializeAlternatingBackColor ()
2084 return (grid_style.AlternatingBackColor != default_style.AlternatingBackColor);
2087 protected virtual bool ShouldSerializeBackgroundColor ()
2089 return (background_color != def_background_color);
2092 protected virtual bool ShouldSerializeCaptionBackColor ()
2094 return (caption_backcolor != def_caption_backcolor);
2097 protected virtual bool ShouldSerializeCaptionForeColor ()
2099 return caption_forecolor != def_caption_forecolor;
2102 protected virtual bool ShouldSerializeGridLineColor ()
2104 return grid_style.GridLineColor != default_style.GridLineColor;
2107 protected virtual bool ShouldSerializeHeaderBackColor ()
2109 return grid_style.HeaderBackColor != default_style.HeaderBackColor;
2112 protected bool ShouldSerializeHeaderFont ()
2114 return grid_style.HeaderFont != default_style.HeaderFont;
2117 protected virtual bool ShouldSerializeHeaderForeColor ()
2119 return grid_style.HeaderForeColor != default_style.HeaderForeColor;
2122 protected virtual bool ShouldSerializeLinkHoverColor ()
2124 return grid_style.LinkHoverColor != grid_style.LinkHoverColor;
2127 protected virtual bool ShouldSerializeParentRowsBackColor ()
2129 return parent_rows_backcolor != def_parent_rows_backcolor;
2132 protected virtual bool ShouldSerializeParentRowsForeColor ()
2134 return parent_rows_backcolor != def_parent_rows_backcolor;
2137 protected bool ShouldSerializePreferredRowHeight ()
2139 return grid_style.PreferredRowHeight != default_style.PreferredRowHeight;
2142 protected bool ShouldSerializeSelectionBackColor ()
2144 return grid_style.SelectionBackColor != default_style.SelectionBackColor;
2147 protected virtual bool ShouldSerializeSelectionForeColor ()
2149 return grid_style.SelectionForeColor != default_style.SelectionForeColor;
2152 public void SubObjectsSiteChange (bool site)
2156 public void UnSelect (int row)
2158 rows[row].IsSelected = false;
2159 selected_rows.Remove (row);
2160 InvalidateRow (row);
2162 #endregion // Public Instance Methods
2164 #region Private Instance Methods
2166 internal void CalcAreasAndInvalidate ()
2172 private void ConnectListManagerEvents ()
2174 list_manager.MetaDataChanged += new EventHandler (OnListManagerMetaDataChanged);
2175 list_manager.PositionChanged += new EventHandler (OnListManagerPositionChanged);
2176 list_manager.ItemChanged += new ItemChangedEventHandler (OnListManagerItemChanged);
2179 private void DisconnectListManagerEvents ()
2181 list_manager.MetaDataChanged -= new EventHandler (OnListManagerMetaDataChanged);
2182 list_manager.PositionChanged -= new EventHandler (OnListManagerPositionChanged);
2183 list_manager.ItemChanged -= new ItemChangedEventHandler (OnListManagerItemChanged);
2186 void DisconnectTableStyleEvents ()
2188 current_style.AllowSortingChanged -= new EventHandler (TableStyleChanged);
2189 current_style.AlternatingBackColorChanged -= new EventHandler (TableStyleChanged);
2190 current_style.BackColorChanged -= new EventHandler (TableStyleChanged);
2191 current_style.ColumnHeadersVisibleChanged -= new EventHandler (TableStyleChanged);
2192 current_style.ForeColorChanged -= new EventHandler (TableStyleChanged);
2193 current_style.GridLineColorChanged -= new EventHandler (TableStyleChanged);
2194 current_style.GridLineStyleChanged -= new EventHandler (TableStyleChanged);
2195 current_style.HeaderBackColorChanged -= new EventHandler (TableStyleChanged);
2196 current_style.HeaderFontChanged -= new EventHandler (TableStyleChanged);
2197 current_style.HeaderForeColorChanged -= new EventHandler (TableStyleChanged);
2198 current_style.LinkColorChanged -= new EventHandler (TableStyleChanged);
2199 current_style.LinkHoverColorChanged -= new EventHandler (TableStyleChanged);
2200 current_style.MappingNameChanged -= new EventHandler (TableStyleChanged);
2201 current_style.PreferredColumnWidthChanged -= new EventHandler (TableStyleChanged);
2202 current_style.PreferredRowHeightChanged -= new EventHandler (TableStyleChanged);
2203 current_style.ReadOnlyChanged -= new EventHandler (TableStyleChanged);
2204 current_style.RowHeadersVisibleChanged -= new EventHandler (TableStyleChanged);
2205 current_style.RowHeaderWidthChanged -= new EventHandler (TableStyleChanged);
2206 current_style.SelectionBackColorChanged -= new EventHandler (TableStyleChanged);
2207 current_style.SelectionForeColorChanged -= new EventHandler (TableStyleChanged);
2210 void ConnectTableStyleEvents ()
2212 current_style.AllowSortingChanged += new EventHandler (TableStyleChanged);
2213 current_style.AlternatingBackColorChanged += new EventHandler (TableStyleChanged);
2214 current_style.BackColorChanged += new EventHandler (TableStyleChanged);
2215 current_style.ColumnHeadersVisibleChanged += new EventHandler (TableStyleChanged);
2216 current_style.ForeColorChanged += new EventHandler (TableStyleChanged);
2217 current_style.GridLineColorChanged += new EventHandler (TableStyleChanged);
2218 current_style.GridLineStyleChanged += new EventHandler (TableStyleChanged);
2219 current_style.HeaderBackColorChanged += new EventHandler (TableStyleChanged);
2220 current_style.HeaderFontChanged += new EventHandler (TableStyleChanged);
2221 current_style.HeaderForeColorChanged += new EventHandler (TableStyleChanged);
2222 current_style.LinkColorChanged += new EventHandler (TableStyleChanged);
2223 current_style.LinkHoverColorChanged += new EventHandler (TableStyleChanged);
2224 current_style.MappingNameChanged += new EventHandler (TableStyleChanged);
2225 current_style.PreferredColumnWidthChanged += new EventHandler (TableStyleChanged);
2226 current_style.PreferredRowHeightChanged += new EventHandler (TableStyleChanged);
2227 current_style.ReadOnlyChanged += new EventHandler (TableStyleChanged);
2228 current_style.RowHeadersVisibleChanged += new EventHandler (TableStyleChanged);
2229 current_style.RowHeaderWidthChanged += new EventHandler (TableStyleChanged);
2230 current_style.SelectionBackColorChanged += new EventHandler (TableStyleChanged);
2231 current_style.SelectionForeColorChanged += new EventHandler (TableStyleChanged);
2234 void TableStyleChanged (object sender, EventArgs args)
2237 CalcAreasAndInvalidate ();
2241 private void EnsureCellVisibility (DataGridCell cell)
2243 if (cell.ColumnNumber <= first_visible_column ||
2244 cell.ColumnNumber + 1 >= first_visible_column + visible_column_count) {
2246 first_visible_column = GetFirstColumnForColumnVisibility (first_visible_column, cell.ColumnNumber);
2247 int pixel = GetColumnStartingPixel (first_visible_column);
2248 ScrollToColumnInPixels (pixel);
2249 horiz_scrollbar.Value = pixel;
2253 if (cell.RowNumber < first_visible_row ||
2254 cell.RowNumber + 1 >= first_visible_row + visible_row_count) {
2256 if (cell.RowNumber + 1 >= first_visible_row + visible_row_count) {
2257 int old_first_visible_row = first_visible_row;
2258 first_visible_row = 1 + cell.RowNumber - visible_row_count;
2259 UpdateVisibleRowCount ();
2260 ScrollToRow (old_first_visible_row, first_visible_row);
2262 int old_first_visible_row = first_visible_row;
2263 first_visible_row = cell.RowNumber;
2264 UpdateVisibleRowCount ();
2265 ScrollToRow (old_first_visible_row, first_visible_row);
2268 vert_scrollbar.Value = first_visible_row;
2272 private void SetDataSource (object source, string member)
2274 SetDataSource (source, member, true);
2277 bool in_setdatasource;
2278 private void SetDataSource (object source, string member, bool recreate_rows)
2280 CurrencyManager old_lm = list_manager;
2282 /* we need this bool flag to work around a
2283 * problem with OnBindingContextChanged. once
2284 * that stuff works properly, remove this
2286 if (in_setdatasource)
2288 in_setdatasource = true;
2291 if (datasource == source && member == datamember)
2295 if (source != null && source as IListSource != null && source as IList != null)
2296 throw new Exception ("Wrong complex data binding source");
2298 datasource = source;
2299 datamember = member;
2304 current_cell = new DataGridCell ();
2306 if (list_manager != null)
2307 DisconnectListManagerEvents ();
2309 list_manager = null;
2311 /* create the new list manager */
2312 if (BindingContext != null && datasource != null)
2313 list_manager = (CurrencyManager) BindingContext [datasource, datamember];
2315 if (list_manager != null)
2316 ConnectListManagerEvents ();
2318 if (old_lm != list_manager) {
2321 /* reset first_visible_row to 0 here before
2322 * doing anything that'll requires us to
2323 * figure out if we need a scrollbar. */
2324 vert_scrollbar.Value = 0;
2325 horiz_scrollbar.Value = 0;
2326 first_visible_row = 0;
2329 RecreateDataGridRows (false);
2332 CalcAreasAndInvalidate ();
2334 in_setdatasource = false;
2336 OnDataSourceChanged (EventArgs.Empty);
2339 void RecreateDataGridRows (bool recalc)
2341 DataGridRelationshipRow[] new_rows = new DataGridRelationshipRow[RowsCount + (ShowEditRow ? 1 : 0)];
2342 int start_index = 0;
2344 start_index = rows.Length;
2345 Array.Copy (rows, 0, new_rows, 0, rows.Length < new_rows.Length ? rows.Length : new_rows.Length);
2348 for (int i = start_index; i < new_rows.Length; i ++) {
2349 new_rows[i] = new DataGridRelationshipRow (this);
2350 new_rows[i].height = RowHeight;
2352 new_rows[i].VerticalOffset = new_rows[i-1].VerticalOffset + new_rows[i-1].Height;
2358 CalcAreasAndInvalidate ();
2361 internal void UpdateRowsFrom (DataGridRelationshipRow row)
2363 int start_index = Array.IndexOf (rows, row);
2364 if (start_index == -1)
2367 for (int i = start_index + 1; i < rows.Length; i ++) {
2368 rows[i].VerticalOffset = rows[i-1].VerticalOffset + rows[i-1].Height;
2371 CalcAreasAndInvalidate ();
2376 if (list_manager != null) {
2377 string list_name = list_manager.GetListName (null);
2378 if (TableStyles[list_name] == null) {
2379 // no style exists by the supplied name
2380 current_style.GridColumnStyles.Clear ();
2381 current_style.CreateColumnsForTable (false);
2383 else if (CurrentTableStyle == grid_style ||
2384 CurrentTableStyle.MappingName != list_name) {
2385 // If the style has been defined by the user, use it
2386 CurrentTableStyle = styles_collection[list_name];
2387 current_style.CreateColumnsForTable (true);
2390 current_style.CreateColumnsForTable (true);
2394 current_style.CreateColumnsForTable (false);
2397 private void OnListManagerMetaDataChanged (object sender, EventArgs e)
2401 //we need to rethink this, as in 2.0 we get this event when a column is added to a table.
2402 // forcing a rebind of columns means that we fail bug #80422. disable this for now.
2407 private void OnListManagerPositionChanged (object sender, EventArgs e)
2409 from_positionchanged_handler = true;
2410 CurrentRow = list_manager.Position;
2411 from_positionchanged_handler = false;
2414 private void OnListManagerItemChanged (object sender, ItemChangedEventArgs e)
2416 if (e.Index == -1) {
2418 if (rows == null || RowsCount != rows.Length - (ShowEditRow ? 1 : 0))
2419 RecreateDataGridRows (true);
2422 InvalidateRow (e.Index);
2426 private void OnTableStylesCollectionChanged (object sender, CollectionChangeEventArgs e)
2428 if (ListManager == null)
2431 string list_name = ListManager.GetListName (null);
2433 case CollectionChangeAction.Add: {
2434 if (e.Element != null && String.Compare (list_name, ((DataGridTableStyle)e.Element).MappingName, true) == 0) {
2435 CurrentTableStyle = (DataGridTableStyle)e.Element;
2436 ((DataGridTableStyle) e.Element).CreateColumnsForTable (false);
2441 case CollectionChangeAction.Remove: {
2442 if (e.Element != null && String.Compare (list_name, ((DataGridTableStyle)e.Element).MappingName, true) == 0) {
2443 CurrentTableStyle = default_style;
2444 current_style.GridColumnStyles.Clear ();
2445 current_style.CreateColumnsForTable (false);
2451 case CollectionChangeAction.Refresh: {
2452 if (CurrentTableStyle == default_style
2453 || String.Compare (list_name, CurrentTableStyle.MappingName, true) != 0) {
2455 DataGridTableStyle style = styles_collection [list_name];
2456 if (style != null) {
2457 CurrentTableStyle = style;
2458 current_style.CreateColumnsForTable (false);
2461 CurrentTableStyle = default_style;
2462 current_style.GridColumnStyles.Clear ();
2463 current_style.CreateColumnsForTable (false);
2470 CalcAreasAndInvalidate ();
2473 private void AddNewRow ()
2475 ListManager.EndCurrentEdit ();
2476 ListManager.AddNew ();
2479 private void Edit ()
2481 if (CurrentTableStyle.GridColumnStyles.Count == 0)
2484 if (CurrentTableStyle.GridColumnStyles[CurrentColumn].bound == false)
2488 is_changing = false;
2490 CurrentTableStyle.GridColumnStyles[CurrentColumn].Edit (ListManager,
2491 CurrentRow, GetCellBounds (CurrentRow, CurrentColumn),
2492 _readonly, null, true);
2495 private void EndEdit ()
2497 if (CurrentTableStyle.GridColumnStyles.Count == 0)
2500 if (CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber].bound == false)
2503 EndEdit (CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber],
2504 current_cell.RowNumber,
2508 private void ShiftSelection (int index)
2510 // we have to save off selection_start
2511 // because ResetSelection clobbers it
2512 int saved_selection_start = selection_start;
2516 selection_start = saved_selection_start;
2518 if (index >= selection_start) {
2519 start = selection_start;
2524 end = selection_start;
2527 if (start == -1) start = 0;
2529 for (int idx = start; idx <= end; idx ++) {
2534 private void ScrollToColumnInPixels (int pixel)
2538 if (pixel > horiz_pixeloffset) // ScrollRight
2539 pixels = -1 * (pixel - horiz_pixeloffset);
2541 pixels = horiz_pixeloffset - pixel;
2543 Rectangle area = cells_area;
2545 if (ColumnHeadersVisible == true) {
2546 area.Y -= ColumnHeadersArea.Height;
2547 area.Height += ColumnHeadersArea.Height;
2550 horiz_pixeloffset = pixel;
2551 UpdateVisibleColumn ();
2555 XplatUI.ScrollWindow (Handle, area, pixels, 0, false);
2557 int pixel_offset = GetColumnStartingPixel (CurrentColumn);
2558 int next_pixel_offset = pixel_offset + CurrentTableStyle.GridColumnStyles[CurrentColumn].Width;
2560 if (pixel_offset >= horiz_pixeloffset
2561 && next_pixel_offset < horiz_pixeloffset + cells_area.Width)
2565 private void ScrollToRow (int old_row, int new_row)
2570 if (new_row > old_row) { // Scrolldown
2571 for (i = old_row; i < new_row; i ++)
2572 pixels -= rows[i].Height;
2575 for (i = new_row; i < old_row; i ++)
2576 pixels += rows[i].Height;
2584 Rectangle rows_area = cells_area; // Cells area - partial rows space
2586 if (RowHeadersVisible) {
2587 rows_area.X -= RowHeaderWidth;
2588 rows_area.Width += RowHeaderWidth;
2591 /* scroll the window */
2592 XplatUI.ScrollWindow (Handle, rows_area, 0, pixels, false);
2594 /* if the row is still */
2595 if (CurrentRow >= first_visible_row && CurrentRow < first_visible_row + visible_row_count)
2599 #endregion Private Instance Methods
2603 static object AllowNavigationChangedEvent = new object ();
2604 static object BackButtonClickEvent = new object ();
2605 static object BackgroundColorChangedEvent = new object ();
2606 static object BorderStyleChangedEvent = new object ();
2607 static object CaptionVisibleChangedEvent = new object ();
2608 static object CurrentCellChangedEvent = new object ();
2609 static object DataSourceChangedEvent = new object ();
2610 static object FlatModeChangedEvent = new object ();
2611 static object NavigateEvent = new object ();
2612 static object ParentRowsLabelStyleChangedEvent = new object ();
2613 static object ParentRowsVisibleChangedEvent = new object ();
2614 static object ReadOnlyChangedEvent = new object ();
2615 static object RowHeaderClickEvent = new object ();
2616 static object ScrollEvent = new object ();
2617 static object ShowParentDetailsButtonClickEvent = new object ();
2619 public event EventHandler AllowNavigationChanged {
2620 add { Events.AddHandler (AllowNavigationChangedEvent, value); }
2621 remove { Events.RemoveHandler (AllowNavigationChangedEvent, value); }
2624 public event EventHandler BackButtonClick {
2625 add { Events.AddHandler (BackButtonClickEvent, value); }
2626 remove { Events.RemoveHandler (BackButtonClickEvent, value); }
2629 public event EventHandler BackgroundColorChanged {
2630 add { Events.AddHandler (BackgroundColorChangedEvent, value); }
2631 remove { Events.RemoveHandler (BackgroundColorChangedEvent, value); }
2635 [EditorBrowsable(EditorBrowsableState.Never)]
2636 public new event EventHandler BackgroundImageChanged {
2637 add { base.BackgroundImageChanged += value; }
2638 remove { base.BackgroundImageChanged -= value; }
2642 [EditorBrowsable(EditorBrowsableState.Never)]
2643 public new event EventHandler TextChanged {
2644 add { base.TextChanged += value; }
2645 remove { base.TextChanged -= value; }
2649 [EditorBrowsable(EditorBrowsableState.Never)]
2650 public new event EventHandler CursorChanged {
2651 add { base.CursorChanged += value; }
2652 remove { base.CursorChanged -= value; }
2655 public event EventHandler BorderStyleChanged {
2656 add { Events.AddHandler (BorderStyleChangedEvent, value); }
2657 remove { Events.RemoveHandler (BorderStyleChangedEvent, value); }
2660 public event EventHandler CaptionVisibleChanged {
2661 add { Events.AddHandler (CaptionVisibleChangedEvent, value); }
2662 remove { Events.RemoveHandler (CaptionVisibleChangedEvent, value); }
2665 public event EventHandler CurrentCellChanged {
2666 add { Events.AddHandler (CurrentCellChangedEvent, value); }
2667 remove { Events.RemoveHandler (CurrentCellChangedEvent, value); }
2670 public event EventHandler DataSourceChanged {
2671 add { Events.AddHandler (DataSourceChangedEvent, value); }
2672 remove { Events.RemoveHandler (DataSourceChangedEvent, value); }
2675 public event EventHandler FlatModeChanged {
2676 add { Events.AddHandler (FlatModeChangedEvent, value); }
2677 remove { Events.RemoveHandler (FlatModeChangedEvent, value); }
2680 public event NavigateEventHandler Navigate {
2681 add { Events.AddHandler (NavigateEvent, value); }
2682 remove { Events.RemoveHandler (NavigateEvent, value); }
2685 public event EventHandler ParentRowsLabelStyleChanged {
2686 add { Events.AddHandler (ParentRowsLabelStyleChangedEvent, value); }
2687 remove { Events.RemoveHandler (ParentRowsLabelStyleChangedEvent, value); }
2690 public event EventHandler ParentRowsVisibleChanged {
2691 add { Events.AddHandler (ParentRowsVisibleChangedEvent, value); }
2692 remove { Events.RemoveHandler (ParentRowsVisibleChangedEvent, value); }
2695 public event EventHandler ReadOnlyChanged {
2696 add { Events.AddHandler (ReadOnlyChangedEvent, value); }
2697 remove { Events.RemoveHandler (ReadOnlyChangedEvent, value); }
2700 protected event EventHandler RowHeaderClick {
2701 add { Events.AddHandler (RowHeaderClickEvent, value); }
2702 remove { Events.RemoveHandler (RowHeaderClickEvent, value); }
2705 public event EventHandler Scroll {
2706 add { Events.AddHandler (ScrollEvent, value); }
2707 remove { Events.RemoveHandler (ScrollEvent, value); }
2710 public event EventHandler ShowParentDetailsButtonClick {
2711 add { Events.AddHandler (ShowParentDetailsButtonClickEvent, value); }
2712 remove { Events.RemoveHandler (ShowParentDetailsButtonClickEvent, value); }
2714 #endregion // Events
2719 #region Code originally in DataGridDrawingLogic.cs
2721 #region Local Variables
2724 Rectangle parent_rows;
2725 int width_of_all_columns;
2727 internal Rectangle caption_area;
2728 internal Rectangle column_headers_area; // Used columns header area
2729 internal int column_headers_max_width; // Total width (max width) for columns headrs
2730 internal Rectangle row_headers_area; // Used Headers rows area
2731 internal Rectangle cells_area;
2732 #endregion // Local Variables
2735 #region Public Instance Methods
2737 // Calc the max with of all columns
2738 int CalcAllColumnsWidth ()
2741 int cnt = CurrentTableStyle.GridColumnStyles.Count;
2743 for (int col = 0; col < cnt; col++) {
2744 if (CurrentTableStyle.GridColumnStyles[col].bound == false) {
2747 width += CurrentTableStyle.GridColumnStyles[col].Width;
2752 // Gets a column from a pixel
2753 int FromPixelToColumn (int pixel, out int column_x)
2756 int cnt = CurrentTableStyle.GridColumnStyles.Count;
2762 if (CurrentTableStyle.CurrentRowHeadersVisible) {
2763 width += row_headers_area.X + row_headers_area.Width;
2764 column_x += row_headers_area.X + row_headers_area.Width;
2767 for (int col = 0; col < cnt; col++) {
2768 if (CurrentTableStyle.GridColumnStyles[col].bound == false)
2771 width += CurrentTableStyle.GridColumnStyles[col].Width;
2776 column_x += CurrentTableStyle.GridColumnStyles[col].Width;
2782 internal int GetColumnStartingPixel (int my_col)
2785 int cnt = CurrentTableStyle.GridColumnStyles.Count;
2787 for (int col = 0; col < cnt; col++) {
2788 if (CurrentTableStyle.GridColumnStyles[col].bound == false) {
2795 width += CurrentTableStyle.GridColumnStyles[col].Width;
2801 // Which column has to be the first visible column to ensure a column visibility
2802 int GetFirstColumnForColumnVisibility (int current_first_visible_column, int column)
2804 int new_col = column;
2807 if (column > current_first_visible_column) { // Going forward
2808 for (new_col = column; new_col >= 0; new_col--){
2809 if (CurrentTableStyle.GridColumnStyles[new_col].bound == false)
2811 width += CurrentTableStyle.GridColumnStyles[new_col].Width;
2813 if (width >= cells_area.Width)
2815 //return new_col < CurrentTableStyle.GridColumnStyles.Count ? new_col + 1 : CurrentTableStyle.GridColumnStyles.Count;
2823 bool in_calc_grid_areas;
2824 void CalcGridAreas ()
2826 if (IsHandleCreated == false) // Delay calculations until the handle is created
2829 /* make sure we don't happen to end up in this method again */
2830 if (in_calc_grid_areas)
2833 in_calc_grid_areas = true;
2835 /* Order is important. E.g. row headers max. height depends on caption */
2836 horiz_pixeloffset = 0;
2839 CalcParentButtons ();
2840 UpdateVisibleRowCount ();
2842 width_of_all_columns = CalcAllColumnsWidth ();
2843 CalcColumnHeaders ();
2846 bool needHoriz = false;
2847 bool needVert = false;
2849 /* figure out which scrollbars we need, and what the visible areas are */
2850 int visible_cells_width = cells_area.Width;
2851 int visible_cells_height = cells_area.Height;
2852 int allrows = RowsCount;
2854 if (ShowEditRow && RowsCount > 0)
2857 /* use a loop to iteratively calculate whether
2858 * we need horiz/vert scrollbars. */
2859 for (int i = 0; i < 3; i ++) {
2861 visible_cells_width = cells_area.Width - vert_scrollbar.Width;
2863 visible_cells_height = cells_area.Height - horiz_scrollbar.Height;
2865 UpdateVisibleRowCount ();
2867 needHoriz = (width_of_all_columns > visible_cells_width);
2868 needVert = (allrows > visible_row_count);
2871 int horiz_scrollbar_width = ClientRectangle.Width;
2872 int horiz_scrollbar_maximum = 0;
2873 int vert_scrollbar_height = 0;
2874 int vert_scrollbar_maximum = 0;
2877 SetUpVerticalScrollBar (out vert_scrollbar_height, out vert_scrollbar_maximum);
2880 SetUpHorizontalScrollBar (out horiz_scrollbar_maximum);
2882 cells_area.Width = visible_cells_width;
2883 cells_area.Height = visible_cells_height;
2885 if (needVert && needHoriz) {
2887 parent_rows.Width -= vert_scrollbar.Width;
2889 if (!ShowingColumnHeaders) {
2890 if (column_headers_area.X + column_headers_area.Width > vert_scrollbar.Location.X) {
2891 column_headers_area.Width -= vert_scrollbar.Width;
2895 horiz_scrollbar_width -= vert_scrollbar.Width;
2896 vert_scrollbar_height -= horiz_scrollbar.Height;
2900 if (row_headers_area.Y + row_headers_area.Height > ClientRectangle.Y + ClientRectangle.Height) {
2901 row_headers_area.Height -= horiz_scrollbar.Height;
2904 vert_scrollbar.Size = new Size (vert_scrollbar.Width,
2905 vert_scrollbar_height);
2907 vert_scrollbar.Maximum = vert_scrollbar_maximum;
2908 Controls.Add (vert_scrollbar);
2909 vert_scrollbar.Visible = true;
2912 Controls.Remove (vert_scrollbar);
2913 vert_scrollbar.Visible = false;
2917 horiz_scrollbar.Size = new Size (horiz_scrollbar_width,
2918 horiz_scrollbar.Height);
2920 horiz_scrollbar.Maximum = horiz_scrollbar_maximum;
2921 Controls.Add (horiz_scrollbar);
2922 horiz_scrollbar.Visible = true;
2925 Controls.Remove (horiz_scrollbar);
2926 horiz_scrollbar.Visible = false;
2929 UpdateVisibleColumn ();
2930 UpdateVisibleRowCount ();
2932 in_calc_grid_areas = false;
2937 caption_area.X = ClientRectangle.X;
2938 caption_area.Y = ClientRectangle.Y;
2939 caption_area.Width = ClientRectangle.Width;
2940 if (caption_visible) {
2941 caption_area.Height = CaptionFont.Height;
2942 if (caption_area.Height < back_button_image.Height)
2943 caption_area.Height = back_button_image.Height;
2944 caption_area.Height += 2;
2947 caption_area.Height = 0;
2950 void CalcCellsArea ()
2952 cells_area.X = ClientRectangle.X + row_headers_area.Width;
2953 cells_area.Y = column_headers_area.Y + column_headers_area.Height;
2954 cells_area.Width = ClientRectangle.X + ClientRectangle.Width - cells_area.X;
2955 if (cells_area.Width < 0)
2956 cells_area.Width = 0;
2957 cells_area.Height = ClientRectangle.Y + ClientRectangle.Height - cells_area.Y;
2958 if (cells_area.Height < 0)
2959 cells_area.Height = 0;
2962 void CalcColumnHeaders ()
2966 column_headers_area.X = ClientRectangle.X;
2967 column_headers_area.Y = parent_rows.Y + parent_rows.Height;
2969 // TODO: take into account Scrollbars
2970 column_headers_max_width = ClientRectangle.X + ClientRectangle.Width - column_headers_area.X;
2971 max_width_cols = column_headers_max_width;
2973 if (CurrentTableStyle.CurrentRowHeadersVisible)
2974 max_width_cols -= RowHeaderWidth;
2976 if (width_of_all_columns > max_width_cols) {
2977 column_headers_area.Width = column_headers_max_width;
2979 column_headers_area.Width = width_of_all_columns;
2981 if (CurrentTableStyle.CurrentRowHeadersVisible)
2982 column_headers_area.Width += RowHeaderWidth;
2985 if (ShowingColumnHeaders)
2986 column_headers_area.Height = CurrentTableStyle.HeaderFont.Height + 6;
2988 column_headers_area.Height = 0;
2991 void CalcParentRows ()
2993 parent_rows.X = ClientRectangle.X;
2994 parent_rows.Y = caption_area.Y + caption_area.Height;
2995 parent_rows.Width = ClientRectangle.Width;
2997 parent_rows.Height = (CaptionFont.Height + 3) * data_source_stack.Count;
2999 parent_rows.Height = 0;
3002 void CalcParentButtons ()
3004 if (data_source_stack.Count > 0 && CaptionVisible) {
3005 back_button_rect = new Rectangle (ClientRectangle.X + ClientRectangle.Width - 2 * (caption_area.Height - 2) - 8,
3006 caption_area.Height / 2 - back_button_image.Height / 2,
3007 back_button_image.Width, back_button_image.Height);
3008 parent_rows_button_rect = new Rectangle (ClientRectangle.X + ClientRectangle.Width - (caption_area.Height - 2) - 4,
3009 caption_area.Height / 2 - parent_rows_button_image.Height / 2,
3010 parent_rows_button_image.Width, parent_rows_button_image.Height);
3013 back_button_rect = parent_rows_button_rect = Rectangle.Empty;
3017 void CalcRowHeaders ()
3019 row_headers_area.X = ClientRectangle.X;
3020 row_headers_area.Y = column_headers_area.Y + column_headers_area.Height;
3021 row_headers_area.Height = ClientRectangle.Height + ClientRectangle.Y - row_headers_area.Y;
3023 if (CurrentTableStyle.CurrentRowHeadersVisible)
3024 row_headers_area.Width = RowHeaderWidth;
3026 row_headers_area.Width = 0;
3029 int GetVisibleRowCount (int visibleHeight)
3031 int rows_height = 0;
3033 for (r = FirstVisibleRow; r < rows.Length; r ++) {
3034 if (rows_height + rows[r].Height >= visibleHeight)
3036 rows_height += rows[r].Height;
3039 if (r < rows.Length - 1)
3042 return r - FirstVisibleRow;
3045 void UpdateVisibleColumn ()
3047 if (CurrentTableStyle.GridColumnStyles.Count == 0) {
3048 visible_column_count = 0;
3053 int max_pixel = horiz_pixeloffset + cells_area.Width;
3056 first_visible_column = FromPixelToColumn (horiz_pixeloffset, out unused);
3058 col = FromPixelToColumn (max_pixel, out unused);
3060 visible_column_count = 1 + col - first_visible_column;
3062 visible_column_count = 0;
3063 for (int i = first_visible_column; i <= col; i ++) {
3064 if (CurrentTableStyle.GridColumnStyles[i].bound)
3065 visible_column_count++;
3068 if (first_visible_column + visible_column_count < CurrentTableStyle.GridColumnStyles.Count) {
3069 visible_column_count++; // Partially visible column
3073 void UpdateVisibleRowCount ()
3075 visible_row_count = GetVisibleRowCount (cells_area.Height);
3077 CalcRowHeaders (); // Height depends on num of visible rows
3081 void InvalidateCaption ()
3083 if (caption_area.IsEmpty)
3086 Invalidate (caption_area);
3089 void InvalidateRow (int row)
3091 if (row < FirstVisibleRow || row > FirstVisibleRow + VisibleRowCount)
3094 Rectangle rect_row = new Rectangle ();
3096 rect_row.X = cells_area.X;
3097 rect_row.Width = width_of_all_columns;
3098 if (rect_row.Width > cells_area.Width)
3099 rect_row.Width = cells_area.Width;
3100 rect_row.Height = rows[row].Height;
3101 rect_row.Y = cells_area.Y + rows[row].VerticalOffset - rows[FirstVisibleRow].VerticalOffset;
3102 Invalidate (rect_row);
3105 void InvalidateRowHeader (int row)
3107 Rectangle rect_rowhdr = new Rectangle ();
3108 rect_rowhdr.X = row_headers_area.X;
3109 rect_rowhdr.Width = row_headers_area.Width;
3110 rect_rowhdr.Height = rows[row].Height;
3111 rect_rowhdr.Y = row_headers_area.Y + rows[row].VerticalOffset - rows[FirstVisibleRow].VerticalOffset;
3112 Invalidate (rect_rowhdr);
3115 internal void InvalidateColumn (DataGridColumnStyle column)
3117 Rectangle rect_col = new Rectangle ();
3121 col = CurrentTableStyle.GridColumnStyles.IndexOf (column);
3126 rect_col.Width = column.Width;
3127 col_pixel = GetColumnStartingPixel (col);
3128 rect_col.X = cells_area.X + col_pixel - horiz_pixeloffset;
3129 rect_col.Y = cells_area.Y;
3130 rect_col.Height = cells_area.Height;
3131 Invalidate (rect_col);
3134 void DrawResizeLineVert (int x)
3136 XplatUI.DrawReversibleRectangle (Handle,
3137 new Rectangle (x, cells_area.Y, 1, cells_area.Height - 3),
3141 void DrawResizeLineHoriz (int y)
3143 XplatUI.DrawReversibleRectangle (Handle,
3144 new Rectangle (cells_area.X, y, cells_area.Width - 3, 1),
3148 void SetUpHorizontalScrollBar (out int maximum)
3150 maximum = width_of_all_columns;
3152 horiz_scrollbar.Location = new Point (ClientRectangle.X, ClientRectangle.Y +
3153 ClientRectangle.Height - horiz_scrollbar.Height);
3155 horiz_scrollbar.LargeChange = cells_area.Width;
3159 void SetUpVerticalScrollBar (out int height, out int maximum)
3163 y = ClientRectangle.Y + parent_rows.Y + parent_rows.Height;
3164 height = ClientRectangle.Height - parent_rows.Y - parent_rows.Height;
3166 vert_scrollbar.Location = new Point (ClientRectangle.X +
3167 ClientRectangle.Width - vert_scrollbar.Width, y);
3169 maximum = RowsCount;
3171 if (ShowEditRow && RowsCount > 0) {
3175 vert_scrollbar.LargeChange = VLargeChange;
3178 #endregion // Public Instance Methods
3180 #region Instance Properties
3181 // Returns the ColumnHeaders area excluding the rectangle shared with RowHeaders
3182 internal Rectangle ColumnHeadersArea {
3184 Rectangle columns_area = column_headers_area;
3186 if (CurrentTableStyle.CurrentRowHeadersVisible) {
3187 columns_area.X += RowHeaderWidth;
3188 columns_area.Width -= RowHeaderWidth;
3190 return columns_area;
3194 bool ShowingColumnHeaders {
3195 get { return ColumnHeadersVisible && CurrentTableStyle.GridColumnStyles.Count > 0; }
3198 internal Rectangle RowHeadersArea {
3199 get { return row_headers_area; }
3202 internal Rectangle ParentRowsArea {
3203 get { return parent_rows; }
3207 get { return VisibleRowCount; }
3210 #endregion Instance Properties
3212 #endregion // Code originally in DataGridDrawingLogic.cs