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