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