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