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