2008-03-27 Carlos Alberto Cortez <calberto.cortez@gmail.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / DataGrid.cs
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:
8 //
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 //
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.
19 //
20 // Copyright (c) 2005,2006 Novell, Inc. (http://www.novell.com)
21 //
22 // Authors:
23 //      Jordi Mas i Hernandez   <jordi@ximian.com>
24 //      Chris Toshok            <toshok@ximian.com>
25 //
26 //
27
28 using System;
29 using System.ComponentModel;
30 using System.Data;
31 using System.Drawing;
32 using System.Runtime.InteropServices;
33 using System.Collections;
34 using System.Text;
35
36 namespace System.Windows.Forms
37 {
38         internal class DataGridRelationshipRow {
39                 DataGrid owner;
40
41                 public DataGridRelationshipRow (DataGrid owner)
42                 {
43                         this.owner = owner;
44                         IsSelected = false;
45                         IsExpanded = false;
46                         height = 0;
47                         VerticalOffset = 0;
48                         RelationHeight = 0;
49                         relation_area = Rectangle.Empty;
50                 }
51
52                 public int height;
53
54                 /* this needs to be a property so that the Autosize
55                  * example from the Windows.Forms FAQ will work */
56                 public int Height {
57                         get { return height; }
58                         set {
59                                 if (height != value) {
60                                         height = value;
61                                         owner.UpdateRowsFrom (this);
62                                 }
63                         }
64                 }
65
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 */
71         }
72
73         internal class DataGridDataSource
74         {
75                 public DataGrid owner;
76                 public CurrencyManager list_manager;
77                 public object view;
78                 public string data_member;
79                 public object data_source;
80                 public DataGridCell current;
81
82                 public DataGridDataSource (DataGrid owner, CurrencyManager list_manager, object data_source, string data_member, object view_data, DataGridCell current)
83                 {
84                         this.owner = owner;
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;
90                 }
91
92                 DataGridRelationshipRow[] rows;
93                 public DataGridRelationshipRow[] Rows {
94                         get { return rows; }
95                         set { rows = value; }
96                 }
97
98                 Hashtable selected_rows;
99                 public Hashtable SelectedRows {
100                         get { return selected_rows; }
101                         set { selected_rows = value; }
102                 }
103
104                 int selection_start;
105                 public int SelectionStart {
106                         get { return selection_start; }
107                         set { selection_start = value; }
108                 }
109         }
110
111         [DefaultEvent("Navigate")]
112         [DefaultProperty("DataSource")]
113         [Designer("System.Windows.Forms.Design.DataGridDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
114 #if NET_2_0
115         [ComplexBindingProperties ("DataSource", "DataMember")]
116         [ClassInterface (ClassInterfaceType.AutoDispatch)]
117         [ComVisible (true)]
118 #endif
119         public class DataGrid : Control, ISupportInitialize, IDataGridEditingService
120         {
121                 [Flags]
122 #if !NET_2_0
123                 [Serializable]
124 #endif
125                 public enum HitTestType
126                 {
127                         None            = 0,
128                         Cell            = 1,
129                         ColumnHeader    = 2,
130                         RowHeader       = 4,
131                         ColumnResize    = 8,
132                         RowResize       = 16,
133                         Caption         = 32,
134                         ParentRows      = 64
135                 }
136
137                 public sealed class HitTestInfo
138                 {
139                         public static readonly HitTestInfo Nowhere = null;
140
141                         int row;
142                         int column;
143                         DataGrid.HitTestType type;
144
145                         #region Private Constructors
146                         internal HitTestInfo () : this (-1, -1, HitTestType.None)
147                         {
148                         }
149
150                         internal HitTestInfo (int row, int column, DataGrid.HitTestType type)
151                         {
152                                 this.row = row;
153                                 this.column = column;
154                                 this.type = type;
155                         }
156                         #endregion
157
158
159                         #region Public Instance Properties
160                         public int Column {
161                                 get { return column; }
162                         }
163
164                         public int Row {
165                                 get { return row; }
166                         }
167                         public DataGrid.HitTestType Type {
168                                 get { return type; }
169                         }
170                         #endregion //Public Instance Properties
171
172                         public override bool Equals (object value)
173                         {
174                                 if (!(value is HitTestInfo))
175                                         return false;
176
177                                 HitTestInfo obj = (HitTestInfo) value;
178                                 return (obj.Column == column && obj.Row == row && obj.Type ==type);
179                         }
180
181                         public override int GetHashCode ()
182                         {
183                                 return row ^ column;
184                         }
185
186                         public override string ToString ()
187                         {
188                                 return "{ " + type + "," + row + "," + column + "}";
189                         }
190                 }
191
192                 #region Local Variables
193                 /* cached theme defaults */
194                 static readonly Color   def_background_color = ThemeEngine.Current.DataGridBackgroundColor;
195                 static readonly Color   def_caption_backcolor = ThemeEngine.Current.DataGridCaptionBackColor;
196                 static readonly Color   def_caption_forecolor = ThemeEngine.Current.DataGridCaptionForeColor;
197                 static readonly Color   def_parent_rows_backcolor = ThemeEngine.Current.DataGridParentRowsBackColor;
198                 static readonly Color   def_parent_rows_forecolor = ThemeEngine.Current.DataGridParentRowsForeColor;
199
200                 /* colors */
201                 // XXX this needs addressing. Control.background_color should not be internal.
202                 new Color background_color;
203                 Color caption_backcolor;
204                 Color caption_forecolor;
205                 Color parent_rows_backcolor;
206                 Color parent_rows_forecolor;
207
208                 /* flags to determine which areas of the datagrid are shown */
209                 bool caption_visible;
210                 bool parent_rows_visible;
211
212                 GridTableStylesCollection styles_collection;
213                 DataGridParentRowsLabelStyle parent_rows_label_style;
214                 DataGridTableStyle default_style;
215                 DataGridTableStyle grid_style;
216                 DataGridTableStyle current_style;
217
218                 /* selection */
219                 DataGridCell current_cell;
220                 Hashtable selected_rows;
221                 int selection_start; // used for range selection
222
223                 /* layout/rendering */
224                 bool allow_navigation;
225                 int first_visible_row;
226                 int first_visible_column;
227                 int visible_row_count;
228                 int visible_column_count;
229                 Font caption_font;
230                 string caption_text;
231                 bool flatmode;
232                 HScrollBar horiz_scrollbar;
233                 VScrollBar vert_scrollbar;
234                 int horiz_pixeloffset;
235
236                 internal Bitmap back_button_image;
237                 internal Rectangle back_button_rect;
238                 internal bool back_button_mouseover;
239                 internal bool back_button_active;
240                 internal Bitmap parent_rows_button_image;
241                 internal Rectangle parent_rows_button_rect;
242                 internal bool parent_rows_button_mouseover;
243                 internal bool parent_rows_button_active;
244
245                 /* databinding */
246                 object datasource;
247                 string datamember;
248                 CurrencyManager list_manager;
249                 bool refetch_list_manager = true;
250                 bool _readonly;
251                 DataGridRelationshipRow[] rows;
252
253                 /* column resize fields */
254                 bool column_resize_active;
255                 int resize_column_x;
256                 int resize_column_width_delta;
257                 int resize_column;
258                 
259                 /* row resize fields */
260                 bool row_resize_active;
261                 int resize_row_y;
262                 int resize_row_height_delta;
263                 int resize_row;
264
265                 /* used to make sure we don't endlessly recurse calling set_CurrentCell and OnListManagerPositionChanged */
266                 bool from_positionchanged_handler;
267
268                 /* editing state */
269                 bool cursor_in_add_row;
270                 bool add_row_changed;
271                 bool is_editing;                // Current cell is edit mode
272                 bool is_changing;
273
274                 internal Stack data_source_stack;
275
276                 #endregion // Local Variables
277
278                 #region Public Constructors
279                 public DataGrid ()
280                 {
281                         allow_navigation = true;
282                         background_color = def_background_color;
283                         border_style = BorderStyle.Fixed3D;
284                         caption_backcolor = def_caption_backcolor;
285                         caption_forecolor = def_caption_forecolor;
286                         caption_text = string.Empty;
287                         caption_visible = true;
288                         datamember = string.Empty;
289                         parent_rows_backcolor = def_parent_rows_backcolor;
290                         parent_rows_forecolor = def_parent_rows_forecolor;
291                         parent_rows_visible = true;
292                         current_cell = new DataGridCell ();
293                         parent_rows_label_style = DataGridParentRowsLabelStyle.Both;
294                         selected_rows = new Hashtable ();
295                         selection_start = -1;
296                         rows = new DataGridRelationshipRow [0];
297
298                         default_style = new DataGridTableStyle (true);
299                         grid_style = new DataGridTableStyle ();
300
301                         styles_collection = new GridTableStylesCollection (this);
302                         styles_collection.CollectionChanged += new CollectionChangeEventHandler (OnTableStylesCollectionChanged);
303
304                         CurrentTableStyle = grid_style;
305
306                         horiz_scrollbar = new ImplicitHScrollBar ();
307                         horiz_scrollbar.Scroll += new ScrollEventHandler (GridHScrolled);
308                         vert_scrollbar = new ImplicitVScrollBar ();
309                         vert_scrollbar.Scroll += new ScrollEventHandler (GridVScrolled);
310
311                         SetStyle (ControlStyles.UserMouse, true);
312
313                         data_source_stack = new Stack ();
314
315                         back_button_image = ResourceImageLoader.Get ("go-previous.png");
316                         back_button_image.MakeTransparent (Color.Transparent);
317                         parent_rows_button_image = ResourceImageLoader.Get ("go-top.png");
318                         parent_rows_button_image.MakeTransparent (Color.Transparent);
319                 }
320
321                 #endregion      // Public Constructor
322
323                 #region Public Instance Properties
324
325                 [DefaultValue(true)]
326                 public bool AllowNavigation {
327                         get { return allow_navigation; }
328                         set {
329                                 if (allow_navigation != value) {
330                                         allow_navigation = value;
331                                         OnAllowNavigationChanged (EventArgs.Empty);
332                                 }
333                         }
334                 }
335
336                 [DefaultValue(true)]
337                 public bool AllowSorting {
338                         get { return grid_style.AllowSorting; }
339                         set { grid_style.AllowSorting = value; }
340                 }
341
342                 public Color AlternatingBackColor {
343                         get { return grid_style.AlternatingBackColor; }
344                         set { grid_style.AlternatingBackColor = value; }
345                 }
346
347                 public override Color BackColor {
348                         get { return grid_style.BackColor; }
349                         set { grid_style.BackColor = value; }
350                 }
351
352                 public Color BackgroundColor {
353                         get { return background_color; }
354                         set {
355                                  if (background_color != value) {
356                                         background_color = value;
357                                         OnBackgroundColorChanged (EventArgs.Empty);
358                                         Invalidate ();
359                                 }
360                         }
361                 }
362
363                 [Browsable(false)]
364                 [EditorBrowsable(EditorBrowsableState.Never)]
365                 public override Image BackgroundImage {
366                         get { return base.BackgroundImage; }
367                         set {
368                                 if (base.BackgroundImage == value)
369                                         return;
370
371                                 base.BackgroundImage = value;
372                                 Invalidate ();
373                         }
374                 }
375
376 #if NET_2_0
377                 [Browsable (false)]
378                 [EditorBrowsable (EditorBrowsableState.Never)]
379                 public override ImageLayout BackgroundImageLayout {
380                         get { return base.BackgroundImageLayout; }
381                         set { base.BackgroundImageLayout = value; }
382                 }
383 #endif
384
385                 [DispId(-504)]
386                 [DefaultValue(BorderStyle.Fixed3D)]
387                 public BorderStyle BorderStyle {
388                         get { return InternalBorderStyle; }
389                         set { 
390                                 InternalBorderStyle = value; 
391                                 CalcAreasAndInvalidate ();
392                                 OnBorderStyleChanged (EventArgs.Empty);
393                         }
394                 }
395
396                 public Color CaptionBackColor {
397                         get { return caption_backcolor; }
398                         set {
399                                 if (caption_backcolor != value) {
400                                         caption_backcolor = value;
401                                         InvalidateCaption ();
402                                 }
403                         }
404                 }
405
406                 [Localizable(true)]
407                 [AmbientValue(null)]
408                 public Font CaptionFont {
409                         get {
410                                 if (caption_font == null)
411                                         return new Font (Font, FontStyle.Bold);
412
413                                 return caption_font;
414                         }
415                         set {
416                                 if (caption_font != null && caption_font.Equals (value))
417                                         return;
418
419                                 caption_font = value;
420                                 CalcAreasAndInvalidate ();
421                         }
422                 }
423
424                 public Color CaptionForeColor {
425                         get { return caption_forecolor; }
426                         set {
427                                 if (caption_forecolor != value) {
428                                         caption_forecolor = value;
429                                         InvalidateCaption ();
430                                 }
431                         }
432                 }
433
434                 [Localizable(true)]
435                 [DefaultValue("")]
436                 public string CaptionText {
437                         get { return caption_text; }
438                         set {
439                                 if (caption_text != value) {
440                                         caption_text = value;
441                                         InvalidateCaption ();
442                                 }
443                         }
444                 }
445
446                 [DefaultValue(true)]
447                 public bool CaptionVisible {
448                         get { return caption_visible; }
449                         set {
450                                 if (caption_visible != value) {
451                                         EndEdit ();
452                                         caption_visible = value;
453                                         CalcAreasAndInvalidate ();
454                                         OnCaptionVisibleChanged (EventArgs.Empty);
455                                 }
456                         }
457                 }
458
459                 [DefaultValue(true)]
460                 public bool ColumnHeadersVisible {
461                         get { return grid_style.ColumnHeadersVisible; }
462                         set { grid_style.ColumnHeadersVisible = value; }
463                 }
464
465                 bool setting_current_cell;
466
467                 [Browsable(false)]
468                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
469                 public DataGridCell CurrentCell {
470                         get { return current_cell; }
471                         set {
472                                 if (setting_current_cell)
473                                         return;
474                                 setting_current_cell = true;
475
476                                 if (!IsHandleCreated) {
477                                         setting_current_cell = false;
478                                         throw new Exception ("CurrentCell cannot be set at this time.");
479                                 }
480
481                                 if (current_cell.Equals (value)) {
482                                         setting_current_cell = false;
483                                         return;
484                                 }
485
486                                 /* make sure the new cell fits in the correct bounds for [row,column] */
487                                 if (ReadOnly && value.RowNumber > RowsCount - 1)
488                                         value.RowNumber = RowsCount - 1;
489                                 else if (value.RowNumber > RowsCount)
490                                         value.RowNumber = RowsCount;
491                                 if (value.ColumnNumber >= CurrentTableStyle.GridColumnStyles.Count)
492                                         value.ColumnNumber = CurrentTableStyle.GridColumnStyles.Count == 0 ? 0 : CurrentTableStyle.GridColumnStyles.Count - 1;
493
494
495                                 /* now make sure we don't go negative */
496                                 if (value.RowNumber < 0) value.RowNumber = 0;
497                                 if (value.ColumnNumber < 0) value.ColumnNumber = 0;
498
499                                 bool was_changing = is_changing;
500
501                                 add_row_changed = add_row_changed || was_changing;
502
503                                 EndEdit ();
504                                 if (value.RowNumber != current_cell.RowNumber) {
505                                         if (!from_positionchanged_handler) {
506                                                 try {
507                                                         ListManager.EndCurrentEdit ();
508                                                 }
509                                                 catch (Exception e) {
510                                                         DialogResult r = MessageBox.Show (String.Format ("{0} Do you wish to correct the value?", e.Message),
511                                                                                           "Error when committing the row to the original data source",
512                                                                                           MessageBoxButtons.YesNo);
513                                                         if (r == DialogResult.Yes) {
514                                                                 Edit ();
515                                                                 return;
516                                                         }
517                                                         else
518                                                                 ListManager.CancelCurrentEdit ();
519                                                 }
520                                         }
521
522                                         if (value.RowNumber == RowsCount && !ListManager.CanAddRows)
523                                                 value.RowNumber --;
524                                 }
525
526                                 int old_row = current_cell.RowNumber;
527
528                                 current_cell = value;
529
530                                 EnsureCellVisibility (value);
531
532                                 if (CurrentRow == RowsCount && ListManager.CanAddRows) {
533                                         cursor_in_add_row = true;
534                                         add_row_changed = false;
535                                         AddNewRow ();
536                                 }
537                                 else {
538                                         cursor_in_add_row = false;
539                                 }
540
541                                 InvalidateRowHeader (old_row);
542                                 InvalidateRowHeader (current_cell.RowNumber);
543
544                                 list_manager.Position = current_cell.RowNumber;
545
546                                 OnCurrentCellChanged (EventArgs.Empty);
547
548                                 if (!from_positionchanged_handler)
549                                         Edit ();
550
551                                 setting_current_cell = false;
552                         }
553                 }
554
555                 int CurrentRow {
556                         get { return current_cell.RowNumber; }
557                         set { CurrentCell = new DataGridCell (value, current_cell.ColumnNumber); }
558                 }
559
560                 int CurrentColumn {
561                         get { return current_cell.ColumnNumber; }
562                         set { CurrentCell = new DataGridCell (current_cell.RowNumber, value); }
563                 }
564
565                 [Browsable(false)]
566                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
567                 public int CurrentRowIndex {
568                         get {
569                                 if (ListManager == null)
570                                         return -1;
571                                 
572                                 return CurrentRow;
573                         }
574                         set { CurrentRow = value; }
575                 }
576
577                 [Browsable(false)]
578                 [EditorBrowsable(EditorBrowsableState.Never)]
579                 public override Cursor Cursor {
580                         get { return base.Cursor; }
581                         set { base.Cursor = value; }
582                 }
583
584                 [DefaultValue(null)]
585                 [Editor ("System.Windows.Forms.Design.DataMemberListEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
586                 public string DataMember {
587                         get { return datamember; }
588                         set {
589                                 if (BindingContext != null) {
590                                         SetDataSource (datasource, value);
591                                 }
592                                 else {
593                                         if (list_manager != null)
594                                                 list_manager = null;
595                                         datamember = value;
596                                         refetch_list_manager = true;
597                                 }
598                         }
599                 }
600
601                 [DefaultValue(null)]
602                 [RefreshProperties(RefreshProperties.Repaint)]
603 #if NET_2_0
604                 [AttributeProvider (typeof (IListSource))]
605 #else
606                 [TypeConverter("System.Windows.Forms.Design.DataSourceConverter, " + Consts.AssemblySystem_Design)]
607 #endif
608                 public object DataSource {
609                         get { return datasource; }
610                         set {
611                                 if (BindingContext != null) {
612                                         SetDataSource (value, ListManager == null ? datamember : string.Empty);
613                                 }
614                                 else {
615                                         datasource = value;
616                                         if (list_manager != null)
617                                                 datamember = string.Empty;
618
619                                         if (list_manager != null)
620                                                 list_manager = null;
621                                         refetch_list_manager = true;
622                                 }
623                         }
624                 }
625
626                 protected override Size DefaultSize {
627                         get { return new Size (130, 80); }
628                 }
629
630                 [Browsable(false)]
631                 public int FirstVisibleColumn {
632                         get { return first_visible_column; }
633                 }
634
635                 [DefaultValue(false)]
636                 public bool FlatMode {
637                         get { return flatmode; }
638                         set {
639                                 if (flatmode != value) {
640                                         flatmode = value;
641                                         OnFlatModeChanged (EventArgs.Empty);
642                                         Refresh ();
643                                 }
644                         }
645                 }
646
647                 public override Color ForeColor {
648                         get { return grid_style.ForeColor; }
649                         set { grid_style.ForeColor = value; }
650                 }
651
652                 public Color GridLineColor {
653                         get { return grid_style.GridLineColor; }
654                         set {
655                                 if (value == Color.Empty)
656                                         throw new ArgumentException ("Color.Empty value is invalid.");
657
658                                 grid_style.GridLineColor = value;
659                         }
660                 }
661
662                 [DefaultValue(DataGridLineStyle.Solid)]
663                 public DataGridLineStyle GridLineStyle {
664                         get { return grid_style.GridLineStyle; }
665                         set { grid_style.GridLineStyle = value; }
666                 }
667
668                 public Color HeaderBackColor {
669                         get { return grid_style.HeaderBackColor; }
670                         set {
671                                 if (value == Color.Empty)
672                                         throw new ArgumentException ("Color.Empty value is invalid.");
673
674                                 grid_style.HeaderBackColor = value;
675                         }
676                 }
677
678                 public Font HeaderFont {
679                         get { return grid_style.HeaderFont; }
680                         set { grid_style.HeaderFont = value; }
681                 }
682
683                 public Color HeaderForeColor {
684                         get { return grid_style.HeaderForeColor; }
685                         set { grid_style.HeaderForeColor = value; }
686                 }
687
688                 protected ScrollBar HorizScrollBar {
689                         get { return horiz_scrollbar; }
690                 }
691                 internal ScrollBar HScrollBar {
692                         get { return horiz_scrollbar; }
693                 }
694
695                 internal int HorizPixelOffset {
696                         get { return horiz_pixeloffset; }
697                 }
698
699                 internal bool IsChanging {
700                         get { return is_changing; }
701                 }
702
703                 public object this [DataGridCell cell] {
704                         get { return this [cell.RowNumber, cell.ColumnNumber]; }
705                         set { this [cell.RowNumber, cell.ColumnNumber] = value; }
706                 }
707
708                 public object this [int rowIndex, int columnIndex] {
709                         get { return CurrentTableStyle.GridColumnStyles[columnIndex].GetColumnValueAtRow (ListManager,
710                                                                                                           rowIndex); }
711                         set { CurrentTableStyle.GridColumnStyles[columnIndex].SetColumnValueAtRow (ListManager,
712                                                                                                    rowIndex, value); }
713                 }
714
715                 public Color LinkColor {
716                         get { return grid_style.LinkColor; }
717                         set { grid_style.LinkColor = value; }
718                 }
719
720                 internal Font LinkFont {
721                         get { return new Font (Font, FontStyle.Underline); }
722                 }
723
724 #if !NET_2_0
725                 [ComVisible(false)]
726 #endif
727                 [Browsable(false)]
728                 [EditorBrowsable(EditorBrowsableState.Never)]
729                 public Color LinkHoverColor {
730                         get { return grid_style.LinkHoverColor; }
731                         set { grid_style.LinkHoverColor = value; }
732                 }
733
734                 [Browsable(false)]
735                 [EditorBrowsable(EditorBrowsableState.Advanced)]
736                 protected internal CurrencyManager ListManager {
737                         get {
738                                 if (list_manager == null && refetch_list_manager) {
739                                         SetDataSource (datasource, datamember);
740                                         refetch_list_manager = false;
741                                 }
742
743                                 return list_manager;
744                         }
745                         set { throw new NotSupportedException ("Operation is not supported."); }
746                 }
747
748                 public Color ParentRowsBackColor {
749                         get { return parent_rows_backcolor; }
750                         set {
751                                 if (parent_rows_backcolor != value) {
752                                         parent_rows_backcolor = value;
753                                         if (parent_rows_visible) {
754                                                 Refresh ();
755                                         }
756                                 }
757                         }
758                 }
759
760                 public Color ParentRowsForeColor {
761                         get { return parent_rows_forecolor; }
762                         set {
763                                 if (parent_rows_forecolor != value) {
764                                         parent_rows_forecolor = value;
765                                         if (parent_rows_visible) {
766                                                 Refresh ();
767                                         }
768                                 }
769                         }
770                 }
771
772                 [DefaultValue(DataGridParentRowsLabelStyle.Both)]
773                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
774                 public DataGridParentRowsLabelStyle ParentRowsLabelStyle {
775                         get { return parent_rows_label_style; }
776                         set {
777                                 if (parent_rows_label_style != value) {
778                                         parent_rows_label_style = value;
779                                         if (parent_rows_visible) {
780                                                 Refresh ();
781                                         }
782
783                                         OnParentRowsLabelStyleChanged (EventArgs.Empty);
784                                 }
785                         }
786                 }
787
788                 [DefaultValue(true)]
789                 public bool ParentRowsVisible {
790                         get { return parent_rows_visible; }
791                         set {
792                                 if (parent_rows_visible != value) {
793                                         parent_rows_visible = value;
794                                         CalcAreasAndInvalidate ();
795                                         OnParentRowsVisibleChanged (EventArgs.Empty);
796                                 }
797                         }
798                 }
799
800                 // Settting this property seems to have no effect.
801                 [DefaultValue(75)]
802                 [TypeConverter(typeof(DataGridPreferredColumnWidthTypeConverter))]
803                 public int PreferredColumnWidth {
804                         get { return grid_style.PreferredColumnWidth; }
805                         set { grid_style.PreferredColumnWidth = value; }
806                 }
807
808                 public int PreferredRowHeight {
809                         get { return grid_style.PreferredRowHeight; }
810                         set { grid_style.PreferredRowHeight = value; }
811                 }
812
813                 [DefaultValue(false)]
814                 public bool ReadOnly {
815                         get { return _readonly; }
816                         set {
817                                 if (_readonly != value) {
818                                         _readonly = value;
819                                         OnReadOnlyChanged (EventArgs.Empty);
820                                         CalcAreasAndInvalidate ();
821                                 }
822                         }
823                 }
824
825                 [DefaultValue(true)]
826                 public bool RowHeadersVisible {
827                         get { return grid_style.RowHeadersVisible; }
828                         set { grid_style.RowHeadersVisible = value; }
829                 }
830
831                 [DefaultValue(35)]
832                 public int RowHeaderWidth {
833                         get { return grid_style.RowHeaderWidth; }
834                         set { grid_style.RowHeaderWidth = value; }
835                 }
836
837                 internal DataGridRelationshipRow[] DataGridRows {
838                         get { return rows; }
839                 }
840
841
842                 public Color SelectionBackColor {
843                         get { return grid_style.SelectionBackColor; }
844                         set { grid_style.SelectionBackColor = value; }
845                 }
846
847                 public Color SelectionForeColor {
848                         get { return grid_style.SelectionForeColor; }
849                         set { grid_style.SelectionForeColor = value; }
850                 }
851
852                 public override ISite Site {
853                         get { return base.Site; }
854                         set { base.Site = value; }
855                 }
856
857                 [Localizable(true)]
858                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
859                 public GridTableStylesCollection TableStyles {
860                         get { return styles_collection; }
861                 }
862
863                 [Bindable(false)]
864                 [Browsable(false)]
865                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
866                 [EditorBrowsable(EditorBrowsableState.Never)]
867                 public override string Text {
868                         get { return base.Text; }
869                         set { base.Text = value; }
870                 }
871
872                 [Browsable(false)]
873                 [EditorBrowsable(EditorBrowsableState.Advanced)]
874                 protected ScrollBar VertScrollBar {
875                         get { return vert_scrollbar; }
876                 }
877                 internal ScrollBar VScrollBar {
878                         get { return vert_scrollbar; }
879                 }
880
881                 [Browsable(false)]
882                 public int VisibleColumnCount {
883                         get { return visible_column_count; }
884                 }
885
886                 [Browsable(false)]
887                 public int VisibleRowCount {
888                         get { return visible_row_count; }
889                 }
890
891                 #endregion      // Public Instance Properties
892
893                 #region Private Instance Properties
894                 internal DataGridTableStyle CurrentTableStyle {
895                         get { return current_style; }
896                         set {
897                                 if (current_style != value) {
898                                         if (current_style != null)
899                                                 DisconnectTableStyleEvents ();
900
901                                         current_style = value;
902
903                                         if (current_style != null) {
904                                                 current_style.DataGrid = this;
905                                                 ConnectTableStyleEvents ();
906                                         }
907                                         CalcAreasAndInvalidate ();
908                                 }
909                         }
910                 }
911
912                 internal int FirstVisibleRow {
913                         get { return first_visible_row; }
914                 }
915                 
916                 internal int RowsCount {
917                         get { return ListManager != null ? ListManager.Count : 0; }
918                 }
919
920                 internal int RowHeight {
921                         get {
922                                 if (CurrentTableStyle.CurrentPreferredRowHeight > Font.Height + 3 + 1 /* line */)
923                                         return CurrentTableStyle.CurrentPreferredRowHeight;
924                                 else
925                                         return Font.Height + 3 + 1 /* line */;
926                         }
927                 }
928                 
929                 internal override bool ScaleChildrenInternal {
930                         get { return false; }
931                 }
932
933                 internal bool ShowEditRow {
934                         get {
935                                 if (ListManager != null && !ListManager.CanAddRows)
936                                         return false;
937
938                                 return !_readonly;
939                         }
940                 }
941                 
942                 internal bool ShowParentRows {
943                         get { return ParentRowsVisible && data_source_stack.Count > 0; }
944                 }
945                 
946                 #endregion Private Instance Properties
947
948                 #region Public Instance Methods
949
950                 void AbortEditing ()
951                 {
952                         if (is_changing) {
953                                 CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber].Abort (current_cell.RowNumber);
954                                 is_changing = false;
955                                 InvalidateRowHeader (current_cell.RowNumber);
956                         }
957                 }
958
959                 [MonoTODO]
960                 public bool BeginEdit (DataGridColumnStyle gridColumn, int rowNumber)
961                 {
962                         if (is_changing)
963                                 return false;
964
965                         int column = CurrentTableStyle.GridColumnStyles.IndexOf (gridColumn);
966                         if (column < 0)
967                                 return false;
968
969                         CurrentCell = new DataGridCell (rowNumber, column);
970
971                         /* force editing of CurrentCell if we aren't already editing */
972                         Edit ();
973
974                         return true;
975                 }
976
977                 public void BeginInit ()
978                 {
979                 }
980
981                 protected virtual void CancelEditing ()
982                 {
983                         if (CurrentTableStyle.GridColumnStyles.Count == 0)
984                                 return;
985
986                         CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber].ConcedeFocus ();
987
988                         if (is_changing) {
989                                 if (current_cell.ColumnNumber < CurrentTableStyle.GridColumnStyles.Count)
990                                         CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber].Abort (current_cell.RowNumber);
991                                 InvalidateRowHeader (current_cell.RowNumber);
992                         }
993
994                         if (cursor_in_add_row && !is_changing) {
995                                 ListManager.CancelCurrentEdit ();
996                         }
997
998                         is_changing = false;
999                         is_editing = false;
1000                 }
1001
1002                 [MonoTODO]
1003                 public void Collapse (int row)
1004                 {
1005                         if (!rows[row].IsExpanded)
1006                                 return;
1007
1008                         SuspendLayout ();
1009                         rows[row].IsExpanded = false;
1010                         for (int i = 1; i < rows.Length - row; i ++)
1011                                 rows[row + i].VerticalOffset -= rows[row].RelationHeight;
1012
1013                         rows[row].height -= rows[row].RelationHeight;
1014                         rows[row].RelationHeight = 0;
1015                         ResumeLayout (false);
1016
1017                         /* XX need to redraw from @row down */
1018                         CalcAreasAndInvalidate ();
1019                 }
1020
1021                 protected internal virtual void ColumnStartedEditing (Control editingControl)
1022                 {
1023                         ColumnStartedEditing (editingControl.Bounds);
1024                 }
1025
1026                 protected internal virtual void ColumnStartedEditing (Rectangle bounds)
1027                 {
1028                         bool need_invalidate = is_changing == false;
1029                         // XXX calculate the row header to invalidate
1030                         // instead of using CurrentRow
1031                         is_changing = true;
1032
1033                         if (cursor_in_add_row && need_invalidate)
1034                                 RecreateDataGridRows (true);
1035
1036                         if (need_invalidate)
1037                                 InvalidateRowHeader (CurrentRow);
1038                 }
1039
1040                 protected override AccessibleObject CreateAccessibilityInstance ()
1041                 {
1042                         return base.CreateAccessibilityInstance ();
1043                 }
1044
1045                 protected virtual DataGridColumnStyle CreateGridColumn (PropertyDescriptor prop)
1046                 {
1047                         return CreateGridColumn (prop, false);
1048                 }
1049
1050                 protected virtual DataGridColumnStyle CreateGridColumn (PropertyDescriptor prop, bool isDefault)
1051                 {
1052                         throw new NotImplementedException();
1053                 }
1054
1055                 protected override void Dispose (bool disposing)
1056                 {
1057                         base.Dispose (disposing);
1058                 }
1059
1060                 public bool EndEdit (DataGridColumnStyle gridColumn, int rowNumber, bool shouldAbort)
1061                 {
1062                         if (shouldAbort || (_readonly || gridColumn.TableStyleReadOnly || gridColumn.ReadOnly))
1063                                 gridColumn.Abort (rowNumber);
1064                         else {
1065                                 gridColumn.Commit (ListManager, rowNumber);
1066                                 gridColumn.ConcedeFocus ();
1067                         }
1068
1069                         if (is_editing || is_changing) {
1070                                 is_editing = false;
1071                                 is_changing = false;
1072                                 InvalidateRowHeader (rowNumber);
1073                         }
1074                         return true;
1075                 }
1076
1077                 public void EndInit ()
1078                 {
1079                         if (grid_style != null)
1080                                 grid_style.DataGrid = this;
1081                 }
1082
1083                 public void Expand (int row)
1084                 {
1085                         if (rows[row].IsExpanded)
1086                                 return;
1087
1088                         rows[row].IsExpanded = true;
1089
1090                         int i;
1091
1092                         string[] relations = CurrentTableStyle.Relations;
1093                         StringBuilder relation_builder = new StringBuilder ("");
1094
1095                         for (i = 0; i < relations.Length; i ++) {
1096                                 if (i > 0)
1097                                         relation_builder.Append ("\n");
1098
1099                                 relation_builder.Append (relations[i]);
1100                         }
1101                         string relation_text = relation_builder.ToString ();
1102
1103                         SizeF measured_area = TextRenderer.MeasureString (relation_text, LinkFont);
1104
1105                         rows[row].relation_area = new Rectangle (cells_area.X + 1,
1106                                                                  0, /* updated as needed at the usage sites for relation_area */
1107                                                                  (int)measured_area.Width + 4,
1108                                                                  Font.Height * relations.Length);
1109
1110                         for (i = 1; i < rows.Length - row; i ++)
1111                                 rows[row + i].VerticalOffset += rows[row].relation_area.Height;
1112                         rows[row].height += rows[row].relation_area.Height;
1113                         rows[row].RelationHeight = rows[row].relation_area.Height;
1114
1115                         /* XX need to redraw from @row down */
1116                         CalcAreasAndInvalidate ();
1117                 }
1118
1119                 public Rectangle GetCellBounds (DataGridCell dgc)
1120                 {
1121                         return GetCellBounds (dgc.RowNumber, dgc.ColumnNumber);
1122                 }
1123
1124                 public Rectangle GetCellBounds (int row, int col)
1125                 {
1126                         Rectangle bounds = new Rectangle ();
1127                         int col_pixel;
1128
1129                         bounds.Width = CurrentTableStyle.GridColumnStyles[col].Width;
1130                         bounds.Height = rows[row].Height - rows[row].RelationHeight;
1131                         bounds.Y = cells_area.Y + rows[row].VerticalOffset - rows[FirstVisibleRow].VerticalOffset;
1132                         col_pixel = GetColumnStartingPixel (col);
1133                         bounds.X = cells_area.X + col_pixel - horiz_pixeloffset;
1134                         return bounds;
1135                 }
1136
1137                 public Rectangle GetCurrentCellBounds ()
1138                 {
1139                         return GetCellBounds (current_cell.RowNumber, current_cell.ColumnNumber);
1140                 }
1141
1142                 protected virtual string GetOutputTextDelimiter ()
1143                 {
1144                         return string.Empty;
1145                 }
1146
1147                 protected virtual void GridHScrolled (object sender, ScrollEventArgs se)
1148                 {
1149                         if (se.NewValue == horiz_pixeloffset ||
1150                             se.Type == ScrollEventType.EndScroll) {
1151                                 return;
1152                         }
1153
1154                         ScrollToColumnInPixels (se.NewValue);
1155                 }
1156
1157                 protected virtual void GridVScrolled (object sender, ScrollEventArgs se)
1158                 {
1159                         int old_first_visible_row = first_visible_row;
1160                         first_visible_row = se.NewValue;
1161
1162                         if (first_visible_row == old_first_visible_row)
1163                                 return;
1164
1165                         UpdateVisibleRowCount ();
1166
1167                         if (first_visible_row == old_first_visible_row)
1168                                 return;
1169                         
1170                         ScrollToRow (old_first_visible_row, first_visible_row);
1171                 }
1172
1173                 public HitTestInfo HitTest (Point position)
1174                 {
1175                         return HitTest (position.X, position.Y);
1176                 }
1177
1178                 const int RESIZE_HANDLE_HORIZ_SIZE = 5;
1179                 const int RESIZE_HANDLE_VERT_SIZE = 3;
1180
1181                 // From Point to Cell
1182                 public HitTestInfo HitTest (int x, int y)
1183                 {
1184                         if (column_headers_area.Contains (x, y)) {
1185                                 int offset_x = x + horiz_pixeloffset;
1186                                 int column_x;
1187                                 int column_under_mouse = FromPixelToColumn (offset_x, out column_x);
1188                                 
1189                                 if ((column_x + CurrentTableStyle.GridColumnStyles[column_under_mouse].Width - offset_x < RESIZE_HANDLE_HORIZ_SIZE)
1190                                     && column_under_mouse < CurrentTableStyle.GridColumnStyles.Count) {
1191
1192                                         return new HitTestInfo (-1, column_under_mouse, HitTestType.ColumnResize);
1193                                 }
1194                                 else {
1195                                         return new HitTestInfo (-1, column_under_mouse, HitTestType.ColumnHeader);
1196                                 }
1197                         }
1198
1199                         if (row_headers_area.Contains (x, y)) {
1200                                 int posy;
1201                                 int rcnt = FirstVisibleRow + VisibleRowCount;
1202                                 for (int r = FirstVisibleRow; r < rcnt; r++) {
1203                                         posy = cells_area.Y + rows[r].VerticalOffset - rows[FirstVisibleRow].VerticalOffset;
1204                                         if (y <= posy + rows[r].Height) {
1205                                                 if ((posy + rows[r].Height) - y < RESIZE_HANDLE_VERT_SIZE) {
1206                                                         return new HitTestInfo (r, -1, HitTestType.RowResize);
1207                                                 }
1208                                                 else {
1209                                                         return new HitTestInfo (r, -1, HitTestType.RowHeader);
1210                                                 }
1211                                         }
1212                                 }
1213                         }
1214
1215                         if (caption_area.Contains (x, y)) {
1216                                 return new HitTestInfo (-1, -1, HitTestType.Caption);
1217                         }
1218
1219                         if (parent_rows.Contains (x, y)) {
1220                                 return new HitTestInfo (-1, -1, HitTestType.ParentRows);
1221                         }
1222
1223                         int pos_y, pos_x, width;
1224                         int rowcnt = FirstVisibleRow + VisibleRowCount;
1225                         for (int row = FirstVisibleRow; row < rowcnt; row++) {
1226
1227                                 pos_y = cells_area.Y + rows[row].VerticalOffset - rows[FirstVisibleRow].VerticalOffset;
1228                                 if (y <= pos_y + rows[row].Height) {
1229                                         int col_pixel;
1230                                         int column_cnt = first_visible_column + visible_column_count;
1231                                         if (column_cnt > 0) {
1232                                                 for (int column = first_visible_column; column < column_cnt; column++) {
1233                                                         if (CurrentTableStyle.GridColumnStyles[column].bound == false)
1234                                                                 continue;
1235                                                         col_pixel = GetColumnStartingPixel (column);
1236                                                         pos_x = cells_area.X + col_pixel - horiz_pixeloffset;
1237                                                         width = CurrentTableStyle.GridColumnStyles[column].Width;
1238
1239                                                         if (x <= pos_x + width) { // Column found
1240                                                                 return new HitTestInfo (row, column, HitTestType.Cell);
1241                                                         }
1242                                                 }
1243                                         }
1244                                         else if (CurrentTableStyle.HasRelations) {
1245                                                 /* XXX this needs checking against MS somehow... */
1246                                                 if (x < rows[row].relation_area.X + rows[row].relation_area.Width)
1247                                                         return new HitTestInfo (row, 0/*XXX?*/, HitTestType.Cell);
1248                                         }
1249
1250                                         break;
1251                                 }
1252                         }
1253
1254                         return new HitTestInfo ();
1255                 }
1256
1257                 public bool IsExpanded (int rowNumber)
1258                 {
1259                         return (rows[rowNumber].IsExpanded);
1260                 }
1261
1262                 public bool IsSelected (int row)
1263                 {
1264                         return rows[row].IsSelected;
1265                 }
1266
1267                 [MonoTODO]
1268                 public void NavigateBack ()
1269                 {
1270                         if (data_source_stack.Count == 0)
1271                                 return;
1272
1273                         DataGridDataSource source = (DataGridDataSource)data_source_stack.Pop ();
1274                         list_manager = source.list_manager;
1275                         rows = source.Rows;
1276                         selected_rows = source.SelectedRows;
1277                         selection_start = source.SelectionStart;
1278                         SetDataSource (source.data_source, source.data_member);
1279
1280                         CurrentCell = source.current;
1281                 }
1282
1283                 [MonoTODO]
1284                 public void NavigateTo (int rowNumber, string relationName)
1285                 {
1286                         if (allow_navigation == false)
1287                                 return;
1288
1289                         DataGridDataSource previous_source = new DataGridDataSource (this, list_manager, datasource, datamember, list_manager.Current, CurrentCell);
1290                         previous_source.Rows = rows;
1291                         previous_source.SelectedRows = selected_rows;
1292                         previous_source.SelectionStart = selection_start;
1293
1294                         data_source_stack.Push (previous_source);
1295
1296                         rows = null;
1297                         selected_rows = new Hashtable ();
1298                         selection_start = -1;
1299
1300                         DataMember = String.Format ("{0}.{1}", DataMember, relationName);
1301                         OnDataSourceChanged (EventArgs.Empty);
1302                 }
1303
1304                 protected virtual void OnAllowNavigationChanged (EventArgs e)
1305                 {
1306                         EventHandler eh = (EventHandler)(Events [AllowNavigationChangedEvent]);
1307                         if (eh != null)
1308                                 eh (this, e);
1309                 }
1310
1311                 protected void OnBackButtonClicked (object sender, EventArgs e)
1312                 {
1313                         EventHandler eh = (EventHandler)(Events [BackButtonClickEvent]);
1314                         if (eh != null)
1315                                 eh (this, e);
1316                 }
1317
1318                 protected override void OnBackColorChanged (EventArgs e)
1319                 {
1320                         base.OnBackColorChanged (e);
1321                 }
1322
1323                 protected virtual void OnBackgroundColorChanged (EventArgs e)
1324                 {
1325                         EventHandler eh = (EventHandler)(Events [BackgroundColorChangedEvent]);
1326                         if (eh != null)
1327                                 eh (this, e);
1328                 }
1329
1330                 protected override void OnBindingContextChanged (EventArgs e)
1331                 {
1332                         base.OnBindingContextChanged (e);
1333
1334                         SetDataSource (datasource, datamember);
1335                 }
1336
1337                 protected virtual void OnBorderStyleChanged (EventArgs e)
1338                 {
1339                         EventHandler eh = (EventHandler)(Events [BorderStyleChangedEvent]);
1340                         if (eh != null)
1341                                 eh (this, e);
1342                 }
1343
1344                 protected virtual void OnCaptionVisibleChanged (EventArgs e)
1345                 {
1346                         EventHandler eh = (EventHandler)(Events [CaptionVisibleChangedEvent]);
1347                         if (eh != null)
1348                                 eh (this, e);
1349                 }
1350
1351                 protected virtual void OnCurrentCellChanged (EventArgs e)
1352                 {
1353                         EventHandler eh = (EventHandler)(Events [CurrentCellChangedEvent]);
1354                         if (eh != null)
1355                                 eh (this, e);
1356                 }
1357
1358                 protected virtual void OnDataSourceChanged (EventArgs e)
1359                 {
1360                         EventHandler eh = (EventHandler)(Events [DataSourceChangedEvent]);
1361                         if (eh != null)
1362                                 eh (this, e);
1363                 }
1364
1365                 protected override void OnEnter (EventArgs e)
1366                 {
1367                         base.OnEnter (e);
1368                         Edit ();
1369                 }
1370
1371                 protected virtual void OnFlatModeChanged (EventArgs e)
1372                 {
1373                         EventHandler eh = (EventHandler)(Events [FlatModeChangedEvent]);
1374                         if (eh != null)
1375                                 eh (this, e);
1376                 }
1377
1378                 protected override void OnFontChanged (EventArgs e)
1379                 {
1380                         CalcGridAreas ();
1381                         base.OnFontChanged (e);
1382                 }
1383
1384                 protected override void OnForeColorChanged (EventArgs e)
1385                 {
1386                         base.OnForeColorChanged (e);
1387                 }
1388
1389                 protected override void OnHandleCreated (EventArgs e)
1390                 {
1391                         base.OnHandleCreated (e);
1392                         SetDataSource (datasource, datamember);
1393                 }
1394
1395                 protected override void OnHandleDestroyed (EventArgs e)
1396                 {
1397                         base.OnHandleDestroyed (e);
1398                 }
1399
1400                 protected override void OnKeyDown (KeyEventArgs ke)
1401                 {
1402                         base.OnKeyDown (ke);
1403                         
1404                         if (ProcessGridKey (ke) == true)
1405                                 ke.Handled = true;
1406
1407                         /* TODO: we probably don't need this check,
1408                          * since current_cell wouldn't have been set
1409                          * to something invalid */
1410                         if (CurrentTableStyle.GridColumnStyles.Count > 0) {
1411                                 CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber].OnKeyDown
1412                                         (ke, current_cell.RowNumber, current_cell.ColumnNumber);
1413                         }
1414                 }
1415
1416                 protected override void OnKeyPress (KeyPressEventArgs kpe)
1417                 {
1418                         base.OnKeyPress (kpe);
1419                 }
1420
1421                 protected override void OnLayout (LayoutEventArgs levent)
1422                 {
1423                         base.OnLayout (levent);
1424                         CalcAreasAndInvalidate ();
1425                 }
1426
1427                 protected override void OnLeave (EventArgs e)
1428                 {
1429                         base.OnLeave (e);
1430
1431                         EndEdit ();
1432                         if (cursor_in_add_row) {
1433                                 ListManager.CancelCurrentEdit ();
1434                         }
1435                 }
1436
1437                 protected override void OnMouseDown (MouseEventArgs e)
1438                 {
1439                         base.OnMouseDown (e);
1440
1441                         bool ctrl_pressed = ((Control.ModifierKeys & Keys.Control) != 0);
1442                         bool shift_pressed = ((Control.ModifierKeys & Keys.Shift) != 0);
1443
1444                         HitTestInfo testinfo;
1445                         testinfo = HitTest (e.X, e.Y);
1446
1447                         switch (testinfo.Type) {
1448                         case HitTestType.Cell:
1449                                 if (testinfo.Row < 0 || testinfo.Column < 0)
1450                                         break;
1451
1452                                 if (rows[testinfo.Row].IsExpanded) {
1453                                         Rectangle relation_area = rows[testinfo.Row].relation_area;
1454                                         relation_area.Y = rows[testinfo.Row].VerticalOffset + cells_area.Y + rows[testinfo.Row].Height - rows[testinfo.Row].RelationHeight;
1455                                         if (relation_area.Contains (e.X, e.Y)) {
1456                                                 /* the click happened in the relation area, navigate to the new table */
1457                                                 int relative = e.Y - relation_area.Y;
1458                                                 NavigateTo (testinfo.Row, CurrentTableStyle.Relations[relative / LinkFont.Height]);
1459                                                 return;
1460                                         }
1461                                 }
1462
1463                                 DataGridCell new_cell = new DataGridCell (testinfo.Row, testinfo.Column);
1464
1465                                 if ((new_cell.Equals (current_cell) == false) || (!is_editing)) {
1466                                         CurrentCell = new_cell;
1467                                         Edit ();
1468                                 } else {
1469                                         CurrentTableStyle.GridColumnStyles[testinfo.Column].OnMouseDown (e, testinfo.Row, testinfo.Column);
1470                                 }
1471
1472                                 break;
1473
1474                         case HitTestType.RowHeader:
1475                                 bool expansion_click = false;
1476                                 if (CurrentTableStyle.HasRelations) {
1477                                         if (e.X > row_headers_area.X + row_headers_area.Width / 2) {
1478                                                 /* it's in the +/- space */
1479                                                 if (IsExpanded (testinfo.Row))
1480                                                         Collapse (testinfo.Row);
1481                                                 else
1482                                                         Expand (testinfo.Row);
1483
1484                                                 expansion_click = true;
1485                                         }
1486                                 }
1487
1488                                 CancelEditing ();
1489                                 CurrentRow = testinfo.Row;
1490
1491                                 if (!ctrl_pressed && !shift_pressed && !expansion_click) {
1492                                         ResetSelection (); // Invalidates selected rows
1493                                 }
1494
1495                                 if ((shift_pressed || expansion_click) && selection_start != -1) {
1496                                         ShiftSelection (testinfo.Row);
1497                                 } else { // ctrl_pressed or single item
1498                                         selection_start = testinfo.Row;
1499                                         Select (testinfo.Row);
1500                                 }
1501
1502                                 OnRowHeaderClick (EventArgs.Empty);
1503
1504                                 break;
1505
1506                         case HitTestType.ColumnHeader:
1507                                 if (CurrentTableStyle.GridColumnStyles.Count == 0)
1508                                         break;
1509
1510                                 if (AllowSorting == false)
1511                                         break;
1512
1513                                 if (ListManager.List is IBindingList == false)
1514                                         break;
1515                         
1516                                 ListSortDirection direction = ListSortDirection.Ascending;
1517                                 PropertyDescriptor prop = CurrentTableStyle.GridColumnStyles[testinfo.Column].PropertyDescriptor;
1518                                 IBindingList list = (IBindingList) ListManager.List;
1519
1520                                 if (list.SortProperty != null) {
1521                                         CurrentTableStyle.GridColumnStyles[list.SortProperty].ArrowDrawingMode 
1522                                                 = DataGridColumnStyle.ArrowDrawing.No;
1523                                 }
1524
1525                                 if (prop == list.SortProperty && list.SortDirection == ListSortDirection.Ascending) {
1526                                         direction = ListSortDirection.Descending;
1527                                 }
1528                                 
1529                                 CurrentTableStyle.GridColumnStyles[testinfo.Column].ArrowDrawingMode =
1530                                         direction == ListSortDirection.Ascending ? 
1531                                         DataGridColumnStyle.ArrowDrawing.Ascending : DataGridColumnStyle.ArrowDrawing.Descending;
1532                                 
1533                                 list.ApplySort (prop, direction);
1534                                 Refresh ();
1535                                 break;
1536
1537                         case HitTestType.ColumnResize:
1538                                 if (e.Clicks == 2) {
1539                                         EndEdit ();
1540                                         ColumnResize (testinfo.Column);
1541                                 } else {
1542                                         resize_column = testinfo.Column;
1543                                         column_resize_active = true;
1544                                         resize_column_x = e.X;
1545                                         resize_column_width_delta = 0;
1546                                         EndEdit ();
1547                                         DrawResizeLineVert (resize_column_x);
1548                                 }
1549                                 break;
1550
1551                         case HitTestType.RowResize:
1552                                 if (e.Clicks == 2) {
1553                                         EndEdit ();
1554                                         RowResize (testinfo.Row);
1555                                 } else {
1556                                         resize_row = testinfo.Row;
1557                                         row_resize_active = true;
1558                                         resize_row_y = e.Y;
1559                                         resize_row_height_delta = 0;
1560                                         EndEdit ();
1561                                         DrawResizeLineHoriz (resize_row_y);
1562                                 }
1563                                 break;
1564
1565                         case HitTestType.Caption:
1566                                 if (back_button_rect.Contains (e.X, e.Y)) {
1567                                         back_button_active = true;
1568                                         Invalidate (back_button_rect);
1569                                 }
1570                                 if (parent_rows_button_rect.Contains (e.X, e.Y)) {
1571                                         parent_rows_button_active = true;
1572                                         Invalidate (parent_rows_button_rect);
1573                                 }
1574                                 break;
1575
1576                         default:
1577                                 break;
1578                         }
1579                 }
1580
1581                 protected override void OnMouseLeave (EventArgs e)
1582                 {
1583                         base.OnMouseLeave (e);
1584                 }
1585
1586                 protected override void OnMouseMove (MouseEventArgs e)
1587                 {
1588                         base.OnMouseMove (e);
1589
1590                         if (column_resize_active) {
1591                                 /* erase the old line */
1592                                 DrawResizeLineVert (resize_column_x + resize_column_width_delta);
1593
1594                                 resize_column_width_delta = e.X - resize_column_x;
1595
1596                                 /* draw the new line */
1597                                 DrawResizeLineVert (resize_column_x + resize_column_width_delta);
1598                                 return;
1599                         }
1600                         else if (row_resize_active) {
1601                                 /* erase the old line */
1602                                 DrawResizeLineHoriz (resize_row_y + resize_row_height_delta);
1603
1604                                 resize_row_height_delta = e.Y - resize_row_y;
1605
1606                                 /* draw the new line */
1607                                 DrawResizeLineHoriz (resize_row_y + resize_row_height_delta);
1608                                 return;
1609                         }
1610                         else {
1611                                 /* determine the cursor to use */
1612                                 HitTestInfo testinfo;
1613                                 testinfo = HitTest (e.X, e.Y);
1614
1615                                 switch (testinfo.Type) {
1616                                 case HitTestType.ColumnResize:
1617                                         Cursor = Cursors.VSplit;
1618                                         break;
1619                                 case HitTestType.RowResize:
1620                                         Cursor = Cursors.HSplit;
1621                                         break;
1622                                 case HitTestType.Caption:
1623                                         Cursor = Cursors.Default;
1624                                         if (back_button_rect.Contains (e.X, e.Y)) {
1625                                                 if (!back_button_mouseover)
1626                                                         Invalidate (back_button_rect);
1627                                                 back_button_mouseover = true;
1628                                         } else if (back_button_mouseover) {
1629                                                 Invalidate (back_button_rect);
1630                                                 back_button_mouseover = false;
1631                                         }
1632
1633                                         if (parent_rows_button_rect.Contains (e.X, e.Y)) {
1634                                                 if (parent_rows_button_mouseover)
1635                                                         Invalidate (parent_rows_button_rect);
1636                                                 parent_rows_button_mouseover = true;
1637                                         } else if (parent_rows_button_mouseover) {
1638                                                 Invalidate (parent_rows_button_rect);
1639                                                 parent_rows_button_mouseover = false;
1640                                         }
1641                                         break;
1642                                 case HitTestType.Cell:
1643                                         if (rows[testinfo.Row].IsExpanded) {
1644                                                 Rectangle relation_area = rows[testinfo.Row].relation_area;
1645                                                 relation_area.Y = rows[testinfo.Row].VerticalOffset + cells_area.Y + rows[testinfo.Row].Height - rows[testinfo.Row].RelationHeight;
1646                                                 if (relation_area.Contains (e.X, e.Y)) {
1647                                                         Cursor = Cursors.Hand;
1648                                                         break;
1649                                                 }
1650                                         }
1651
1652                                         Cursor = Cursors.Default;
1653                                         break;
1654                                 default:
1655                                         Cursor = Cursors.Default;
1656                                         break;
1657                                 }
1658                         }
1659                 }
1660
1661                 protected override void OnMouseUp (MouseEventArgs e)
1662                 {
1663                         base.OnMouseUp (e);
1664
1665                         if (column_resize_active) {
1666                                 column_resize_active = false;
1667                                 if (resize_column_width_delta + CurrentTableStyle.GridColumnStyles[resize_column].Width < 0)
1668                                         resize_column_width_delta = -CurrentTableStyle.GridColumnStyles[resize_column].Width;
1669                                 CurrentTableStyle.GridColumnStyles[resize_column].Width += resize_column_width_delta;
1670                                 width_of_all_columns += resize_column_width_delta;
1671                                 Edit ();
1672                                 Invalidate ();
1673                         } else if (row_resize_active) {
1674                                 row_resize_active = false;
1675
1676                                 if (resize_row_height_delta + rows[resize_row].Height < 0)
1677                                         resize_row_height_delta = -rows[resize_row].Height;
1678
1679                                 rows[resize_row].height = rows[resize_row].Height + resize_row_height_delta;
1680                                 for (int i = resize_row + 1; i < rows.Length; i ++)
1681                                         rows[i].VerticalOffset += resize_row_height_delta;
1682
1683                                 Edit ();
1684                                 CalcAreasAndInvalidate ();
1685                         } else if (back_button_active) {
1686                                 if (back_button_rect.Contains (e.X, e.Y)) {
1687                                         Invalidate (back_button_rect);
1688                                         NavigateBack ();
1689                                         OnBackButtonClicked (this, EventArgs.Empty);
1690                                 }
1691                                 back_button_active = false;
1692                         } else if (parent_rows_button_active) {
1693                                 if (parent_rows_button_rect.Contains (e.X, e.Y)) {
1694                                         Invalidate (parent_rows_button_rect);
1695                                         ParentRowsVisible = !ParentRowsVisible;
1696                                         OnShowParentDetailsButtonClicked (this, EventArgs.Empty);
1697                                 }
1698                                 parent_rows_button_active = false;
1699                         }
1700                 }
1701
1702                 protected override void OnMouseWheel (MouseEventArgs e)
1703                 {
1704                         base.OnMouseWheel (e);
1705
1706                         bool ctrl_pressed = ((Control.ModifierKeys & Keys.Control) != 0);
1707                         int pixels;
1708
1709                         if (ctrl_pressed) { // scroll horizontally
1710                                 if (!horiz_scrollbar.Visible)
1711                                         return;
1712
1713                                 if (e.Delta > 0) {
1714                                         /* left */
1715                                         pixels = Math.Max (horiz_scrollbar.Minimum,
1716                                                            horiz_scrollbar.Value - horiz_scrollbar.LargeChange);
1717                                 } else {
1718                                         /* right */
1719                                         pixels = Math.Min (horiz_scrollbar.Maximum - horiz_scrollbar.LargeChange + 1,
1720                                                            horiz_scrollbar.Value + horiz_scrollbar.LargeChange);
1721                                 }
1722
1723                                 GridHScrolled (this, new ScrollEventArgs (ScrollEventType.ThumbPosition, pixels));
1724                                 horiz_scrollbar.Value = pixels;
1725                         } else {
1726                                 if (!vert_scrollbar.Visible)
1727                                         return;
1728
1729                                 if (e.Delta > 0) {
1730                                         /* up */
1731                                         pixels = Math.Max (vert_scrollbar.Minimum,
1732                                                            vert_scrollbar.Value - vert_scrollbar.LargeChange);
1733                                 } else {
1734                                         /* down */
1735                                         pixels = Math.Min (vert_scrollbar.Maximum - vert_scrollbar.LargeChange + 1,
1736                                                            vert_scrollbar.Value + vert_scrollbar.LargeChange);
1737                                 }
1738
1739                                 GridVScrolled (this, new ScrollEventArgs (ScrollEventType.ThumbPosition, pixels));
1740                                 vert_scrollbar.Value = pixels;
1741                         }
1742                 }
1743
1744                 protected void OnNavigate (NavigateEventArgs e)
1745                 {
1746                         EventHandler eh = (EventHandler)(Events [NavigateEvent]);
1747                         if (eh != null)
1748                                 eh (this, e);
1749                 }
1750
1751                 protected override void OnPaint (PaintEventArgs pe)
1752                 {
1753                         ThemeEngine.Current.DataGridPaint (pe, this);
1754                 }
1755
1756                 protected override void OnPaintBackground (PaintEventArgs ebe)
1757                 {
1758                 }
1759
1760                 protected virtual void OnParentRowsLabelStyleChanged (EventArgs e)
1761                 {
1762                         EventHandler eh = (EventHandler)(Events [ParentRowsLabelStyleChangedEvent]);
1763                         if (eh != null)
1764                                 eh (this, e);
1765                 }
1766
1767                 protected virtual void OnParentRowsVisibleChanged (EventArgs e)
1768                 {
1769                         EventHandler eh = (EventHandler)(Events [ParentRowsVisibleChangedEvent]);
1770                         if (eh != null)
1771                                 eh (this, e);
1772                 }
1773
1774                 protected virtual void OnReadOnlyChanged (EventArgs e)
1775                 {
1776                         EventHandler eh = (EventHandler)(Events [ReadOnlyChangedEvent]);
1777                         if (eh != null)
1778                                 eh (this, e);
1779                 }
1780
1781                 protected override void OnResize (EventArgs e)
1782                 {
1783                         base.OnResize (e);
1784                 }
1785
1786                 protected void OnRowHeaderClick (EventArgs e)
1787                 {
1788                         EventHandler eh = (EventHandler)(Events [RowHeaderClickEvent]);
1789                         if (eh != null)
1790                                 eh (this, e);
1791                 }
1792
1793                 protected void OnScroll (EventArgs e)
1794                 {
1795                         EventHandler eh = (EventHandler)(Events [ScrollEvent]);
1796                         if (eh != null)
1797                                 eh (this, e);
1798                 }
1799
1800                 protected void OnShowParentDetailsButtonClicked (object sender, EventArgs e)
1801                 {
1802                         EventHandler eh = (EventHandler)(Events [ShowParentDetailsButtonClickEvent]);
1803                         if (eh != null)
1804                                 eh (this, e);
1805                 }
1806
1807                 protected override bool ProcessDialogKey (Keys keyData)
1808                 {
1809                         return ProcessGridKey (new KeyEventArgs (keyData));
1810                 }
1811
1812                 void UpdateSelectionAfterCursorMove (bool extend_selection)
1813                 {
1814                         if (extend_selection) {
1815                                 CancelEditing ();
1816                                 ShiftSelection (CurrentRow);
1817                         } else {
1818                                 ResetSelection ();
1819                                 selection_start = CurrentRow;
1820                         }
1821                 }
1822
1823                 protected bool ProcessGridKey (KeyEventArgs ke)
1824                 {
1825                         bool ctrl_pressed = ((ke.Modifiers & Keys.Control) != 0);
1826                         //bool alt_pressed = ((ke.Modifiers & Keys.Alt) != 0);
1827                         bool shift_pressed = ((ke.Modifiers & Keys.Shift) != 0);
1828
1829                         switch (ke.KeyCode) {
1830                         case Keys.Escape:
1831                                 if (is_changing)
1832                                         AbortEditing ();
1833                                 else
1834                                         CancelEditing ();
1835                                 Edit ();
1836                                 return true;
1837                                 
1838                         case Keys.D0:
1839                                 if (ctrl_pressed) {
1840                                         if (is_editing)
1841                                                 CurrentTableStyle.GridColumnStyles[CurrentColumn].EnterNullValue ();
1842                                         return true;
1843                                 }
1844                                 return false;
1845
1846                         case Keys.Enter:
1847                                 if (is_changing)
1848                                         CurrentRow ++;
1849                                 return true;
1850
1851                         case Keys.Tab:
1852                                 if (shift_pressed) {
1853                                         if (CurrentColumn > 0)
1854                                                 CurrentColumn --;
1855                                         else if ((CurrentRow > 0) && (CurrentColumn == 0))
1856                                                 CurrentCell = new DataGridCell (CurrentRow - 1, CurrentTableStyle.GridColumnStyles.Count - 1);
1857                                 } else {
1858                                         if (CurrentColumn < CurrentTableStyle.GridColumnStyles.Count - 1)
1859                                                 CurrentColumn ++;
1860                                         else if ((CurrentRow <= RowsCount) && (CurrentColumn == CurrentTableStyle.GridColumnStyles.Count - 1))
1861                                                 CurrentCell = new DataGridCell (CurrentRow + 1, 0);
1862                                 }
1863
1864                                 UpdateSelectionAfterCursorMove (false);
1865
1866                                 return true;
1867
1868                         case Keys.Right:
1869                                 if (ctrl_pressed) {
1870                                         CurrentColumn = CurrentTableStyle.GridColumnStyles.Count - 1;
1871                                 } else {
1872                                         if (CurrentColumn < CurrentTableStyle.GridColumnStyles.Count - 1) {
1873                                                 CurrentColumn ++;
1874                                         } else if (CurrentRow < RowsCount - 1
1875                                                    || (CurrentRow == RowsCount - 1
1876                                                        && !cursor_in_add_row)) {
1877                                                 CurrentCell = new DataGridCell (CurrentRow + 1, 0);
1878                                         }
1879                                 }
1880
1881                                 UpdateSelectionAfterCursorMove (false);
1882
1883                                 return true;
1884
1885                         case Keys.Left:
1886                                 if (ctrl_pressed) {
1887                                         CurrentColumn = 0;
1888                                 } else {
1889                                         if (current_cell.ColumnNumber > 0)
1890                                                 CurrentColumn --;
1891                                         else if (CurrentRow > 0)
1892                                                 CurrentCell = new DataGridCell (CurrentRow - 1, CurrentTableStyle.GridColumnStyles.Count - 1);
1893                                 }
1894
1895                                 UpdateSelectionAfterCursorMove (false);
1896
1897                                 return true;
1898
1899                         case Keys.Up:
1900                                 if (ctrl_pressed)
1901                                         CurrentRow = 0;
1902                                 else if (CurrentRow > 0)
1903                                         CurrentRow --;
1904
1905                                 UpdateSelectionAfterCursorMove (shift_pressed);
1906
1907                                 return true;
1908
1909                         case Keys.Down:
1910                                 if (ctrl_pressed)
1911                                         CurrentRow = RowsCount - 1;
1912                                 else if (CurrentRow < RowsCount - 1)
1913                                         CurrentRow ++;
1914                                 else if (CurrentRow == RowsCount - 1 && cursor_in_add_row && (add_row_changed || is_changing))
1915                                         CurrentRow ++;
1916                                 else if (CurrentRow == RowsCount - 1 && !cursor_in_add_row && !shift_pressed)
1917                                         CurrentRow ++;
1918
1919                                 UpdateSelectionAfterCursorMove (shift_pressed);
1920
1921                                 return true;
1922
1923                         case Keys.PageUp:
1924                                 if (CurrentRow > VLargeChange)
1925                                         CurrentRow -= VLargeChange;
1926                                 else
1927                                         CurrentRow = 0;
1928
1929                                 UpdateSelectionAfterCursorMove (shift_pressed);
1930
1931                                 return true;
1932
1933                         case Keys.PageDown:
1934                                 if (CurrentRow < RowsCount - VLargeChange)
1935                                         CurrentRow += VLargeChange;
1936                                 else
1937                                         CurrentRow = RowsCount - 1;
1938
1939                                 UpdateSelectionAfterCursorMove (shift_pressed);
1940
1941                                 return true;
1942
1943                         case Keys.Home:
1944                                 if (ctrl_pressed)
1945                                         CurrentCell = new DataGridCell (0, 0);
1946                                 else
1947                                         CurrentColumn = 0;
1948
1949                                 UpdateSelectionAfterCursorMove (ctrl_pressed && shift_pressed);
1950
1951                                 return true;
1952
1953                         case Keys.End:
1954                                 if (ctrl_pressed)
1955                                         CurrentCell = new DataGridCell (RowsCount - 1, CurrentTableStyle.GridColumnStyles.Count - 1);
1956                                 else
1957                                         CurrentColumn = CurrentTableStyle.GridColumnStyles.Count - 1;
1958
1959                                 UpdateSelectionAfterCursorMove (ctrl_pressed && shift_pressed);
1960
1961                                 return true;
1962
1963                         case Keys.Delete:
1964                                 if (is_editing)
1965                                         return false;
1966                                 else if (selected_rows.Keys.Count > 0) {
1967                                         foreach (int row in selected_rows.Keys)
1968                                                 ListManager.RemoveAt (row);
1969                                         selected_rows.Clear ();
1970                                         CalcAreasAndInvalidate ();
1971                                 }
1972
1973                                 return true;
1974                         }
1975
1976                         return false; // message not processed
1977                 }
1978
1979                 protected override bool ProcessKeyPreview (ref Message m)
1980                 {
1981                         if ((Msg) m.Msg == Msg.WM_KEYDOWN) {
1982                                 Keys key = (Keys) m.WParam.ToInt32 ();
1983                                 KeyEventArgs ke = new KeyEventArgs (key);
1984                                 if (ProcessGridKey (ke))
1985                                         return true;
1986                         }
1987
1988                         return base.ProcessKeyPreview (ref m);
1989                 }
1990                 
1991                 protected bool ProcessTabKey (Keys keyData)
1992                 {
1993                         return false;
1994                 }
1995
1996                 public void ResetAlternatingBackColor ()
1997                 {
1998                         grid_style.AlternatingBackColor = default_style.AlternatingBackColor;
1999                 }
2000
2001                 public override void ResetBackColor ()
2002                 {
2003                         grid_style.BackColor = default_style.BackColor;
2004                 }
2005
2006                 public override void ResetForeColor ()
2007                 {
2008                         grid_style.ForeColor = default_style.ForeColor;
2009                 }
2010
2011                 public void ResetGridLineColor ()
2012                 {
2013                         grid_style.GridLineColor = default_style.GridLineColor;
2014                 }
2015
2016                 public void ResetHeaderBackColor ()
2017                 {
2018                         grid_style.HeaderBackColor = default_style.HeaderBackColor;
2019                 }
2020
2021                 public void ResetHeaderFont ()
2022                 {
2023                         grid_style.HeaderFont = null;
2024                 }
2025
2026                 public void ResetHeaderForeColor ()
2027                 {
2028                         grid_style.HeaderForeColor = default_style.HeaderForeColor;
2029                 }
2030
2031                 public void ResetLinkColor ()
2032                 {
2033                         grid_style.LinkColor = default_style.LinkColor;
2034                 }
2035
2036                 public void ResetLinkHoverColor ()
2037                 {
2038                         grid_style.LinkHoverColor = default_style.LinkHoverColor;
2039                 }
2040
2041                 protected void ResetSelection ()
2042                 {
2043                         InvalidateSelection ();
2044                         selected_rows.Clear ();
2045                         selection_start = -1;
2046                 }
2047
2048                 void InvalidateSelection ()
2049                 {
2050                         foreach (int row in selected_rows.Keys) {
2051                                 rows[row].IsSelected = false;
2052                                 InvalidateRow (row);
2053                         }
2054                 }
2055
2056                 public void ResetSelectionBackColor ()
2057                 {
2058                         grid_style.SelectionBackColor = default_style.SelectionBackColor;
2059                 }
2060
2061                 public void ResetSelectionForeColor ()
2062                 {
2063                         grid_style.SelectionForeColor = default_style.SelectionForeColor;
2064                 }
2065
2066                 public void Select (int row)
2067                 {
2068                         EndEdit();
2069
2070                         if (selected_rows.Count == 0)
2071                                 selection_start = row;
2072
2073                         selected_rows[row] = true;
2074                         rows[row].IsSelected = true;
2075
2076                         InvalidateRow (row);
2077                 }
2078
2079                 public void SetDataBinding (object dataSource, string dataMember)
2080                 {
2081                         SetDataSource (dataSource, dataMember);
2082                 }
2083
2084                 protected virtual bool ShouldSerializeAlternatingBackColor ()
2085                 {
2086                         return (grid_style.AlternatingBackColor != default_style.AlternatingBackColor);
2087                 }
2088
2089                 protected virtual bool ShouldSerializeBackgroundColor ()
2090                 {
2091                         return (background_color != def_background_color);
2092                 }
2093
2094                 protected virtual bool ShouldSerializeCaptionBackColor ()
2095                 {
2096                         return (caption_backcolor != def_caption_backcolor);
2097                 }
2098
2099                 protected virtual bool ShouldSerializeCaptionForeColor ()
2100                 {
2101                         return caption_forecolor != def_caption_forecolor;
2102                 }
2103
2104                 protected virtual bool ShouldSerializeGridLineColor ()
2105                 {
2106                         return grid_style.GridLineColor != default_style.GridLineColor;
2107                 }
2108
2109                 protected virtual bool ShouldSerializeHeaderBackColor ()
2110                 {
2111                         return grid_style.HeaderBackColor != default_style.HeaderBackColor;
2112                 }
2113
2114                 protected bool ShouldSerializeHeaderFont ()
2115                 {
2116                         return grid_style.HeaderFont != default_style.HeaderFont;
2117                 }
2118
2119                 protected virtual bool ShouldSerializeHeaderForeColor ()
2120                 {
2121                         return grid_style.HeaderForeColor != default_style.HeaderForeColor;
2122                 }
2123
2124                 protected virtual bool ShouldSerializeLinkHoverColor ()
2125                 {
2126                         return grid_style.LinkHoverColor != grid_style.LinkHoverColor;
2127                 }
2128
2129                 protected virtual bool ShouldSerializeParentRowsBackColor ()
2130                 {
2131                         return parent_rows_backcolor != def_parent_rows_backcolor;
2132                 }
2133
2134                 protected virtual bool ShouldSerializeParentRowsForeColor ()
2135                 {
2136                         return parent_rows_backcolor != def_parent_rows_backcolor;
2137                 }
2138
2139                 protected bool ShouldSerializePreferredRowHeight ()
2140                 {
2141                         return grid_style.PreferredRowHeight != default_style.PreferredRowHeight;
2142                 }
2143
2144                 protected bool ShouldSerializeSelectionBackColor ()
2145                 {
2146                         return grid_style.SelectionBackColor != default_style.SelectionBackColor;
2147                 }
2148
2149                 protected virtual bool ShouldSerializeSelectionForeColor ()
2150                 {
2151                         return grid_style.SelectionForeColor != default_style.SelectionForeColor;
2152                 }
2153
2154                 public void SubObjectsSiteChange (bool site)
2155                 {
2156                 }
2157
2158                 public void UnSelect (int row)
2159                 {
2160                         rows[row].IsSelected = false;
2161                         selected_rows.Remove (row);
2162                         InvalidateRow (row);
2163                 }
2164                 #endregion      // Public Instance Methods
2165
2166                 #region Private Instance Methods
2167
2168                 internal void CalcAreasAndInvalidate ()
2169                 {
2170                         CalcGridAreas ();
2171                         Invalidate ();
2172                 }
2173                 
2174                 private void ConnectListManagerEvents ()
2175                 {
2176                         list_manager.MetaDataChanged += new EventHandler (OnListManagerMetaDataChanged);
2177                         list_manager.PositionChanged += new EventHandler (OnListManagerPositionChanged);
2178                         list_manager.ItemChanged += new ItemChangedEventHandler (OnListManagerItemChanged);
2179                 }
2180                 
2181                 private void DisconnectListManagerEvents ()
2182                 {
2183                         list_manager.MetaDataChanged -= new EventHandler (OnListManagerMetaDataChanged);
2184                         list_manager.PositionChanged -= new EventHandler (OnListManagerPositionChanged);
2185                         list_manager.ItemChanged -= new ItemChangedEventHandler (OnListManagerItemChanged);
2186                 }
2187
2188                 void DisconnectTableStyleEvents ()
2189                 {
2190                         current_style.AllowSortingChanged -= new EventHandler (TableStyleChanged);
2191                         current_style.AlternatingBackColorChanged -= new EventHandler (TableStyleChanged);
2192                         current_style.BackColorChanged -= new EventHandler (TableStyleChanged);
2193                         current_style.ColumnHeadersVisibleChanged -= new EventHandler (TableStyleChanged);
2194                         current_style.ForeColorChanged -= new EventHandler (TableStyleChanged);
2195                         current_style.GridLineColorChanged -= new EventHandler (TableStyleChanged);
2196                         current_style.GridLineStyleChanged -= new EventHandler (TableStyleChanged);
2197                         current_style.HeaderBackColorChanged -= new EventHandler (TableStyleChanged);
2198                         current_style.HeaderFontChanged -= new EventHandler (TableStyleChanged);
2199                         current_style.HeaderForeColorChanged -= new EventHandler (TableStyleChanged);
2200                         current_style.LinkColorChanged -= new EventHandler (TableStyleChanged);
2201                         current_style.LinkHoverColorChanged -= new EventHandler (TableStyleChanged);
2202                         current_style.MappingNameChanged -= new EventHandler (TableStyleChanged);
2203                         current_style.PreferredColumnWidthChanged -= new EventHandler (TableStyleChanged);
2204                         current_style.PreferredRowHeightChanged -= new EventHandler (TableStyleChanged);
2205                         current_style.ReadOnlyChanged -= new EventHandler (TableStyleChanged);
2206                         current_style.RowHeadersVisibleChanged -= new EventHandler (TableStyleChanged);
2207                         current_style.RowHeaderWidthChanged -= new EventHandler (TableStyleChanged);
2208                         current_style.SelectionBackColorChanged -= new EventHandler (TableStyleChanged);
2209                         current_style.SelectionForeColorChanged -= new EventHandler (TableStyleChanged);
2210                 }
2211
2212                 void ConnectTableStyleEvents ()
2213                 {
2214                         current_style.AllowSortingChanged += new EventHandler (TableStyleChanged);
2215                         current_style.AlternatingBackColorChanged += new EventHandler (TableStyleChanged);
2216                         current_style.BackColorChanged += new EventHandler (TableStyleChanged);
2217                         current_style.ColumnHeadersVisibleChanged += new EventHandler (TableStyleChanged);
2218                         current_style.ForeColorChanged += new EventHandler (TableStyleChanged);
2219                         current_style.GridLineColorChanged += new EventHandler (TableStyleChanged);
2220                         current_style.GridLineStyleChanged += new EventHandler (TableStyleChanged);
2221                         current_style.HeaderBackColorChanged += new EventHandler (TableStyleChanged);
2222                         current_style.HeaderFontChanged += new EventHandler (TableStyleChanged);
2223                         current_style.HeaderForeColorChanged += new EventHandler (TableStyleChanged);
2224                         current_style.LinkColorChanged += new EventHandler (TableStyleChanged);
2225                         current_style.LinkHoverColorChanged += new EventHandler (TableStyleChanged);
2226                         current_style.MappingNameChanged += new EventHandler (TableStyleChanged);
2227                         current_style.PreferredColumnWidthChanged += new EventHandler (TableStyleChanged);
2228                         current_style.PreferredRowHeightChanged += new EventHandler (TableStyleChanged);
2229                         current_style.ReadOnlyChanged += new EventHandler (TableStyleChanged);
2230                         current_style.RowHeadersVisibleChanged += new EventHandler (TableStyleChanged);
2231                         current_style.RowHeaderWidthChanged += new EventHandler (TableStyleChanged);
2232                         current_style.SelectionBackColorChanged += new EventHandler (TableStyleChanged);
2233                         current_style.SelectionForeColorChanged += new EventHandler (TableStyleChanged);
2234                 }
2235
2236                 void TableStyleChanged (object sender, EventArgs args)
2237                 {
2238                         EndEdit ();
2239                         CalcAreasAndInvalidate ();
2240                 }
2241
2242
2243                 private void EnsureCellVisibility (DataGridCell cell)
2244                 {
2245                         if (cell.ColumnNumber <= first_visible_column ||
2246                                 cell.ColumnNumber + 1 >= first_visible_column + visible_column_count) {
2247
2248                                 first_visible_column = GetFirstColumnForColumnVisibility (first_visible_column, cell.ColumnNumber);
2249                                 int pixel = GetColumnStartingPixel (first_visible_column);
2250                                 ScrollToColumnInPixels (pixel);
2251                                 horiz_scrollbar.Value = pixel;
2252                                 Update();
2253                         }
2254
2255                         if (cell.RowNumber < first_visible_row ||
2256                             cell.RowNumber + 1 >= first_visible_row + visible_row_count) {
2257
2258                                 if (cell.RowNumber + 1 >= first_visible_row + visible_row_count) {
2259                                         int old_first_visible_row = first_visible_row;
2260                                         first_visible_row = 1 + cell.RowNumber - visible_row_count;
2261                                         UpdateVisibleRowCount ();
2262                                         ScrollToRow (old_first_visible_row, first_visible_row);
2263                                 } else {
2264                                         int old_first_visible_row = first_visible_row;
2265                                         first_visible_row = cell.RowNumber;
2266                                         UpdateVisibleRowCount ();
2267                                         ScrollToRow (old_first_visible_row, first_visible_row);
2268                                 }
2269
2270                                 vert_scrollbar.Value = first_visible_row;
2271                         }
2272                 }
2273
2274                 private void SetDataSource (object source, string member)
2275                 {
2276                         SetDataSource (source, member, true);
2277                 }
2278
2279                 bool in_setdatasource;
2280                 private void SetDataSource (object source, string member, bool recreate_rows)
2281                 {
2282                         CurrencyManager old_lm = list_manager;
2283
2284                         /* we need this bool flag to work around a
2285                          * problem with OnBindingContextChanged.  once
2286                          * that stuff works properly, remove this
2287                          * hack */
2288                         if (in_setdatasource)
2289                                 return;
2290                         in_setdatasource = true;
2291
2292 #if false
2293                         if (datasource == source && member == datamember)
2294                                 return;
2295 #endif
2296
2297                         if (source != null && source as IListSource != null && source as IList != null)
2298                                 throw new Exception ("Wrong complex data binding source");
2299
2300                         datasource = source;
2301                         datamember = member;
2302
2303                         if (is_editing)
2304                                 CancelEditing ();
2305
2306                         current_cell = new DataGridCell ();
2307
2308                         if (list_manager != null)
2309                                 DisconnectListManagerEvents ();
2310
2311                         list_manager = null;
2312
2313                         /* create the new list manager */
2314                         if (BindingContext != null && datasource != null)
2315                                 list_manager = (CurrencyManager) BindingContext [datasource, datamember];
2316
2317                         if (list_manager != null)
2318                                 ConnectListManagerEvents ();
2319
2320                         if (old_lm != list_manager) {
2321                                 BindColumns ();
2322
2323                                 /* reset first_visible_row to 0 here before
2324                                  * doing anything that'll requires us to
2325                                  * figure out if we need a scrollbar. */
2326                                 vert_scrollbar.Value = 0;
2327                                 horiz_scrollbar.Value = 0;
2328                                 first_visible_row = 0;
2329
2330                                 if (recreate_rows)
2331                                         RecreateDataGridRows (false);
2332                         }
2333
2334                         CalcAreasAndInvalidate ();
2335
2336                         in_setdatasource = false;
2337
2338                         OnDataSourceChanged (EventArgs.Empty);
2339                 }
2340
2341                 void RecreateDataGridRows (bool recalc)
2342                 {
2343                         DataGridRelationshipRow[] new_rows = new DataGridRelationshipRow[RowsCount + (ShowEditRow ? 1 : 0)];
2344                         int start_index = 0;
2345                         if (rows != null) {
2346                                 start_index = rows.Length;
2347                                 Array.Copy (rows, 0, new_rows, 0, rows.Length < new_rows.Length ? rows.Length : new_rows.Length);
2348                         }
2349
2350                         for (int i = start_index; i < new_rows.Length; i ++) {
2351                                 new_rows[i] = new DataGridRelationshipRow (this);
2352                                 new_rows[i].height = RowHeight;
2353                                 if (i > 0)
2354                                         new_rows[i].VerticalOffset = new_rows[i-1].VerticalOffset + new_rows[i-1].Height;
2355                         }
2356
2357                         rows = new_rows;
2358
2359                         if (recalc)
2360                                 CalcAreasAndInvalidate ();
2361                 }
2362
2363                 internal void UpdateRowsFrom (DataGridRelationshipRow row)
2364                 {
2365                         int start_index = Array.IndexOf (rows, row);
2366                         if (start_index == -1)
2367                                 return;
2368
2369                         for (int i = start_index + 1; i < rows.Length; i ++)
2370                                 rows[i].VerticalOffset = rows[i-1].VerticalOffset + rows[i-1].Height;
2371
2372                         CalcAreasAndInvalidate ();
2373                 }
2374
2375                 void BindColumns ()
2376                 {
2377                         if (list_manager != null) {
2378                                 string list_name = list_manager.GetListName (null);
2379                                 if (TableStyles[list_name] == null) {
2380                                         // no style exists by the supplied name
2381                                         current_style.GridColumnStyles.Clear ();
2382                                         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);
2388                                 } else {
2389                                         current_style.CreateColumnsForTable (true);
2390                                 }
2391                         } else
2392                                 current_style.CreateColumnsForTable (false);
2393                 }
2394
2395                 private void OnListManagerMetaDataChanged (object sender, EventArgs e)
2396                 {
2397                         // XXX
2398
2399                         //we need to rethink this, as in 2.0 we get this event when a column is added to a table.
2400                         // forcing a rebind of columns means that we fail bug #80422.  disable this for now.
2401                         //
2402                         // BindColumns ();
2403                 }
2404
2405                 private void OnListManagerPositionChanged (object sender, EventArgs e)
2406                 {
2407                         from_positionchanged_handler = true;
2408                         CurrentRow = list_manager.Position;
2409                         from_positionchanged_handler = false;
2410                 }
2411
2412                 private void OnListManagerItemChanged (object sender, ItemChangedEventArgs e)
2413                 {
2414                         if (e.Index == -1) {
2415                                 ResetSelection ();
2416                                 if (rows == null || RowsCount != rows.Length - (ShowEditRow ? 1 : 0))
2417                                         RecreateDataGridRows (true);
2418                         } else {
2419                                 InvalidateRow (e.Index);
2420                         }
2421                 }
2422
2423                 private void OnTableStylesCollectionChanged (object sender, CollectionChangeEventArgs e)
2424                 {
2425                         if (ListManager == null)
2426                                 return;
2427                         
2428                         string list_name = ListManager.GetListName (null);
2429                         switch (e.Action) {
2430                         case CollectionChangeAction.Add:
2431                                 if (e.Element != null && String.Compare (list_name, ((DataGridTableStyle)e.Element).MappingName, true) == 0) {
2432                                         CurrentTableStyle = (DataGridTableStyle)e.Element;
2433                                         ((DataGridTableStyle) e.Element).CreateColumnsForTable (false);
2434                                 }
2435                                 break;
2436                         case CollectionChangeAction.Remove:
2437                                 if (e.Element != null && String.Compare (list_name, ((DataGridTableStyle)e.Element).MappingName, true) == 0) {
2438                                         CurrentTableStyle = default_style;
2439                                         current_style.GridColumnStyles.Clear ();
2440                                         current_style.CreateColumnsForTable (false);
2441                                 }
2442                                 break;
2443                         case CollectionChangeAction.Refresh:
2444                                 if (CurrentTableStyle == default_style
2445                                         || String.Compare (list_name, CurrentTableStyle.MappingName, true) != 0) {
2446                                         DataGridTableStyle style = styles_collection [list_name];
2447                                         if (style != null) {
2448                                                 CurrentTableStyle = style;
2449                                                 current_style.CreateColumnsForTable (false);
2450                                         } else {
2451                                                 CurrentTableStyle = default_style;
2452                                                 current_style.GridColumnStyles.Clear ();
2453                                                 current_style.CreateColumnsForTable (false);
2454                                         }
2455                                 }
2456                                 break;
2457                         }
2458                         CalcAreasAndInvalidate ();
2459                 }
2460
2461                 private void AddNewRow ()
2462                 {
2463                         ListManager.EndCurrentEdit ();
2464                         ListManager.AddNew ();
2465                 }
2466
2467                 private void Edit ()
2468                 {
2469                         if (CurrentTableStyle.GridColumnStyles.Count == 0)
2470                                 return;
2471
2472                         if (!CurrentTableStyle.GridColumnStyles[CurrentColumn].bound)
2473                                 return;
2474
2475                         is_editing = true;
2476                         is_changing = false;
2477
2478                         CurrentTableStyle.GridColumnStyles[CurrentColumn].Edit (ListManager,
2479                                 CurrentRow, GetCellBounds (CurrentRow, CurrentColumn),
2480                                 _readonly, null, true);
2481                 }
2482
2483                 private void EndEdit ()
2484                 {
2485                         if (CurrentTableStyle.GridColumnStyles.Count == 0)
2486                                 return;
2487
2488                         if (!CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber].bound)
2489                                 return;
2490
2491                         EndEdit (CurrentTableStyle.GridColumnStyles[current_cell.ColumnNumber],
2492                                 current_cell.RowNumber, false);
2493                 }
2494
2495                 private void ShiftSelection (int index)
2496                 {
2497                         // we have to save off selection_start
2498                         // because ResetSelection clobbers it
2499                         int saved_selection_start = selection_start;
2500                         int start, end;
2501
2502                         ResetSelection ();
2503                         selection_start = saved_selection_start;
2504
2505                         if (index >= selection_start) {
2506                                 start = selection_start;
2507                                 end = index;
2508                         } else {
2509                                 start = index;
2510                                 end = selection_start;
2511                         }
2512
2513                         if (start == -1) start = 0;
2514
2515                         for (int idx = start; idx <= end; idx ++)
2516                                 Select (idx);
2517                 }
2518
2519                 private void ScrollToColumnInPixels (int pixel)
2520                 {
2521                         int pixels;
2522
2523                         if (pixel > horiz_pixeloffset) // ScrollRight
2524                                 pixels = -1 * (pixel - horiz_pixeloffset);
2525                         else
2526                                 pixels = horiz_pixeloffset - pixel;
2527
2528                         Rectangle area = cells_area;
2529
2530                         if (ColumnHeadersVisible) {
2531                                 area.Y -= ColumnHeadersArea.Height;
2532                                 area.Height += ColumnHeadersArea.Height;
2533                         }
2534                                 
2535                         horiz_pixeloffset = pixel;
2536                         UpdateVisibleColumn ();
2537
2538                         EndEdit ();
2539
2540                         XplatUI.ScrollWindow (Handle, area, pixels, 0, false);
2541
2542                         int pixel_offset = GetColumnStartingPixel (CurrentColumn);
2543                         int next_pixel_offset = pixel_offset + CurrentTableStyle.GridColumnStyles[CurrentColumn].Width;
2544
2545                         if (pixel_offset >= horiz_pixeloffset
2546                             && next_pixel_offset < horiz_pixeloffset + cells_area.Width)
2547                                 Edit ();
2548                 }
2549
2550                 private void ScrollToRow (int old_row, int new_row)
2551                 {
2552                         int pixels = 0;
2553                         int i;
2554
2555                         if (new_row > old_row) { // Scrolldown
2556                                 for (i = old_row; i < new_row; i ++)
2557                                         pixels -= rows[i].Height;
2558                         } else {
2559                                 for (i = new_row; i < old_row; i ++)
2560                                         pixels += rows[i].Height;
2561                         }
2562
2563                         if (pixels == 0)
2564                                 return;
2565
2566                         EndEdit ();
2567
2568                         Rectangle rows_area = cells_area; // Cells area - partial rows space
2569
2570                         if (RowHeadersVisible) {
2571                                 rows_area.X -= RowHeaderWidth;
2572                                 rows_area.Width += RowHeaderWidth;
2573                         }
2574
2575                         /* scroll the window */
2576                         XplatUI.ScrollWindow (Handle, rows_area, 0, pixels, false);
2577
2578                         /* if the row is still */
2579                         if (CurrentRow >= first_visible_row && CurrentRow < first_visible_row + visible_row_count)
2580                                 Edit ();
2581                 }
2582
2583
2584                 private void ColumnResize (int column) 
2585                 {
2586                         CurrencyManager source = this.ListManager;
2587                         DataGridColumnStyle style = CurrentTableStyle.GridColumnStyles[column];
2588                         string headerText = style.HeaderText;
2589                         using (Graphics g = base.CreateGraphics ()) {
2590                                 int rows = source.Count;
2591                                 int width = (int)g.MeasureString (headerText, CurrentTableStyle.HeaderFont).Width + 4;
2592
2593                                 for (int i = 0; i < rows; i++) {
2594                                         int rowColWidth = (int)style.GetPreferredSize (g, style.GetColumnValueAtRow (source, i)).Width;
2595                                         if (rowColWidth > width)
2596                                                 width = rowColWidth;
2597                                 }
2598                                 if (style.Width != width)
2599                                         style.Width = width;
2600                         }
2601                 }
2602
2603                 private void RowResize (int row)
2604                 {
2605                         CurrencyManager source = this.ListManager;
2606                         using (Graphics g = base.CreateGraphics ()) {
2607                                 GridColumnStylesCollection columns = CurrentTableStyle.GridColumnStyles;
2608                                 int colCount = columns.Count;
2609                                 //int rowCount = source.Count;
2610                                 int height = 0;
2611                                 for (int i = 0; i < colCount; i++) {
2612                                         object val = columns[i].GetColumnValueAtRow (source, row);
2613                                         height = Math.Max (columns[i].GetPreferredHeight (g, val), height);
2614                                 }
2615                                 if (this.DataGridRows[row].Height != height)
2616                                         this.DataGridRows[row].Height = height;
2617                         }
2618                 }
2619                 #endregion Private Instance Methods
2620
2621                 #region Events
2622                 static object AllowNavigationChangedEvent = new object ();
2623                 static object BackButtonClickEvent = new object ();
2624                 static object BackgroundColorChangedEvent = new object ();
2625                 static object BorderStyleChangedEvent = new object ();
2626                 static object CaptionVisibleChangedEvent = new object ();
2627                 static object CurrentCellChangedEvent = new object ();
2628                 static object DataSourceChangedEvent = new object ();
2629                 static object FlatModeChangedEvent = new object ();
2630                 static object NavigateEvent = new object ();
2631                 static object ParentRowsLabelStyleChangedEvent = new object ();
2632                 static object ParentRowsVisibleChangedEvent = new object ();
2633                 static object ReadOnlyChangedEvent = new object ();
2634                 static object RowHeaderClickEvent = new object ();
2635                 static object ScrollEvent = new object ();
2636                 static object ShowParentDetailsButtonClickEvent = new object ();
2637
2638                 public event EventHandler AllowNavigationChanged {
2639                         add { Events.AddHandler (AllowNavigationChangedEvent, value); }
2640                         remove { Events.RemoveHandler (AllowNavigationChangedEvent, value); }
2641                 }
2642
2643                 public event EventHandler BackButtonClick {
2644                         add { Events.AddHandler (BackButtonClickEvent, value); }
2645                         remove { Events.RemoveHandler (BackButtonClickEvent, value); }
2646                 }
2647
2648                 public event EventHandler BackgroundColorChanged {
2649                         add { Events.AddHandler (BackgroundColorChangedEvent, value); }
2650                         remove { Events.RemoveHandler (BackgroundColorChangedEvent, value); }
2651                 }
2652
2653                 [Browsable(false)]
2654                 [EditorBrowsable(EditorBrowsableState.Never)]
2655                 public new event EventHandler BackgroundImageChanged {
2656                         add { base.BackgroundImageChanged += value; }
2657                         remove { base.BackgroundImageChanged -= value; }
2658                 }
2659
2660 #if NET_2_0
2661                 [Browsable(false)]
2662                 [EditorBrowsable(EditorBrowsableState.Never)]
2663                 public new event EventHandler BackgroundImageLayoutChanged {
2664                         add { base.BackgroundImageLayoutChanged += value; }
2665                         remove { base.BackgroundImageLayoutChanged -= value; }
2666                 }
2667 #endif
2668
2669                 [Browsable(false)]
2670                 [EditorBrowsable(EditorBrowsableState.Never)]
2671                 public new event EventHandler TextChanged {
2672                         add { base.TextChanged += value; }
2673                         remove { base.TextChanged -= value; }
2674                 }
2675
2676                 [Browsable(false)]
2677                 [EditorBrowsable(EditorBrowsableState.Never)]
2678                 public new event EventHandler CursorChanged {
2679                         add { base.CursorChanged += value; }
2680                         remove { base.CursorChanged -= value; }
2681                 }
2682
2683                 public event EventHandler BorderStyleChanged {
2684                         add { Events.AddHandler (BorderStyleChangedEvent, value); }
2685                         remove { Events.RemoveHandler (BorderStyleChangedEvent, value); }
2686                 }
2687
2688                 public event EventHandler CaptionVisibleChanged {
2689                         add { Events.AddHandler (CaptionVisibleChangedEvent, value); }
2690                         remove { Events.RemoveHandler (CaptionVisibleChangedEvent, value); }
2691                 }
2692
2693                 public event EventHandler CurrentCellChanged {
2694                         add { Events.AddHandler (CurrentCellChangedEvent, value); }
2695                         remove { Events.RemoveHandler (CurrentCellChangedEvent, value); }
2696                 }
2697
2698                 public event EventHandler DataSourceChanged {
2699                         add { Events.AddHandler (DataSourceChangedEvent, value); }
2700                         remove { Events.RemoveHandler (DataSourceChangedEvent, value); }
2701                 }
2702
2703                 public event EventHandler FlatModeChanged {
2704                         add { Events.AddHandler (FlatModeChangedEvent, value); }
2705                         remove { Events.RemoveHandler (FlatModeChangedEvent, value); }
2706                 }
2707
2708                 public event NavigateEventHandler Navigate {
2709                         add { Events.AddHandler (NavigateEvent, value); }
2710                         remove { Events.RemoveHandler (NavigateEvent, value); }
2711                 }
2712
2713                 public event EventHandler ParentRowsLabelStyleChanged {
2714                         add { Events.AddHandler (ParentRowsLabelStyleChangedEvent, value); }
2715                         remove { Events.RemoveHandler (ParentRowsLabelStyleChangedEvent, value); }
2716                 }
2717
2718                 public event EventHandler ParentRowsVisibleChanged {
2719                         add { Events.AddHandler (ParentRowsVisibleChangedEvent, value); }
2720                         remove { Events.RemoveHandler (ParentRowsVisibleChangedEvent, value); }
2721                 }
2722
2723                 public event EventHandler ReadOnlyChanged {
2724                         add { Events.AddHandler (ReadOnlyChangedEvent, value); }
2725                         remove { Events.RemoveHandler (ReadOnlyChangedEvent, value); }
2726                 }
2727
2728                 protected event EventHandler RowHeaderClick {
2729                         add { Events.AddHandler (RowHeaderClickEvent, value); }
2730                         remove { Events.RemoveHandler (RowHeaderClickEvent, value); }
2731                 }
2732
2733                 public event EventHandler Scroll {
2734                         add { Events.AddHandler (ScrollEvent, value); }
2735                         remove { Events.RemoveHandler (ScrollEvent, value); }
2736                 }
2737
2738                 public event EventHandler ShowParentDetailsButtonClick {
2739                         add { Events.AddHandler (ShowParentDetailsButtonClickEvent, value); }
2740                         remove { Events.RemoveHandler (ShowParentDetailsButtonClickEvent, value); }
2741                 }
2742                 #endregion      // Events
2743
2744                 #region Code originally in DataGridDrawingLogic.cs
2745
2746                 #region Local Variables
2747
2748                 // Areas
2749                 Rectangle parent_rows;
2750                 int width_of_all_columns;
2751
2752                 internal Rectangle caption_area;
2753                 internal Rectangle column_headers_area; // Used columns header area
2754                 internal int column_headers_max_width;  // Total width (max width) for columns headrs
2755                 internal Rectangle row_headers_area;    // Used Headers rows area
2756                 internal Rectangle cells_area;
2757                 #endregion // Local Variables
2758
2759                 #region Public Instance Methods
2760
2761                 // Calc the max with of all columns
2762                 int CalcAllColumnsWidth ()
2763                 {
2764                         int width = 0;
2765                         int cnt = CurrentTableStyle.GridColumnStyles.Count;
2766
2767                         for (int col = 0; col < cnt; col++) {
2768                                 if (CurrentTableStyle.GridColumnStyles[col].bound == false) {
2769                                         continue;
2770                                 }
2771                                 width += CurrentTableStyle.GridColumnStyles[col].Width;
2772                         }
2773                         return width;
2774                 }
2775
2776                 // Gets a column from a pixel
2777                 int FromPixelToColumn (int pixel, out int column_x)
2778                 {
2779                         int width = 0;
2780                         int cnt = CurrentTableStyle.GridColumnStyles.Count;
2781                         column_x = 0;
2782
2783                         if (cnt == 0)
2784                                 return 0;
2785                                 
2786                         if (CurrentTableStyle.CurrentRowHeadersVisible) {
2787                                 width += row_headers_area.X + row_headers_area.Width;
2788                                 column_x += row_headers_area.X + row_headers_area.Width;
2789                         }
2790
2791                         for (int col = 0; col < cnt; col++) {
2792                                 if (CurrentTableStyle.GridColumnStyles[col].bound == false)
2793                                         continue;
2794
2795                                 width += CurrentTableStyle.GridColumnStyles[col].Width;
2796
2797                                 if (pixel < width)
2798                                         return col;
2799
2800                                 column_x += CurrentTableStyle.GridColumnStyles[col].Width;
2801                         }
2802
2803                         return cnt - 1;
2804                 }
2805
2806                 internal int GetColumnStartingPixel (int my_col)
2807                 {
2808                         int width = 0;
2809                         int cnt = CurrentTableStyle.GridColumnStyles.Count;
2810
2811                         for (int col = 0; col < cnt; col++) {
2812                                 if (CurrentTableStyle.GridColumnStyles[col].bound == false) {
2813                                         continue;
2814                                 }
2815
2816                                 if (my_col == col)
2817                                         return width;
2818
2819                                 width += CurrentTableStyle.GridColumnStyles[col].Width;
2820                         }
2821
2822                         return 0;
2823                 }
2824                 
2825                 // Which column has to be the first visible column to ensure a column visibility
2826                 int GetFirstColumnForColumnVisibility (int current_first_visible_column, int column)
2827                 {
2828                         int new_col = column;
2829                         int width = 0;
2830                         
2831                         if (column > current_first_visible_column) { // Going forward
2832                                 for (new_col = column; new_col >= 0; new_col--) {
2833                                         if (!CurrentTableStyle.GridColumnStyles[new_col].bound)
2834                                                 continue;
2835                                         width += CurrentTableStyle.GridColumnStyles[new_col].Width;
2836                                         
2837                                         if (width >= cells_area.Width)
2838                                                 return new_col + 1;
2839                                                 //return new_col < CurrentTableStyle.GridColumnStyles.Count ? new_col + 1 : CurrentTableStyle.GridColumnStyles.Count;
2840                                 }
2841                                 return 0;
2842                         } else {
2843                                 return  column;
2844                         }
2845                 }
2846
2847                 bool in_calc_grid_areas;
2848                 void CalcGridAreas ()
2849                 {
2850                         if (!IsHandleCreated) // Delay calculations until the handle is created
2851                                 return;
2852
2853                         /* make sure we don't happen to end up in this method again */
2854                         if (in_calc_grid_areas)
2855                                 return;
2856
2857                         in_calc_grid_areas = true;
2858
2859                         /* Order is important. E.g. row headers max. height depends on caption */
2860                         horiz_pixeloffset = 0;
2861                         CalcCaption ();
2862                         CalcParentRows ();
2863                         CalcParentButtons ();
2864                         UpdateVisibleRowCount ();
2865                         CalcRowHeaders ();
2866                         width_of_all_columns = CalcAllColumnsWidth ();
2867                         CalcColumnHeaders ();
2868                         CalcCellsArea ();
2869
2870                         bool needHoriz = false;
2871                         bool needVert = false;
2872
2873                         /* figure out which scrollbars we need, and what the visible areas are */
2874                         int visible_cells_width = cells_area.Width;
2875                         int visible_cells_height = cells_area.Height;
2876                         int allrows = RowsCount;
2877
2878                         if (ShowEditRow && RowsCount > 0)
2879                                 allrows++;
2880
2881                         /* use a loop to iteratively calculate whether
2882                          * we need horiz/vert scrollbars. */
2883                         for (int i = 0; i < 3; i++) {
2884                                 if (needVert)
2885                                         visible_cells_width = cells_area.Width - vert_scrollbar.Width;
2886                                 if (needHoriz)
2887                                         visible_cells_height = cells_area.Height - horiz_scrollbar.Height;
2888
2889                                 UpdateVisibleRowCount ();
2890
2891                                 needHoriz = (width_of_all_columns > visible_cells_width);
2892                                 needVert = (allrows > visible_row_count);
2893                         }
2894
2895                         int horiz_scrollbar_width = ClientRectangle.Width;
2896                         int horiz_scrollbar_maximum = 0;
2897                         int vert_scrollbar_height = 0;
2898                         int vert_scrollbar_maximum = 0;
2899
2900                         if (needVert)
2901                                 SetUpVerticalScrollBar (out vert_scrollbar_height, out vert_scrollbar_maximum);
2902
2903                         if (needHoriz)
2904                                 SetUpHorizontalScrollBar (out horiz_scrollbar_maximum);
2905
2906                         cells_area.Width = visible_cells_width;
2907                         cells_area.Height = visible_cells_height;
2908
2909                         if (needVert && needHoriz) {
2910                                 if (ShowParentRows)
2911                                         parent_rows.Width -= vert_scrollbar.Width;
2912
2913                                 if (!ShowingColumnHeaders) {
2914                                         if (column_headers_area.X + column_headers_area.Width > vert_scrollbar.Location.X) {
2915                                                 column_headers_area.Width -= vert_scrollbar.Width;
2916                                         }
2917                                 }
2918
2919                                 horiz_scrollbar_width -= vert_scrollbar.Width;
2920                                 vert_scrollbar_height -= horiz_scrollbar.Height;
2921                         }
2922
2923                         if (needVert) {
2924                                 if (row_headers_area.Y + row_headers_area.Height > ClientRectangle.Y + ClientRectangle.Height) {
2925                                         row_headers_area.Height -= horiz_scrollbar.Height;
2926                                 }
2927
2928                                 vert_scrollbar.Size = new Size (vert_scrollbar.Width,
2929                                                                 vert_scrollbar_height);
2930
2931                                 vert_scrollbar.Maximum = vert_scrollbar_maximum;
2932                                 Controls.Add (vert_scrollbar);
2933                                 vert_scrollbar.Visible = true;
2934                         } else {
2935                                 Controls.Remove (vert_scrollbar);
2936                                 vert_scrollbar.Visible = false;
2937                         }
2938
2939                         if (needHoriz) {
2940                                 horiz_scrollbar.Size = new Size (horiz_scrollbar_width,
2941                                         horiz_scrollbar.Height);
2942
2943                                 horiz_scrollbar.Maximum = horiz_scrollbar_maximum;
2944                                 Controls.Add (horiz_scrollbar);
2945                                 horiz_scrollbar.Visible = true;
2946                         } else {
2947                                 Controls.Remove (horiz_scrollbar);
2948                                 horiz_scrollbar.Visible = false;
2949                         }
2950
2951                         UpdateVisibleColumn ();
2952                         UpdateVisibleRowCount ();
2953
2954                         in_calc_grid_areas = false;
2955                 }
2956
2957                 void CalcCaption ()
2958                 {
2959                         caption_area.X = ClientRectangle.X;
2960                         caption_area.Y = ClientRectangle.Y;
2961                         caption_area.Width = ClientRectangle.Width;
2962                         if (caption_visible) {
2963                                 caption_area.Height = CaptionFont.Height;
2964                                 if (caption_area.Height < back_button_image.Height)
2965                                         caption_area.Height = back_button_image.Height;
2966                                 caption_area.Height += 2;
2967                         } else
2968                                 caption_area.Height = 0;
2969                 }
2970
2971                 void CalcCellsArea ()
2972                 {
2973                         cells_area.X = ClientRectangle.X + row_headers_area.Width;
2974                         cells_area.Y = column_headers_area.Y + column_headers_area.Height;
2975                         cells_area.Width = ClientRectangle.X + ClientRectangle.Width - cells_area.X;
2976                         if (cells_area.Width < 0)
2977                                 cells_area.Width = 0;
2978                         cells_area.Height = ClientRectangle.Y + ClientRectangle.Height - cells_area.Y;
2979                         if (cells_area.Height < 0)
2980                                 cells_area.Height = 0;
2981                 }
2982
2983                 void CalcColumnHeaders ()
2984                 {
2985                         int max_width_cols;
2986
2987                         column_headers_area.X = ClientRectangle.X;
2988                         column_headers_area.Y = parent_rows.Y + parent_rows.Height;
2989
2990                         // TODO: take into account Scrollbars
2991                         column_headers_max_width = ClientRectangle.X + ClientRectangle.Width - column_headers_area.X;
2992                         max_width_cols = column_headers_max_width;
2993
2994                         if (CurrentTableStyle.CurrentRowHeadersVisible)
2995                                 max_width_cols -= RowHeaderWidth;
2996
2997                         if (width_of_all_columns > max_width_cols) {
2998                                 column_headers_area.Width = column_headers_max_width;
2999                         } else {
3000                                 column_headers_area.Width = width_of_all_columns;
3001
3002                                 if (CurrentTableStyle.CurrentRowHeadersVisible)
3003                                         column_headers_area.Width += RowHeaderWidth;
3004                         }
3005
3006                         if (ShowingColumnHeaders)
3007                                 column_headers_area.Height = CurrentTableStyle.HeaderFont.Height + 6;
3008                         else
3009                                 column_headers_area.Height = 0;
3010                 }
3011
3012                 void CalcParentRows ()
3013                 {
3014                         parent_rows.X = ClientRectangle.X;
3015                         parent_rows.Y = caption_area.Y + caption_area.Height;
3016                         parent_rows.Width = ClientRectangle.Width;
3017                         if (ShowParentRows)
3018                                 parent_rows.Height = (CaptionFont.Height + 3) * data_source_stack.Count;
3019                         else
3020                                 parent_rows.Height = 0;
3021                 }
3022
3023                 void CalcParentButtons ()
3024                 {
3025                         if (data_source_stack.Count > 0 && CaptionVisible) {
3026                                 back_button_rect = new Rectangle (ClientRectangle.X + ClientRectangle.Width - 2 * (caption_area.Height - 2) - 8,
3027                                                                   caption_area.Height / 2 - back_button_image.Height / 2,
3028                                                                   back_button_image.Width, back_button_image.Height);
3029                                 parent_rows_button_rect = new Rectangle (ClientRectangle.X + ClientRectangle.Width - (caption_area.Height - 2) - 4,
3030                                                                          caption_area.Height / 2 - parent_rows_button_image.Height / 2,
3031                                                                          parent_rows_button_image.Width, parent_rows_button_image.Height);
3032                         } else {
3033                                 back_button_rect = parent_rows_button_rect = Rectangle.Empty;
3034                         }
3035                 }
3036
3037                 void CalcRowHeaders ()
3038                 {
3039                         row_headers_area.X = ClientRectangle.X;
3040                         row_headers_area.Y = column_headers_area.Y + column_headers_area.Height;
3041                         row_headers_area.Height = ClientRectangle.Height + ClientRectangle.Y - row_headers_area.Y;
3042
3043                         if (CurrentTableStyle.CurrentRowHeadersVisible)
3044                                 row_headers_area.Width = RowHeaderWidth;
3045                         else
3046                                 row_headers_area.Width = 0;
3047                 }
3048
3049                 int GetVisibleRowCount (int visibleHeight)
3050                 {
3051                         int rows_height = 0;
3052                         int r;
3053                         for (r = FirstVisibleRow; r < rows.Length; r ++) {
3054                                 if (rows_height + rows[r].Height >= visibleHeight)
3055                                         break;
3056                                 rows_height += rows[r].Height;
3057                         }
3058
3059                         if (r <= rows.Length - 1)
3060                                 r ++;
3061
3062                         return r - FirstVisibleRow;
3063                 }
3064
3065                 void UpdateVisibleColumn ()
3066                 {
3067                         if (CurrentTableStyle.GridColumnStyles.Count == 0) {
3068                                 visible_column_count = 0;
3069                                 return;
3070                         }
3071                         
3072                         int col;
3073                         int max_pixel = horiz_pixeloffset + cells_area.Width;
3074                         int unused;
3075
3076                         first_visible_column = FromPixelToColumn (horiz_pixeloffset, out unused);
3077
3078                         col = FromPixelToColumn (max_pixel, out unused);
3079                         
3080                         visible_column_count = 1 + col - first_visible_column;
3081
3082                         visible_column_count = 0;
3083                         for (int i = first_visible_column; i <= col; i ++) {
3084                                 if (CurrentTableStyle.GridColumnStyles[i].bound)
3085                                         visible_column_count++;
3086                         }
3087
3088                         if (first_visible_column + visible_column_count < CurrentTableStyle.GridColumnStyles.Count) { 
3089                                 visible_column_count++; // Partially visible column
3090                         }
3091                 }
3092
3093                 void UpdateVisibleRowCount ()
3094                 {
3095                         visible_row_count = GetVisibleRowCount (cells_area.Height);
3096
3097                         CalcRowHeaders (); // Height depends on num of visible rows
3098                 }
3099
3100                 void InvalidateCaption ()
3101                 {
3102                         if (caption_area.IsEmpty)
3103                                 return;
3104
3105                         Invalidate (caption_area);
3106                 }
3107
3108                 void InvalidateRow (int row)
3109                 {
3110                         if (row < FirstVisibleRow || row > FirstVisibleRow + VisibleRowCount)
3111                                 return;
3112
3113                         Rectangle rect_row = new Rectangle ();
3114
3115                         rect_row.X = cells_area.X;
3116                         rect_row.Width = width_of_all_columns;
3117                         if (rect_row.Width > cells_area.Width)
3118                                 rect_row.Width = cells_area.Width;
3119                         rect_row.Height = rows[row].Height;
3120                         rect_row.Y = cells_area.Y + rows[row].VerticalOffset - rows[FirstVisibleRow].VerticalOffset;
3121                         Invalidate (rect_row);
3122                 }
3123
3124                 void InvalidateRowHeader (int row)
3125                 {
3126                         Rectangle rect_rowhdr = new Rectangle ();
3127                         rect_rowhdr.X = row_headers_area.X;
3128                         rect_rowhdr.Width = row_headers_area.Width;
3129                         rect_rowhdr.Height = rows[row].Height;
3130                         rect_rowhdr.Y = row_headers_area.Y + rows[row].VerticalOffset - rows[FirstVisibleRow].VerticalOffset;
3131                         Invalidate (rect_rowhdr);
3132                 }
3133
3134                 internal void InvalidateColumn (DataGridColumnStyle column)
3135                 {
3136                         Rectangle rect_col = new Rectangle ();
3137                         int col_pixel;
3138                         int col = -1;
3139
3140                         col = CurrentTableStyle.GridColumnStyles.IndexOf (column);
3141
3142                         if (col == -1)
3143                                 return;
3144
3145                         rect_col.Width = column.Width;
3146                         col_pixel = GetColumnStartingPixel (col);
3147                         rect_col.X = cells_area.X + col_pixel - horiz_pixeloffset;
3148                         rect_col.Y = cells_area.Y;
3149                         rect_col.Height = cells_area.Height;
3150                         Invalidate (rect_col);
3151                 }
3152
3153                 void DrawResizeLineVert (int x)
3154                 {
3155                         XplatUI.DrawReversibleRectangle (Handle,
3156                                                          new Rectangle (x, cells_area.Y, 1, cells_area.Height - 3),
3157                                                          2);
3158                 }
3159
3160                 void DrawResizeLineHoriz (int y)
3161                 {
3162                         XplatUI.DrawReversibleRectangle (Handle,
3163                                                          new Rectangle (cells_area.X, y, cells_area.Width - 3, 1),
3164                                                          2);
3165                 }
3166
3167                 void SetUpHorizontalScrollBar (out int maximum)
3168                 {
3169                         maximum = width_of_all_columns;
3170
3171                         horiz_scrollbar.Location = new Point (ClientRectangle.X, ClientRectangle.Y +
3172                                 ClientRectangle.Height - horiz_scrollbar.Height);
3173
3174                         horiz_scrollbar.LargeChange = cells_area.Width;
3175                 }
3176
3177                 void SetUpVerticalScrollBar (out int height, out int maximum)
3178                 {
3179                         int y;
3180                         
3181                         y = ClientRectangle.Y + parent_rows.Y + parent_rows.Height;
3182                         height = ClientRectangle.Height - parent_rows.Y - parent_rows.Height;
3183
3184                         vert_scrollbar.Location = new Point (ClientRectangle.X +
3185                                                              ClientRectangle.Width - vert_scrollbar.Width, y);
3186
3187                         maximum = RowsCount;
3188                         
3189                         if (ShowEditRow && RowsCount > 0) {
3190                                 maximum++;
3191                         }
3192                         
3193                         vert_scrollbar.LargeChange = VLargeChange;
3194                 }
3195
3196                 #endregion // Public Instance Methods
3197
3198                 #region Instance Properties
3199                 // Returns the ColumnHeaders area excluding the rectangle shared with RowHeaders
3200                 internal Rectangle ColumnHeadersArea {
3201                         get {
3202                                 Rectangle columns_area = column_headers_area;
3203
3204                                 if (CurrentTableStyle.CurrentRowHeadersVisible) {
3205                                         columns_area.X += RowHeaderWidth;
3206                                         columns_area.Width -= RowHeaderWidth;
3207                                 }
3208                                 return columns_area;
3209                         }
3210                 }
3211
3212                 bool ShowingColumnHeaders {
3213                         get { return ColumnHeadersVisible && CurrentTableStyle.GridColumnStyles.Count > 0; }
3214                 }
3215
3216                 internal Rectangle RowHeadersArea {
3217                         get { return row_headers_area; }
3218                 }
3219
3220                 internal Rectangle ParentRowsArea {
3221                         get { return parent_rows; }
3222                 }
3223
3224                 int VLargeChange {
3225                         get { return VisibleRowCount; }
3226                 }
3227
3228                 #endregion Instance Properties
3229
3230                 #endregion // Code originally in DataGridDrawingLogic.cs
3231         }
3232 }