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