PageRenderTime 38ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/mcs/class/Managed.Windows.Forms/System.Windows.Forms/DataGrid.cs

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