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 
DataGridRelationshipRow(DataGrid owner)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 
DataGridDataSource(DataGrid owner, CurrencyManager list_manager, object data_source, string data_member, object view_data, DataGridCell current)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
HitTestInfo()141 			internal HitTestInfo () : this (-1, -1, HitTestType.None)
142 			{
143 			}
144 
HitTestInfo(int row, int column, DataGrid.HitTestType type)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 
Equals(object value)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 
GetHashCode()176 			public override int GetHashCode ()
177 			{
178 				return row ^ column;
179 			}
180 
ToString()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
DataGrid()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 
EditRowChanged(DataGridColumnStyle column_style)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 
AbortEditing()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 
BeginEdit(DataGridColumnStyle gridColumn, int rowNumber)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 
BeginInit()1014 		public void BeginInit ()
1015 		{
1016 		}
1017 
CancelEditing()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 
Collapse(int row)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 
ColumnStartedEditing(Control editingControl)1057 		protected internal virtual void ColumnStartedEditing (Control editingControl)
1058 		{
1059 			ColumnStartedEditing (editingControl.Bounds);
1060 		}
1061 
ColumnStartedEditing(Rectangle bounds)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 
CreateAccessibilityInstance()1076 		protected override AccessibleObject CreateAccessibilityInstance ()
1077 		{
1078 			return base.CreateAccessibilityInstance ();
1079 		}
1080 
CreateGridColumn(PropertyDescriptor prop)1081 		protected virtual DataGridColumnStyle CreateGridColumn (PropertyDescriptor prop)
1082 		{
1083 			return CreateGridColumn (prop, false);
1084 		}
1085 
1086 		[MonoTODO ("Not implemented, will throw NotImplementedException")]
CreateGridColumn(PropertyDescriptor prop, bool isDefault)1087 		protected virtual DataGridColumnStyle CreateGridColumn (PropertyDescriptor prop, bool isDefault)
1088 		{
1089 			throw new NotImplementedException();
1090 		}
1091 
Dispose(bool disposing)1092 		protected override void Dispose (bool disposing)
1093 		{
1094 			base.Dispose (disposing);
1095 		}
1096 
EndEdit(DataGridColumnStyle gridColumn, int rowNumber, bool shouldAbort)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 
EndInit()1114 		public void EndInit ()
1115 		{
1116 			if (grid_style != null)
1117 				grid_style.DataGrid = this;
1118 		}
1119 
Expand(int row)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 
GetCellBounds(DataGridCell dgc)1156 		public Rectangle GetCellBounds (DataGridCell dgc)
1157 		{
1158 			return GetCellBounds (dgc.RowNumber, dgc.ColumnNumber);
1159 		}
1160 
GetCellBounds(int row, int col)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 
GetCurrentCellBounds()1174 		public Rectangle GetCurrentCellBounds ()
1175 		{
1176 			return GetCellBounds (current_cell.RowNumber, current_cell.ColumnNumber);
1177 		}
1178 
GetOutputTextDelimiter()1179 		protected virtual string GetOutputTextDelimiter ()
1180 		{
1181 			return string.Empty;
1182 		}
1183 
GridHScrolled(object sender, ScrollEventArgs se)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 
GridVScrolled(object sender, ScrollEventArgs se)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 
HitTest(Point position)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
HitTest(int x, int y)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 
IsExpanded(int rowNumber)1297 		public bool IsExpanded (int rowNumber)
1298 		{
1299 			return (rows[rowNumber].IsExpanded);
1300 		}
1301 
IsSelected(int row)1302 		public bool IsSelected (int row)
1303 		{
1304 			return rows[row].IsSelected;
1305 		}
1306 
NavigateBack()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 
NavigateTo(int rowNumber, string relationName)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 
OnAllowNavigationChanged(EventArgs e)1354 		protected virtual void OnAllowNavigationChanged (EventArgs e)
1355 		{
1356 			EventHandler eh = (EventHandler)(Events [AllowNavigationChangedEvent]);
1357 			if (eh != null)
1358 				eh (this, e);
1359 		}
1360 
OnBackButtonClicked(object sender, EventArgs e)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 
OnBackColorChanged(EventArgs e)1368 		protected override void OnBackColorChanged (EventArgs e)
1369 		{
1370 			base.OnBackColorChanged (e);
1371 		}
1372 
OnBackgroundColorChanged(EventArgs e)1373 		protected virtual void OnBackgroundColorChanged (EventArgs e)
1374 		{
1375 			EventHandler eh = (EventHandler)(Events [BackgroundColorChangedEvent]);
1376 			if (eh != null)
1377 				eh (this, e);
1378 		}
1379 
OnBindingContextChanged(EventArgs e)1380 		protected override void OnBindingContextChanged (EventArgs e)
1381 		{
1382 			base.OnBindingContextChanged (e);
1383 
1384 			SetDataSource (datasource, datamember);
1385 		}
1386 
OnBorderStyleChanged(EventArgs e)1387 		protected virtual void OnBorderStyleChanged (EventArgs e)
1388 		{
1389 			EventHandler eh = (EventHandler)(Events [BorderStyleChangedEvent]);
1390 			if (eh != null)
1391 				eh (this, e);
1392 		}
1393 
OnCaptionVisibleChanged(EventArgs e)1394 		protected virtual void OnCaptionVisibleChanged (EventArgs e)
1395 		{
1396 			EventHandler eh = (EventHandler)(Events [CaptionVisibleChangedEvent]);
1397 			if (eh != null)
1398 				eh (this, e);
1399 		}
1400 
OnCurrentCellChanged(EventArgs e)1401 		protected virtual void OnCurrentCellChanged (EventArgs e)
1402 		{
1403 			EventHandler eh = (EventHandler)(Events [CurrentCellChangedEvent]);
1404 			if (eh != null)
1405 				eh (this, e);
1406 		}
1407 
OnDataSourceChanged(EventArgs e)1408 		protected virtual void OnDataSourceChanged (EventArgs e)
1409 		{
1410 			EventHandler eh = (EventHandler)(Events [DataSourceChangedEvent]);
1411 			if (eh != null)
1412 				eh (this, e);
1413 		}
1414 
OnEnter(EventArgs e)1415 		protected override void OnEnter (EventArgs e)
1416 		{
1417 			base.OnEnter (e);
1418 			Edit ();
1419 		}
1420 
OnFlatModeChanged(EventArgs e)1421 		protected virtual void OnFlatModeChanged (EventArgs e)
1422 		{
1423 			EventHandler eh = (EventHandler)(Events [FlatModeChangedEvent]);
1424 			if (eh != null)
1425 				eh (this, e);
1426 		}
1427 
OnFontChanged(EventArgs e)1428 		protected override void OnFontChanged (EventArgs e)
1429 		{
1430 			CalcGridAreas ();
1431 			base.OnFontChanged (e);
1432 		}
1433 
OnForeColorChanged(EventArgs e)1434 		protected override void OnForeColorChanged (EventArgs e)
1435 		{
1436 			base.OnForeColorChanged (e);
1437 		}
1438 
OnHandleCreated(EventArgs e)1439 		protected override void OnHandleCreated (EventArgs e)
1440 		{
1441 			base.OnHandleCreated (e);
1442 			SetDataSource (datasource, datamember);
1443 		}
1444 
OnHandleDestroyed(EventArgs e)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.
OnKeyDown(KeyEventArgs ke)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 
OnKeyPress(KeyPressEventArgs kpe)1470 		protected override void OnKeyPress (KeyPressEventArgs kpe)
1471 		{
1472 			base.OnKeyPress (kpe);
1473 		}
1474 
OnLayout(LayoutEventArgs levent)1475 		protected override void OnLayout (LayoutEventArgs levent)
1476 		{
1477 			base.OnLayout (levent);
1478 			CalcAreasAndInvalidate ();
1479 		}
1480 
OnLeave(EventArgs e)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 
OnMouseDown(MouseEventArgs e)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 
OnMouseLeave(EventArgs e)1645 		protected override void OnMouseLeave (EventArgs e)
1646 		{
1647 			base.OnMouseLeave (e);
1648 		}
1649 
OnMouseMove(MouseEventArgs e)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 
OnMouseUp(MouseEventArgs e)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 
OnMouseWheel(MouseEventArgs e)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 
OnNavigate(NavigateEventArgs e)1814 		protected void OnNavigate (NavigateEventArgs e)
1815 		{
1816 			EventHandler eh = (EventHandler)(Events [NavigateEvent]);
1817 			if (eh != null)
1818 				eh (this, e);
1819 		}
1820 
OnPaint(PaintEventArgs pe)1821 		protected override void OnPaint (PaintEventArgs pe)
1822 		{
1823 			ThemeEngine.Current.DataGridPaint (pe, this);
1824 		}
1825 
OnPaintBackground(PaintEventArgs ebe)1826 		protected override void OnPaintBackground (PaintEventArgs ebe)
1827 		{
1828 		}
1829 
OnParentRowsLabelStyleChanged(EventArgs e)1830 		protected virtual void OnParentRowsLabelStyleChanged (EventArgs e)
1831 		{
1832 			EventHandler eh = (EventHandler)(Events [ParentRowsLabelStyleChangedEvent]);
1833 			if (eh != null)
1834 				eh (this, e);
1835 		}
1836 
OnParentRowsVisibleChanged(EventArgs e)1837 		protected virtual void OnParentRowsVisibleChanged (EventArgs e)
1838 		{
1839 			EventHandler eh = (EventHandler)(Events [ParentRowsVisibleChangedEvent]);
1840 			if (eh != null)
1841 				eh (this, e);
1842 		}
1843 
OnReadOnlyChanged(EventArgs e)1844 		protected virtual void OnReadOnlyChanged (EventArgs e)
1845 		{
1846 			EventHandler eh = (EventHandler)(Events [ReadOnlyChangedEvent]);
1847 			if (eh != null)
1848 				eh (this, e);
1849 		}
1850 
OnResize(EventArgs e)1851 		protected override void OnResize (EventArgs e)
1852 		{
1853 			base.OnResize (e);
1854 		}
1855 
OnRowHeaderClick(EventArgs e)1856 		protected void OnRowHeaderClick (EventArgs e)
1857 		{
1858 			EventHandler eh = (EventHandler)(Events [RowHeaderClickEvent]);
1859 			if (eh != null)
1860 				eh (this, e);
1861 		}
1862 
OnScroll(EventArgs e)1863 		protected void OnScroll (EventArgs e)
1864 		{
1865 			EventHandler eh = (EventHandler)(Events [ScrollEvent]);
1866 			if (eh != null)
1867 				eh (this, e);
1868 		}
1869 
OnShowParentDetailsButtonClicked(object sender, EventArgs e)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 
ProcessDialogKey(Keys keyData)1877 		protected override bool ProcessDialogKey (Keys keyData)
1878 		{
1879 			return ProcessGridKey (new KeyEventArgs (keyData));
1880 		}
1881 
UpdateSelectionAfterCursorMove(bool extend_selection)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 
ProcessGridKey(KeyEventArgs ke)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 
ProcessKeyPreview(ref Message m)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 
ProcessTabKey(Keys keyData)2082 		protected bool ProcessTabKey (Keys keyData)
2083 		{
2084 			return false;
2085 		}
2086 
ResetAlternatingBackColor()2087 		public void ResetAlternatingBackColor ()
2088 		{
2089 			grid_style.AlternatingBackColor = default_style.AlternatingBackColor;
2090 		}
2091 
ResetBackColor()2092 		public override void ResetBackColor ()
2093 		{
2094 			grid_style.BackColor = default_style.BackColor;
2095 		}
2096 
ResetForeColor()2097 		public override void ResetForeColor ()
2098 		{
2099 			grid_style.ForeColor = default_style.ForeColor;
2100 		}
2101 
ResetGridLineColor()2102 		public void ResetGridLineColor ()
2103 		{
2104 			grid_style.GridLineColor = default_style.GridLineColor;
2105 		}
2106 
ResetHeaderBackColor()2107 		public void ResetHeaderBackColor ()
2108 		{
2109 			grid_style.HeaderBackColor = default_style.HeaderBackColor;
2110 		}
2111 
ResetHeaderFont()2112 		public void ResetHeaderFont ()
2113 		{
2114 			grid_style.HeaderFont = null;
2115 		}
2116 
ResetHeaderForeColor()2117 		public void ResetHeaderForeColor ()
2118 		{
2119 			grid_style.HeaderForeColor = default_style.HeaderForeColor;
2120 		}
2121 
ResetLinkColor()2122 		public void ResetLinkColor ()
2123 		{
2124 			grid_style.LinkColor = default_style.LinkColor;
2125 		}
2126 
ResetLinkHoverColor()2127 		public void ResetLinkHoverColor ()
2128 		{
2129 			grid_style.LinkHoverColor = default_style.LinkHoverColor;
2130 		}
2131 
ResetSelection()2132 		protected void ResetSelection ()
2133 		{
2134 			InvalidateSelection ();
2135 			selected_rows.Clear ();
2136 			selection_start = -1;
2137 		}
2138 
InvalidateSelection()2139 		void InvalidateSelection ()
2140 		{
2141 			foreach (int row in selected_rows.Keys) {
2142 				rows[row].IsSelected = false;
2143 				InvalidateRow (row);
2144 			}
2145 		}
2146 
ResetSelectionBackColor()2147 		public void ResetSelectionBackColor ()
2148 		{
2149 			grid_style.SelectionBackColor = default_style.SelectionBackColor;
2150 		}
2151 
ResetSelectionForeColor()2152 		public void ResetSelectionForeColor ()
2153 		{
2154 			grid_style.SelectionForeColor = default_style.SelectionForeColor;
2155 		}
2156 
Select(int row)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 
SetDataBinding(object dataSource, string dataMember)2178 		public void SetDataBinding (object dataSource, string dataMember)
2179 		{
2180 			SetDataSource (dataSource, dataMember);
2181 		}
2182 
ShouldSerializeAlternatingBackColor()2183 		protected virtual bool ShouldSerializeAlternatingBackColor ()
2184 		{
2185 			return (grid_style.AlternatingBackColor != default_style.AlternatingBackColor);
2186 		}
2187 
ShouldSerializeBackgroundColor()2188 		protected virtual bool ShouldSerializeBackgroundColor ()
2189 		{
2190 			return (background_color != def_background_color);
2191 		}
2192 
ShouldSerializeCaptionBackColor()2193 		protected virtual bool ShouldSerializeCaptionBackColor ()
2194 		{
2195 			return (caption_backcolor != def_caption_backcolor);
2196 		}
2197 
ShouldSerializeCaptionForeColor()2198 		protected virtual bool ShouldSerializeCaptionForeColor ()
2199 		{
2200 			return caption_forecolor != def_caption_forecolor;
2201 		}
2202 
ShouldSerializeGridLineColor()2203 		protected virtual bool ShouldSerializeGridLineColor ()
2204 		{
2205 			return grid_style.GridLineColor != default_style.GridLineColor;
2206 		}
2207 
ShouldSerializeHeaderBackColor()2208 		protected virtual bool ShouldSerializeHeaderBackColor ()
2209 		{
2210 			return grid_style.HeaderBackColor != default_style.HeaderBackColor;
2211 		}
2212 
ShouldSerializeHeaderFont()2213 		protected bool ShouldSerializeHeaderFont ()
2214 		{
2215 			return grid_style.HeaderFont != default_style.HeaderFont;
2216 		}
2217 
ShouldSerializeHeaderForeColor()2218 		protected virtual bool ShouldSerializeHeaderForeColor ()
2219 		{
2220 			return grid_style.HeaderForeColor != default_style.HeaderForeColor;
2221 		}
2222 
ShouldSerializeLinkHoverColor()2223 		protected virtual bool ShouldSerializeLinkHoverColor ()
2224 		{
2225 			return grid_style.LinkHoverColor != default_style.LinkHoverColor;
2226 		}
2227 
ShouldSerializeParentRowsBackColor()2228 		protected virtual bool ShouldSerializeParentRowsBackColor ()
2229 		{
2230 			return parent_rows_backcolor != def_parent_rows_backcolor;
2231 		}
2232 
ShouldSerializeParentRowsForeColor()2233 		protected virtual bool ShouldSerializeParentRowsForeColor ()
2234 		{
2235 			return parent_rows_backcolor != def_parent_rows_backcolor;
2236 		}
2237 
ShouldSerializePreferredRowHeight()2238 		protected bool ShouldSerializePreferredRowHeight ()
2239 		{
2240 			return grid_style.PreferredRowHeight != default_style.PreferredRowHeight;
2241 		}
2242 
ShouldSerializeSelectionBackColor()2243 		protected bool ShouldSerializeSelectionBackColor ()
2244 		{
2245 			return grid_style.SelectionBackColor != default_style.SelectionBackColor;
2246 		}
2247 
ShouldSerializeSelectionForeColor()2248 		protected virtual bool ShouldSerializeSelectionForeColor ()
2249 		{
2250 			return grid_style.SelectionForeColor != default_style.SelectionForeColor;
2251 		}
2252 
SubObjectsSiteChange(bool site)2253 		public void SubObjectsSiteChange (bool site)
2254 		{
2255 		}
2256 
UnSelect(int row)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 
CalcAreasAndInvalidate()2274 		internal void CalcAreasAndInvalidate ()
2275 		{
2276 			CalcGridAreas ();
2277 			Invalidate ();
2278 		}
2279 
ConnectListManagerEvents()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 
DisconnectListManagerEvents()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 
DisconnectTableStyleEvents()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 
ConnectTableStyleEvents()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 
TableStyleChanged(object sender, EventArgs args)2342 		void TableStyleChanged (object sender, EventArgs args)
2343 		{
2344 			EndEdit ();
2345 			CalcAreasAndInvalidate ();
2346 		}
2347 
2348 
EnsureCellVisibility(DataGridCell cell)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 
SetDataSource(object source, string member)2380 		private void SetDataSource (object source, string member)
2381 		{
2382 			SetDataSource (source, member, true);
2383 		}
2384 
2385 		bool in_setdatasource;
SetDataSource(object source, string member, bool recreate_rows)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 
RecreateDataGridRows(bool recalc)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 
UpdateRowsFrom(DataGridRelationshipRow row)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 
BindColumns()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 
OnListManagerMetaDataChanged(object sender, EventArgs e)2513 		private void OnListManagerMetaDataChanged (object sender, EventArgs e)
2514 		{
2515 			BindColumns ();
2516 			CalcAreasAndInvalidate ();
2517 		}
2518 
OnListManagerPositionChanged(object sender, EventArgs e)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 
OnListManagerItemChanged(object sender, ItemChangedEventArgs e)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 
OnTableStylesCollectionChanged(object sender, CollectionChangeEventArgs e)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 
AddNewRow()2591 		private void AddNewRow ()
2592 		{
2593 			ListManager.EndCurrentEdit ();
2594 			ListManager.AddNew ();
2595 		}
2596 
Edit()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 
EndEdit()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 
ShiftSelection(int index)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 
ScrollToColumnInPixels(int pixel)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 
ScrollToRow(int old_row, int new_row)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 
ColumnResize(int column)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 
RowResize(int row)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
CalcAllColumnsWidth()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
FromPixelToColumn(int pixel, out int column_x)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 
GetColumnStartingPixel(int my_col)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
GetFirstColumnForColumnVisibility(int current_first_visible_column, int column)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;
CalcGridAreas()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 
CalcCaption()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 
CalcCellsArea()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 
CalcColumnHeaders()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 
CalcParentRows()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 
CalcParentButtons()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 
CalcRowHeaders()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 
GetVisibleRowCount(int visibleHeight)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 
UpdateVisibleColumn()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 
UpdateVisibleRowCount()3232 		void UpdateVisibleRowCount ()
3233 		{
3234 			visible_row_count = GetVisibleRowCount (cells_area.Height);
3235 
3236 			CalcRowHeaders (); // Height depends on num of visible rows
3237 		}
3238 
InvalidateCaption()3239 		void InvalidateCaption ()
3240 		{
3241 			if (caption_area.IsEmpty)
3242 				return;
3243 
3244 			Invalidate (caption_area);
3245 		}
3246 
InvalidateRow(int row)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 
InvalidateRowHeader(int row)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 
InvalidateColumn(DataGridColumnStyle column)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 
DrawResizeLineVert(int x)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 
DrawResizeLineHoriz(int y)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 
SetUpHorizontalScrollBar(out int maximum)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 
SetUpVerticalScrollBar(out int height, out int maximum)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 
OnUIACollectionChangedEvent(CollectionChangeEventArgs args)3428 		internal void OnUIACollectionChangedEvent (CollectionChangeEventArgs args)
3429 		{
3430 			CollectionChangeEventHandler eh
3431 				= (CollectionChangeEventHandler) Events [UIACollectionChangedEvent];
3432 			if (eh != null)
3433 				eh (this, args);
3434 		}
3435 
OnUIASelectionChangedEvent(CollectionChangeEventArgs args)3436 		internal void OnUIASelectionChangedEvent (CollectionChangeEventArgs args)
3437 		{
3438 			CollectionChangeEventHandler eh
3439 				= (CollectionChangeEventHandler) Events [UIASelectionChangedEvent];
3440 			if (eh != null)
3441 				eh (this, args);
3442 		}
3443 
OnUIAColumnHeadersVisibleChanged()3444 		internal void OnUIAColumnHeadersVisibleChanged ()
3445 		{
3446 			EventHandler eh = (EventHandler) Events [UIAColumnHeadersVisibleChangedEvent];
3447 			if (eh != null)
3448 				eh (this, EventArgs.Empty);
3449 		}
3450 
OnUIAGridCellChanged(CollectionChangeEventArgs args)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 }
3463