PageRenderTime 67ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 1ms

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

https://bitbucket.org/danipen/mono
C# | 6146 lines | 4896 code | 1034 blank | 216 comment | 1208 complexity | 82fcde204b50bdb8de5297c923a606eb 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

Large files files are truncated, but you can click here to view the full file

  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) 2004-2005 Novell, Inc. (http://www.novell.com)
  21. //
  22. // Authors:
  23. // Ravindra Kumar (rkumar@novell.com)
  24. // Jordi Mas i Hernandez, jordi@ximian.com
  25. // Mike Kestner (mkestner@novell.com)
  26. // Daniel Nauck (dna(at)mono-project(dot)de)
  27. // Carlos Alberto Cortez <calberto.cortez@gmail.com>
  28. //
  29. // NOT COMPLETE
  30. using System.Collections;
  31. using System.ComponentModel;
  32. using System.ComponentModel.Design;
  33. using System.Drawing;
  34. using System.Runtime.InteropServices;
  35. using System.Globalization;
  36. using System.Collections.Generic;
  37. namespace System.Windows.Forms
  38. {
  39. [DefaultEvent ("SelectedIndexChanged")]
  40. [DefaultProperty ("Items")]
  41. [Designer ("System.Windows.Forms.Design.ListViewDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
  42. [ClassInterface (ClassInterfaceType.AutoDispatch)]
  43. [ComVisible (true)]
  44. [Docking (DockingBehavior.Ask)]
  45. public class ListView : Control
  46. {
  47. private ItemActivation activation = ItemActivation.Standard;
  48. private ListViewAlignment alignment = ListViewAlignment.Top;
  49. private bool allow_column_reorder;
  50. private bool auto_arrange = true;
  51. private bool check_boxes;
  52. private readonly CheckedIndexCollection checked_indices;
  53. private readonly CheckedListViewItemCollection checked_items;
  54. private readonly ColumnHeaderCollection columns;
  55. internal int focused_item_index = -1;
  56. private bool full_row_select;
  57. private bool grid_lines;
  58. private ColumnHeaderStyle header_style = ColumnHeaderStyle.Clickable;
  59. private bool hide_selection = true;
  60. private bool hover_selection;
  61. private IComparer item_sorter;
  62. private readonly ListViewItemCollection items;
  63. private readonly ListViewGroupCollection groups;
  64. private bool owner_draw;
  65. private bool show_groups = true;
  66. private bool label_edit;
  67. private bool label_wrap = true;
  68. private bool multiselect = true;
  69. private bool scrollable = true;
  70. private bool hover_pending;
  71. private readonly SelectedIndexCollection selected_indices;
  72. private readonly SelectedListViewItemCollection selected_items;
  73. private SortOrder sort_order = SortOrder.None;
  74. private ImageList state_image_list;
  75. internal bool updating;
  76. private View view = View.LargeIcon;
  77. private int layout_wd; // We might draw more than our client area
  78. private int layout_ht; // therefore we need to have these two.
  79. internal HeaderControl header_control;
  80. internal ItemControl item_control;
  81. internal ScrollBar h_scroll; // used for scrolling horizontally
  82. internal ScrollBar v_scroll; // used for scrolling vertically
  83. internal int h_marker; // Position markers for scrolling
  84. internal int v_marker;
  85. private int keysearch_tickcnt;
  86. private string keysearch_text;
  87. static private readonly int keysearch_keydelay = 1000;
  88. private int[] reordered_column_indices;
  89. private int[] reordered_items_indices;
  90. private Point [] items_location;
  91. private ItemMatrixLocation [] items_matrix_location;
  92. private Size item_size; // used for caching item size
  93. private int custom_column_width; // used when using Columns with SmallIcon/List views
  94. private int hot_item_index = -1;
  95. private bool hot_tracking;
  96. private ListViewInsertionMark insertion_mark;
  97. private bool show_item_tooltips;
  98. private ToolTip item_tooltip;
  99. private Size tile_size;
  100. private bool virtual_mode;
  101. private int virtual_list_size;
  102. private bool right_to_left_layout;
  103. // selection is available after the first time the handle is created, *even* if later
  104. // the handle is either recreated or destroyed - so keep this info around.
  105. private bool is_selection_available;
  106. // internal variables
  107. internal ImageList large_image_list;
  108. internal ImageList small_image_list;
  109. internal Size text_size = Size.Empty;
  110. #region Events
  111. static object AfterLabelEditEvent = new object ();
  112. static object BeforeLabelEditEvent = new object ();
  113. static object ColumnClickEvent = new object ();
  114. static object ItemActivateEvent = new object ();
  115. static object ItemCheckEvent = new object ();
  116. static object ItemDragEvent = new object ();
  117. static object SelectedIndexChangedEvent = new object ();
  118. static object DrawColumnHeaderEvent = new object();
  119. static object DrawItemEvent = new object();
  120. static object DrawSubItemEvent = new object();
  121. static object ItemCheckedEvent = new object ();
  122. static object ItemMouseHoverEvent = new object ();
  123. static object ItemSelectionChangedEvent = new object ();
  124. static object CacheVirtualItemsEvent = new object ();
  125. static object RetrieveVirtualItemEvent = new object ();
  126. static object RightToLeftLayoutChangedEvent = new object ();
  127. static object SearchForVirtualItemEvent = new object ();
  128. static object VirtualItemsSelectionRangeChangedEvent = new object ();
  129. public event LabelEditEventHandler AfterLabelEdit {
  130. add { Events.AddHandler (AfterLabelEditEvent, value); }
  131. remove { Events.RemoveHandler (AfterLabelEditEvent, value); }
  132. }
  133. [Browsable (false)]
  134. [EditorBrowsable (EditorBrowsableState.Never)]
  135. public new event EventHandler BackgroundImageLayoutChanged {
  136. add { base.BackgroundImageLayoutChanged += value; }
  137. remove { base.BackgroundImageLayoutChanged -= value; }
  138. }
  139. public event LabelEditEventHandler BeforeLabelEdit {
  140. add { Events.AddHandler (BeforeLabelEditEvent, value); }
  141. remove { Events.RemoveHandler (BeforeLabelEditEvent, value); }
  142. }
  143. public event ColumnClickEventHandler ColumnClick {
  144. add { Events.AddHandler (ColumnClickEvent, value); }
  145. remove { Events.RemoveHandler (ColumnClickEvent, value); }
  146. }
  147. public event DrawListViewColumnHeaderEventHandler DrawColumnHeader {
  148. add { Events.AddHandler(DrawColumnHeaderEvent, value); }
  149. remove { Events.RemoveHandler(DrawColumnHeaderEvent, value); }
  150. }
  151. public event DrawListViewItemEventHandler DrawItem {
  152. add { Events.AddHandler(DrawItemEvent, value); }
  153. remove { Events.RemoveHandler(DrawItemEvent, value); }
  154. }
  155. public event DrawListViewSubItemEventHandler DrawSubItem {
  156. add { Events.AddHandler(DrawSubItemEvent, value); }
  157. remove { Events.RemoveHandler(DrawSubItemEvent, value); }
  158. }
  159. public event EventHandler ItemActivate {
  160. add { Events.AddHandler (ItemActivateEvent, value); }
  161. remove { Events.RemoveHandler (ItemActivateEvent, value); }
  162. }
  163. public event ItemCheckEventHandler ItemCheck {
  164. add { Events.AddHandler (ItemCheckEvent, value); }
  165. remove { Events.RemoveHandler (ItemCheckEvent, value); }
  166. }
  167. public event ItemCheckedEventHandler ItemChecked {
  168. add { Events.AddHandler (ItemCheckedEvent, value); }
  169. remove { Events.RemoveHandler (ItemCheckedEvent, value); }
  170. }
  171. public event ItemDragEventHandler ItemDrag {
  172. add { Events.AddHandler (ItemDragEvent, value); }
  173. remove { Events.RemoveHandler (ItemDragEvent, value); }
  174. }
  175. public event ListViewItemMouseHoverEventHandler ItemMouseHover {
  176. add { Events.AddHandler (ItemMouseHoverEvent, value); }
  177. remove { Events.RemoveHandler (ItemMouseHoverEvent, value); }
  178. }
  179. public event ListViewItemSelectionChangedEventHandler ItemSelectionChanged {
  180. add { Events.AddHandler (ItemSelectionChangedEvent, value); }
  181. remove { Events.RemoveHandler (ItemSelectionChangedEvent, value); }
  182. }
  183. [Browsable (false)]
  184. [EditorBrowsable (EditorBrowsableState.Never)]
  185. public new event EventHandler PaddingChanged {
  186. add { base.PaddingChanged += value; }
  187. remove { base.PaddingChanged -= value; }
  188. }
  189. [Browsable (false)]
  190. [EditorBrowsable (EditorBrowsableState.Never)]
  191. public new event PaintEventHandler Paint {
  192. add { base.Paint += value; }
  193. remove { base.Paint -= value; }
  194. }
  195. public event EventHandler SelectedIndexChanged {
  196. add { Events.AddHandler (SelectedIndexChangedEvent, value); }
  197. remove { Events.RemoveHandler (SelectedIndexChangedEvent, value); }
  198. }
  199. [Browsable (false)]
  200. [EditorBrowsable (EditorBrowsableState.Never)]
  201. public new event EventHandler TextChanged {
  202. add { base.TextChanged += value; }
  203. remove { base.TextChanged -= value; }
  204. }
  205. public event CacheVirtualItemsEventHandler CacheVirtualItems {
  206. add { Events.AddHandler (CacheVirtualItemsEvent, value); }
  207. remove { Events.RemoveHandler (CacheVirtualItemsEvent, value); }
  208. }
  209. public event RetrieveVirtualItemEventHandler RetrieveVirtualItem {
  210. add { Events.AddHandler (RetrieveVirtualItemEvent, value); }
  211. remove { Events.RemoveHandler (RetrieveVirtualItemEvent, value); }
  212. }
  213. public event EventHandler RightToLeftLayoutChanged {
  214. add { Events.AddHandler (RightToLeftLayoutChangedEvent, value); }
  215. remove { Events.RemoveHandler (RightToLeftLayoutChangedEvent, value); }
  216. }
  217. public event SearchForVirtualItemEventHandler SearchForVirtualItem {
  218. add { Events.AddHandler (SearchForVirtualItemEvent, value); }
  219. remove { Events.AddHandler (SearchForVirtualItemEvent, value); }
  220. }
  221. public event ListViewVirtualItemsSelectionRangeChangedEventHandler VirtualItemsSelectionRangeChanged {
  222. add { Events.AddHandler (VirtualItemsSelectionRangeChangedEvent, value); }
  223. remove { Events.RemoveHandler (VirtualItemsSelectionRangeChangedEvent, value); }
  224. }
  225. #endregion // Events
  226. #region Public Constructors
  227. public ListView ()
  228. {
  229. background_color = ThemeEngine.Current.ColorWindow;
  230. groups = new ListViewGroupCollection (this);
  231. items = new ListViewItemCollection (this);
  232. items.Changed += new CollectionChangedHandler (OnItemsChanged);
  233. checked_indices = new CheckedIndexCollection (this);
  234. checked_items = new CheckedListViewItemCollection (this);
  235. columns = new ColumnHeaderCollection (this);
  236. foreground_color = SystemColors.WindowText;
  237. selected_indices = new SelectedIndexCollection (this);
  238. selected_items = new SelectedListViewItemCollection (this);
  239. items_location = new Point [16];
  240. items_matrix_location = new ItemMatrixLocation [16];
  241. reordered_items_indices = new int [16];
  242. item_tooltip = new ToolTip ();
  243. item_tooltip.Active = false;
  244. insertion_mark = new ListViewInsertionMark (this);
  245. InternalBorderStyle = BorderStyle.Fixed3D;
  246. header_control = new HeaderControl (this);
  247. header_control.Visible = false;
  248. Controls.AddImplicit (header_control);
  249. item_control = new ItemControl (this);
  250. Controls.AddImplicit (item_control);
  251. h_scroll = new ImplicitHScrollBar ();
  252. Controls.AddImplicit (this.h_scroll);
  253. v_scroll = new ImplicitVScrollBar ();
  254. Controls.AddImplicit (this.v_scroll);
  255. h_marker = v_marker = 0;
  256. keysearch_tickcnt = 0;
  257. // scroll bars are disabled initially
  258. h_scroll.Visible = false;
  259. h_scroll.ValueChanged += new EventHandler(HorizontalScroller);
  260. v_scroll.Visible = false;
  261. v_scroll.ValueChanged += new EventHandler(VerticalScroller);
  262. // event handlers
  263. base.KeyDown += new KeyEventHandler(ListView_KeyDown);
  264. SizeChanged += new EventHandler (ListView_SizeChanged);
  265. GotFocus += new EventHandler (FocusChanged);
  266. LostFocus += new EventHandler (FocusChanged);
  267. MouseWheel += new MouseEventHandler(ListView_MouseWheel);
  268. MouseEnter += new EventHandler (ListView_MouseEnter);
  269. Invalidated += new InvalidateEventHandler (ListView_Invalidated);
  270. BackgroundImageTiled = false;
  271. this.SetStyle (ControlStyles.UserPaint | ControlStyles.StandardClick
  272. | ControlStyles.UseTextForAccessibility
  273. , false);
  274. }
  275. #endregion // Public Constructors
  276. #region Private Internal Properties
  277. internal Size CheckBoxSize {
  278. get {
  279. if (this.check_boxes) {
  280. if (this.state_image_list != null)
  281. return this.state_image_list.ImageSize;
  282. else
  283. return ThemeEngine.Current.ListViewCheckBoxSize;
  284. }
  285. return Size.Empty;
  286. }
  287. }
  288. internal Size ItemSize {
  289. get {
  290. if (view != View.Details)
  291. return item_size;
  292. Size size = new Size ();
  293. size.Height = item_size.Height;
  294. for (int i = 0; i < columns.Count; i++)
  295. size.Width += columns [i].Wd;
  296. return size;
  297. }
  298. set {
  299. item_size = value;
  300. }
  301. }
  302. internal int HotItemIndex {
  303. get {
  304. return hot_item_index;
  305. }
  306. set {
  307. hot_item_index = value;
  308. }
  309. }
  310. internal bool UsingGroups {
  311. get {
  312. return show_groups && groups.Count > 0 && view != View.List &&
  313. Application.VisualStylesEnabled;
  314. }
  315. }
  316. internal override bool ScaleChildrenInternal {
  317. get { return false; }
  318. }
  319. internal bool UseCustomColumnWidth {
  320. get {
  321. return (view == View.List || view == View.SmallIcon) && columns.Count > 0;
  322. }
  323. }
  324. internal ColumnHeader EnteredColumnHeader {
  325. get {
  326. return header_control.EnteredColumnHeader;
  327. }
  328. }
  329. #endregion // Private Internal Properties
  330. #region Protected Properties
  331. protected override CreateParams CreateParams {
  332. get { return base.CreateParams; }
  333. }
  334. protected override Size DefaultSize {
  335. get { return ThemeEngine.Current.ListViewDefaultSize; }
  336. }
  337. protected override bool DoubleBuffered {
  338. get {
  339. return base.DoubleBuffered;
  340. }
  341. set {
  342. base.DoubleBuffered = value;
  343. }
  344. }
  345. #endregion // Protected Properties
  346. #region Public Instance Properties
  347. [DefaultValue (ItemActivation.Standard)]
  348. public ItemActivation Activation {
  349. get { return activation; }
  350. set {
  351. if (value != ItemActivation.Standard && value != ItemActivation.OneClick &&
  352. value != ItemActivation.TwoClick) {
  353. throw new InvalidEnumArgumentException (string.Format
  354. ("Enum argument value '{0}' is not valid for Activation", value));
  355. }
  356. if (hot_tracking && value != ItemActivation.OneClick)
  357. throw new ArgumentException ("When HotTracking is on, activation must be ItemActivation.OneClick");
  358. activation = value;
  359. }
  360. }
  361. [DefaultValue (ListViewAlignment.Top)]
  362. [Localizable (true)]
  363. public ListViewAlignment Alignment {
  364. get { return alignment; }
  365. set {
  366. if (value != ListViewAlignment.Default && value != ListViewAlignment.Left &&
  367. value != ListViewAlignment.SnapToGrid && value != ListViewAlignment.Top) {
  368. throw new InvalidEnumArgumentException (string.Format
  369. ("Enum argument value '{0}' is not valid for Alignment", value));
  370. }
  371. if (this.alignment != value) {
  372. alignment = value;
  373. // alignment does not matter in Details/List views
  374. if (this.view == View.LargeIcon || this.View == View.SmallIcon)
  375. this.Redraw (true);
  376. }
  377. }
  378. }
  379. [DefaultValue (false)]
  380. public bool AllowColumnReorder {
  381. get { return allow_column_reorder; }
  382. set { allow_column_reorder = value; }
  383. }
  384. [DefaultValue (true)]
  385. public bool AutoArrange {
  386. get { return auto_arrange; }
  387. set {
  388. if (auto_arrange != value) {
  389. auto_arrange = value;
  390. // autoarrange does not matter in Details/List views
  391. if (this.view == View.LargeIcon || this.View == View.SmallIcon)
  392. this.Redraw (true);
  393. }
  394. }
  395. }
  396. public override Color BackColor {
  397. get {
  398. if (background_color.IsEmpty)
  399. return ThemeEngine.Current.ColorWindow;
  400. else
  401. return background_color;
  402. }
  403. set {
  404. background_color = value;
  405. item_control.BackColor = value;
  406. }
  407. }
  408. [Browsable (false)]
  409. [EditorBrowsable (EditorBrowsableState.Never)]
  410. public override ImageLayout BackgroundImageLayout {
  411. get {
  412. return base.BackgroundImageLayout;
  413. }
  414. set {
  415. base.BackgroundImageLayout = value;
  416. }
  417. }
  418. [DefaultValue (false)]
  419. public bool BackgroundImageTiled {
  420. get {
  421. return item_control.BackgroundImageLayout == ImageLayout.Tile;
  422. }
  423. set {
  424. ImageLayout new_image_layout = value ? ImageLayout.Tile : ImageLayout.None;
  425. if (new_image_layout == item_control.BackgroundImageLayout)
  426. return;
  427. item_control.BackgroundImageLayout = new_image_layout;
  428. }
  429. }
  430. [DefaultValue (BorderStyle.Fixed3D)]
  431. [DispId (-504)]
  432. public BorderStyle BorderStyle {
  433. get { return InternalBorderStyle; }
  434. set { InternalBorderStyle = value; }
  435. }
  436. [DefaultValue (false)]
  437. public bool CheckBoxes {
  438. get { return check_boxes; }
  439. set {
  440. if (check_boxes != value) {
  441. if (value && View == View.Tile)
  442. throw new NotSupportedException ("CheckBoxes are not"
  443. + " supported in Tile view. Choose a different"
  444. + " view or set CheckBoxes to false.");
  445. check_boxes = value;
  446. this.Redraw (true);
  447. //UIA Framework: Event used by ListView to set/unset Toggle Pattern
  448. OnUIACheckBoxesChanged ();
  449. }
  450. }
  451. }
  452. [Browsable (false)]
  453. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  454. public CheckedIndexCollection CheckedIndices {
  455. get { return checked_indices; }
  456. }
  457. [Browsable (false)]
  458. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  459. public CheckedListViewItemCollection CheckedItems {
  460. get { return checked_items; }
  461. }
  462. [Editor ("System.Windows.Forms.Design.ColumnHeaderCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
  463. [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
  464. [Localizable (true)]
  465. [MergableProperty (false)]
  466. public ColumnHeaderCollection Columns {
  467. get { return columns; }
  468. }
  469. [Browsable (false)]
  470. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  471. public ListViewItem FocusedItem {
  472. get {
  473. if (focused_item_index == -1)
  474. return null;
  475. return GetItemAtDisplayIndex (focused_item_index);
  476. }
  477. set {
  478. if (value == null || value.ListView != this ||
  479. !IsHandleCreated)
  480. return;
  481. SetFocusedItem (value.DisplayIndex);
  482. }
  483. }
  484. public override Color ForeColor {
  485. get {
  486. if (foreground_color.IsEmpty)
  487. return ThemeEngine.Current.ColorWindowText;
  488. else
  489. return foreground_color;
  490. }
  491. set { foreground_color = value; }
  492. }
  493. [DefaultValue (false)]
  494. public bool FullRowSelect {
  495. get { return full_row_select; }
  496. set {
  497. if (full_row_select != value) {
  498. full_row_select = value;
  499. InvalidateSelection ();
  500. }
  501. }
  502. }
  503. [DefaultValue (false)]
  504. public bool GridLines {
  505. get { return grid_lines; }
  506. set {
  507. if (grid_lines != value) {
  508. grid_lines = value;
  509. this.Redraw (false);
  510. }
  511. }
  512. }
  513. [DefaultValue (ColumnHeaderStyle.Clickable)]
  514. public ColumnHeaderStyle HeaderStyle {
  515. get { return header_style; }
  516. set {
  517. if (header_style == value)
  518. return;
  519. switch (value) {
  520. case ColumnHeaderStyle.Clickable:
  521. case ColumnHeaderStyle.Nonclickable:
  522. case ColumnHeaderStyle.None:
  523. break;
  524. default:
  525. throw new InvalidEnumArgumentException (string.Format
  526. ("Enum argument value '{0}' is not valid for ColumnHeaderStyle", value));
  527. }
  528. header_style = value;
  529. if (view == View.Details)
  530. Redraw (true);
  531. }
  532. }
  533. [DefaultValue (true)]
  534. public bool HideSelection {
  535. get { return hide_selection; }
  536. set {
  537. if (hide_selection != value) {
  538. hide_selection = value;
  539. InvalidateSelection ();
  540. }
  541. }
  542. }
  543. [DefaultValue (false)]
  544. public bool HotTracking {
  545. get {
  546. return hot_tracking;
  547. }
  548. set {
  549. if (hot_tracking == value)
  550. return;
  551. hot_tracking = value;
  552. if (hot_tracking) {
  553. hover_selection = true;
  554. activation = ItemActivation.OneClick;
  555. }
  556. }
  557. }
  558. [DefaultValue (false)]
  559. public bool HoverSelection {
  560. get { return hover_selection; }
  561. set {
  562. if (hot_tracking && value == false)
  563. throw new ArgumentException ("When HotTracking is on, hover selection must be true");
  564. hover_selection = value;
  565. }
  566. }
  567. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  568. [Browsable (false)]
  569. public ListViewInsertionMark InsertionMark {
  570. get {
  571. return insertion_mark;
  572. }
  573. }
  574. [Editor ("System.Windows.Forms.Design.ListViewItemCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
  575. [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
  576. [Localizable (true)]
  577. [MergableProperty (false)]
  578. public ListViewItemCollection Items {
  579. get { return items; }
  580. }
  581. [DefaultValue (false)]
  582. public bool LabelEdit {
  583. get { return label_edit; }
  584. set {
  585. if (value != label_edit) {
  586. label_edit = value;
  587. // UIA Framework: Event used by Value Pattern in ListView.ListItem provider
  588. OnUIALabelEditChanged ();
  589. }
  590. }
  591. }
  592. [DefaultValue (true)]
  593. [Localizable (true)]
  594. public bool LabelWrap {
  595. get { return label_wrap; }
  596. set {
  597. if (label_wrap != value) {
  598. label_wrap = value;
  599. this.Redraw (true);
  600. }
  601. }
  602. }
  603. [DefaultValue (null)]
  604. public ImageList LargeImageList {
  605. get { return large_image_list; }
  606. set {
  607. large_image_list = value;
  608. this.Redraw (true);
  609. }
  610. }
  611. [Browsable (false)]
  612. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  613. public IComparer ListViewItemSorter {
  614. get {
  615. if (View != View.SmallIcon && View != View.LargeIcon && item_sorter is ItemComparer)
  616. return null;
  617. return item_sorter;
  618. }
  619. set {
  620. if (item_sorter != value) {
  621. item_sorter = value;
  622. Sort ();
  623. }
  624. }
  625. }
  626. [DefaultValue (true)]
  627. public bool MultiSelect {
  628. get { return multiselect; }
  629. set {
  630. if (value != multiselect) {
  631. multiselect = value;
  632. // UIA Framework: Event used by Selection Pattern in ListView.ListItem provider
  633. OnUIAMultiSelectChanged ();
  634. }
  635. }
  636. }
  637. [DefaultValue(false)]
  638. public bool OwnerDraw {
  639. get { return owner_draw; }
  640. set {
  641. owner_draw = value;
  642. Redraw (true);
  643. }
  644. }
  645. [Browsable (false)]
  646. [EditorBrowsable (EditorBrowsableState.Never)]
  647. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  648. public new Padding Padding {
  649. get {
  650. return base.Padding;
  651. }
  652. set {
  653. base.Padding = value;
  654. }
  655. }
  656. [MonoTODO ("RTL not supported")]
  657. [Localizable (true)]
  658. [DefaultValue (false)]
  659. public virtual bool RightToLeftLayout {
  660. get { return right_to_left_layout; }
  661. set {
  662. if (right_to_left_layout != value) {
  663. right_to_left_layout = value;
  664. OnRightToLeftLayoutChanged (EventArgs.Empty);
  665. }
  666. }
  667. }
  668. [DefaultValue (true)]
  669. public bool Scrollable {
  670. get { return scrollable; }
  671. set {
  672. if (scrollable != value) {
  673. scrollable = value;
  674. this.Redraw (true);
  675. }
  676. }
  677. }
  678. [Browsable (false)]
  679. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  680. public SelectedIndexCollection SelectedIndices {
  681. get { return selected_indices; }
  682. }
  683. [Browsable (false)]
  684. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  685. public SelectedListViewItemCollection SelectedItems {
  686. get { return selected_items; }
  687. }
  688. [DefaultValue(true)]
  689. public bool ShowGroups {
  690. get { return show_groups; }
  691. set {
  692. if (show_groups != value) {
  693. show_groups = value;
  694. Redraw(true);
  695. // UIA Framework: Used to update a11y Tree
  696. OnUIAShowGroupsChanged ();
  697. }
  698. }
  699. }
  700. [LocalizableAttribute (true)]
  701. [MergableProperty (false)]
  702. [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
  703. [Editor ("System.Windows.Forms.Design.ListViewGroupCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
  704. public ListViewGroupCollection Groups {
  705. get { return groups; }
  706. }
  707. [DefaultValue (false)]
  708. public bool ShowItemToolTips {
  709. get {
  710. return show_item_tooltips;
  711. }
  712. set {
  713. show_item_tooltips = value;
  714. item_tooltip.Active = false;
  715. }
  716. }
  717. [DefaultValue (null)]
  718. public ImageList SmallImageList {
  719. get { return small_image_list; }
  720. set {
  721. small_image_list = value;
  722. this.Redraw (true);
  723. }
  724. }
  725. [DefaultValue (SortOrder.None)]
  726. public SortOrder Sorting {
  727. get { return sort_order; }
  728. set {
  729. if (!Enum.IsDefined (typeof (SortOrder), value)) {
  730. throw new InvalidEnumArgumentException ("value", (int) value,
  731. typeof (SortOrder));
  732. }
  733. if (sort_order == value)
  734. return;
  735. sort_order = value;
  736. if (virtual_mode) // Sorting is not allowed in virtual mode
  737. return;
  738. if (value == SortOrder.None) {
  739. if (item_sorter != null) {
  740. // ListViewItemSorter should never be reset for SmallIcon
  741. // and LargeIcon view
  742. if (View != View.SmallIcon && View != View.LargeIcon)
  743. item_sorter = null;
  744. }
  745. this.Redraw (false);
  746. } else {
  747. if (item_sorter == null)
  748. item_sorter = new ItemComparer (value);
  749. if (item_sorter is ItemComparer) {
  750. item_sorter = new ItemComparer (value);
  751. }
  752. Sort ();
  753. }
  754. }
  755. }
  756. private void OnImageListChanged (object sender, EventArgs args)
  757. {
  758. item_control.Invalidate ();
  759. }
  760. [DefaultValue (null)]
  761. public ImageList StateImageList {
  762. get { return state_image_list; }
  763. set {
  764. if (state_image_list == value)
  765. return;
  766. if (state_image_list != null)
  767. state_image_list.Images.Changed -= new EventHandler (OnImageListChanged);
  768. state_image_list = value;
  769. if (state_image_list != null)
  770. state_image_list.Images.Changed += new EventHandler (OnImageListChanged);
  771. this.Redraw (true);
  772. }
  773. }
  774. [Bindable (false)]
  775. [Browsable (false)]
  776. [EditorBrowsable (EditorBrowsableState.Never)]
  777. public override string Text {
  778. get { return base.Text; }
  779. set {
  780. if (value == base.Text)
  781. return;
  782. base.Text = value;
  783. this.Redraw (true);
  784. }
  785. }
  786. [Browsable (true)]
  787. public Size TileSize {
  788. get {
  789. return tile_size;
  790. }
  791. set {
  792. if (value.Width <= 0 || value.Height <= 0)
  793. throw new ArgumentOutOfRangeException ("value");
  794. tile_size = value;
  795. if (view == View.Tile)
  796. Redraw (true);
  797. }
  798. }
  799. [Browsable (false)]
  800. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  801. public ListViewItem TopItem {
  802. get {
  803. if (view == View.LargeIcon || view == View.SmallIcon || view == View.Tile)
  804. throw new InvalidOperationException ("Cannot get the top item in LargeIcon, SmallIcon or Tile view.");
  805. // there is no item
  806. if (this.items.Count == 0)
  807. return null;
  808. // if contents are not scrolled
  809. // it is the first item
  810. else if (h_marker == 0 && v_marker == 0)
  811. return this.items [0];
  812. // do a hit test for the scrolled position
  813. else {
  814. int header_offset = header_control.Height;
  815. for (int i = 0; i < items.Count; i++) {
  816. Point item_loc = GetItemLocation (i);
  817. if (item_loc.X >= 0 && item_loc.Y - header_offset >= 0)
  818. return items [i];
  819. }
  820. return null;
  821. }
  822. }
  823. set {
  824. if (view == View.LargeIcon || view == View.SmallIcon || view == View.Tile)
  825. throw new InvalidOperationException ("Cannot set the top item in LargeIcon, SmallIcon or Tile view.");
  826. // .Net doesn't throw any exception in the cases below
  827. if (value == null || value.ListView != this)
  828. return;
  829. // Take advantage this property is only valid for Details view.
  830. SetScrollValue (v_scroll, item_size.Height * value.Index);
  831. }
  832. }
  833. [EditorBrowsable (EditorBrowsableState.Advanced)]
  834. [DefaultValue (true)]
  835. [Browsable (false)]
  836. [MonoInternalNote ("Stub, not implemented")]
  837. public bool UseCompatibleStateImageBehavior {
  838. get {
  839. return false;
  840. }
  841. set {
  842. }
  843. }
  844. [DefaultValue (View.LargeIcon)]
  845. public View View {
  846. get { return view; }
  847. set {
  848. if (!Enum.IsDefined (typeof (View), value))
  849. throw new InvalidEnumArgumentException ("value", (int) value,
  850. typeof (View));
  851. if (view != value) {
  852. if (CheckBoxes && value == View.Tile)
  853. throw new NotSupportedException ("CheckBoxes are not"
  854. + " supported in Tile view. Choose a different"
  855. + " view or set CheckBoxes to false.");
  856. if (VirtualMode && value == View.Tile)
  857. throw new NotSupportedException ("VirtualMode is"
  858. + " not supported in Tile view. Choose a different"
  859. + " view or set ViewMode to false.");
  860. h_scroll.Value = v_scroll.Value = 0;
  861. view = value;
  862. Redraw (true);
  863. // UIA Framework: Event used to update UIA Tree.
  864. OnUIAViewChanged ();
  865. }
  866. }
  867. }
  868. [DefaultValue (false)]
  869. [RefreshProperties (RefreshProperties.Repaint)]
  870. public bool VirtualMode {
  871. get {
  872. return virtual_mode;
  873. }
  874. set {
  875. if (virtual_mode == value)
  876. return;
  877. if (!virtual_mode && items.Count > 0)
  878. throw new InvalidOperationException ();
  879. if (value && view == View.Tile)
  880. throw new NotSupportedException ("VirtualMode is"
  881. + " not supported in Tile view. Choose a different"
  882. + " view or set ViewMode to false.");
  883. virtual_mode = value;
  884. Redraw (true);
  885. }
  886. }
  887. [DefaultValue (0)]
  888. [RefreshProperties (RefreshProperties.Repaint)]
  889. public int VirtualListSize {
  890. get {
  891. return virtual_list_size;
  892. }
  893. set {
  894. if (value < 0)
  895. throw new ArgumentException ("value");
  896. if (virtual_list_size == value)
  897. return;
  898. virtual_list_size = value;
  899. if (virtual_mode) {
  900. selected_indices.Reset ();
  901. Redraw (true);
  902. }
  903. }
  904. }
  905. #endregion // Public Instance Properties
  906. #region Internal Methods Properties
  907. internal int FirstVisibleIndex {
  908. get {
  909. // there is no item
  910. if (this.items.Count == 0)
  911. return 0;
  912. if (h_marker == 0 && v_marker == 0)
  913. return 0;
  914. Size item_size = ItemSize;
  915. // In virtual mode we always have fixed positions, and we can infer the positon easily
  916. if (virtual_mode) {
  917. int first = 0;
  918. switch (view) {
  919. case View.Details:
  920. first = v_marker / item_size.Height;
  921. break;
  922. case View.LargeIcon:
  923. case View.SmallIcon:
  924. first = (v_marker / (item_size.Height + y_spacing)) * cols;
  925. break;
  926. case View.List:
  927. first = (h_marker / (item_size.Width * x_spacing)) * rows;
  928. break;
  929. }
  930. if (first >= items.Count)
  931. first = items.Count;
  932. return first;
  933. }
  934. for (int i = 0; i < items.Count; i++) {
  935. Rectangle item_rect = new Rectangle (GetItemLocation (i), item_size);
  936. if (item_rect.Right >= 0 && item_rect.Bottom >= 0)
  937. return i;
  938. }
  939. return 0;
  940. }
  941. }
  942. internal int LastVisibleIndex {
  943. get {
  944. for (int i = FirstVisibleIndex; i < Items.Count; i++) {
  945. if (View == View.List || Alignment == ListViewAlignment.Left) {
  946. if (GetItemLocation (i).X > item_control.ClientRectangle.Right)
  947. return i - 1;
  948. } else {
  949. if (GetItemLocation (i).Y > item_control.ClientRectangle.Bottom)
  950. return i - 1;
  951. }
  952. }
  953. return Items.Count - 1;
  954. }
  955. }
  956. internal void OnSelectedIndexChanged ()
  957. {
  958. if (is_selection_available)
  959. OnSelectedIndexChanged (EventArgs.Empty);
  960. }
  961. internal int TotalWidth {
  962. get { return Math.Max (this.Width, this.layout_wd); }
  963. }
  964. internal int TotalHeight {
  965. get { return Math.Max (this.Height, this.layout_ht); }
  966. }
  967. internal void Redraw (bool recalculate)
  968. {
  969. // Avoid calculations when control is being updated
  970. if (updating)
  971. return;
  972. // VirtualMode doesn't do any calculations until handle is created
  973. if (virtual_mode && !IsHandleCreated)
  974. return;
  975. if (recalculate)
  976. CalculateListView (this.alignment);
  977. Invalidate (true);
  978. }
  979. void InvalidateSelection ()
  980. {
  981. foreach (int selected_index in SelectedIndices)
  982. items [selected_index].Invalidate ();
  983. }
  984. const int text_padding = 15;
  985. internal Size GetChildColumnSize (int index)
  986. {
  987. Size ret_size = Size.Empty;
  988. ColumnHeader col = this.columns [index];
  989. if (col.Width == -2) { // autosize = max(items, columnheader)
  990. Size size = Size.Ceiling (TextRenderer.MeasureString
  991. (col.Text, this.Font));
  992. size.Width += text_padding;
  993. ret_size = BiggestItem (index);
  994. if (size.Width > ret_size.Width)
  995. ret_size = size;
  996. }
  997. else { // -1 and all the values < -2 are put under one category
  998. ret_size = BiggestItem (index);
  999. // fall back to empty columns' width if no subitem is available for a column
  1000. if (ret_size.IsEmpty) {
  1001. ret_size.Width = ThemeEngine.Current.ListViewEmptyColumnWidth;
  1002. if (col.Text.Length > 0)
  1003. ret_size.Height = Size.Ceiling (TextRenderer.MeasureString
  1004. (col.Text, this.Font)).Height;
  1005. else
  1006. ret_size.Height = this.Font.Height;
  1007. }
  1008. }
  1009. ret_size.Height += text_padding;
  1010. // adjust the size for icon and checkbox for 0th column
  1011. if (index == 0) {
  1012. ret_size.Width += (this.CheckBoxSize.Width + 4);
  1013. if (this.small_image_list != null)
  1014. ret_size.Width += this.small_image_list.ImageSize.Width;
  1015. }
  1016. return ret_size;
  1017. }
  1018. // Returns the size of biggest item text in a column
  1019. // or the sum of the text and indent count if we are on 2.0
  1020. private Size BiggestItem (int col)
  1021. {
  1022. Size temp = Size.Empty;
  1023. Size ret_size = Size.Empty;
  1024. bool use_indent_count = small_image_list != null;
  1025. // VirtualMode uses the first item text size
  1026. if (virtual_mode && items.Count > 0) {
  1027. ListViewItem item = items [0];
  1028. ret_size = Size.Ceiling (TextRenderer.MeasureString (item.SubItems[col].Text,
  1029. Font));
  1030. if (use_indent_count)
  1031. ret_size.Width += item.IndentCount * small_image_list.ImageSize.Width;
  1032. } else {
  1033. // 0th column holds the item text, we check the size of
  1034. // the various subitems falling in that column and get
  1035. // the biggest one's size.
  1036. foreach (ListViewItem item in items) {
  1037. if (col >= item.SubItems.Count)
  1038. continue;
  1039. temp = Size.Ceiling (TextRenderer.MeasureString
  1040. (item.SubItems [col].Text, Font));
  1041. if (use_indent_count)
  1042. temp.Width += item.IndentCount * small_image_list.ImageSize.Width;
  1043. if (temp.Width > ret_size.Width)
  1044. ret_size = temp;
  1045. }
  1046. }
  1047. // adjustment for space in Details view
  1048. if (!ret_size.IsEmpty && view == View.Details)
  1049. ret_size.Width += ThemeEngine.Current.ListViewItemPaddingWidth;
  1050. return ret_size;
  1051. }
  1052. const int max_wrap_padding = 30;
  1053. // Sets the size of the biggest item text as per the view
  1054. private void CalcTextSize ()
  1055. {
  1056. // clear the old value
  1057. text_size = Size.Empty;
  1058. if (items.Count == 0)
  1059. return;
  1060. text_size = BiggestItem (0);
  1061. if (view == View.LargeIcon && this.label_wrap) {
  1062. Size temp = Size.Empty;
  1063. if (this.check_boxes)
  1064. temp.Width += 2 * this.CheckBoxSize.Width;
  1065. int icon_w = LargeImageList == null ? 12 : LargeImageList.ImageSize.Width;
  1066. temp.Width += icon_w + max_wrap_padding;
  1067. // wrapping is done for two lines only
  1068. if (text_size.Width > temp.Width) {
  1069. text_size.Width = temp.Width;
  1070. text_size.Height *= 2;
  1071. }
  1072. }
  1073. else if (view == View.List) {
  1074. // in list view max text shown in determined by the
  1075. // control width, even if scolling is enabled.
  1076. int max_wd = this.Width - (this.CheckBoxSize.Width - 2);
  1077. if (this.small_image_list != null)
  1078. max_wd -= this.small_image_list.ImageSize.Width;
  1079. if (text_size.Width > max_wd)
  1080. text_size.Width = max_wd;
  1081. }
  1082. // we do the default settings, if we have got 0's
  1083. if (text_size.Height <= 0)
  1084. text_size.Height = this.Font.Height;
  1085. if (text_size.Width <= 0)
  1086. text_size.Width = this.Width;
  1087. // little adjustment
  1088. text_size.Width += 2;
  1089. text_size.Height += 2;
  1090. }
  1091. private void SetScrollValue (ScrollBar scrollbar, int val)
  1092. {
  1093. int max;
  1094. if (scrollbar == h_scroll)
  1095. max = h_scroll.Maximum - h_scroll.LargeChange + 1;
  1096. else
  1097. max = v_scroll.Maximum - v_scroll.LargeChange + 1;
  1098. if (val > max)
  1099. val = max;
  1100. else if (val < scrollbar.Minimum)
  1101. val = scrollbar.Minimum;
  1102. scrollbar.Value = val;
  1103. }
  1104. private void Scroll (ScrollBar scrollbar, int delta)
  1105. {
  1106. if (delta == 0 || !scrollbar.Visible)
  1107. return;
  1108. SetScrollValue (scrollbar, scrollbar.Value + delta);
  1109. }
  1110. private void CalculateScrollBars ()
  1111. {
  1112. Rectangle client_area = ClientRectangle;
  1113. int height = client_area.Height;
  1114. int width = client_area.Width;
  1115. Size item_size;
  1116. if (!scrollable) {
  1117. h_scroll.Visible = false;
  1118. v_scroll.Visible = false;
  1119. item_control.Size = new Size (width, height);
  1120. header_control.Width = width;
  1121. return;
  1122. }
  1123. // Don't calculate if the view is not displayable
  1124. if (client_area.Height < 0 || client_area.Width < 0)
  1125. return;
  1126. // making a scroll bar visible might make
  1127. // other scroll bar visible
  1128. if (layout_wd > client_area.Right) {
  1129. h_scroll.Visible = true;
  1130. if ((layout_ht + h_scroll.Height) > client_area.Bottom)
  1131. v_scroll.Visible = true;
  1132. else
  1133. v_scroll.Visible = false;
  1134. } else if (layout_ht > client_area.Bottom) {
  1135. v_scroll.Visible = true;
  1136. if ((layout_wd + v_scroll.Width) > client_area.Right)
  1137. h_scroll.Visible = true;
  1138. else
  1139. h_scroll.Visible = false;
  1140. } else {
  1141. h_scroll.Visible = false;
  1142. v_scroll.Visible = false;
  1143. }
  1144. item_size = ItemSize;
  1145. if (h_scroll.is_visible) {
  1146. h_scroll.Location = new Point (client_area.X, client_area.Bottom - h_scroll.Height);
  1147. h_scroll.Minimum = 0;
  1148. // if v_scroll is visible, adjust the maximum of the
  1149. // h_scroll to account for the width of v_scroll
  1150. if (v_scroll.Visible) {
  1151. h_scroll.Maximum = layout_wd + v_scroll.Width;
  1152. h_scroll.Width = client_area.Width - v_scroll.Width;
  1153. }
  1154. else {
  1155. h_scroll.Maximum = layout_wd;
  1156. h_scroll.Width = client_area.Width;
  1157. }
  1158. if (view == View.List)
  1159. h_scroll.SmallChange = item_size.Width + ThemeEngine.Current.ListViewHorizontalSpacing;
  1160. else
  1161. h_scroll.SmallChange = Font.Height;
  1162. h_scroll.LargeChange = client_area.Width;
  1163. height -= h_scroll.Height;
  1164. }
  1165. if (v_scroll.is_visible) {
  1166. v_scroll.Location = new Point (client_area.Right - v_scroll.Width, client_area.Y);
  1167. v_scroll.Minimum = 0;
  1168. // if h_scroll is visible, adjust the height of
  1169. // v_scroll to account for the height of h_scroll
  1170. if (h_scroll.Visible) {
  1171. v_scroll.Maximum = layout_ht + h_scroll.Height;
  1172. v_scroll.Height = client_area.Height > h_scroll.Height ? client_area.Height - h_scroll.Height : 0;
  1173. } else {
  1174. v_scroll.Maximum = layout_ht;
  1175. v_scroll.Height = client_area.Height;
  1176. }
  1177. if (view == View.Details) {
  1178. // Need to update Maximum if using LargeChange with value other than the visible area
  1179. int headerPlusOneItem = header_control.Height + item_size.Height;
  1180. v_scroll.LargeChange = v_scroll.Height > headerPlusOneItem ? v_scroll.Height - headerPlusOneItem : 0;
  1181. v_scroll.Maximum = v_scroll.Maximum > headerPlusOneItem ? v_scroll.Maximum - headerPlusOneItem : 0;
  1182. } else
  1183. v_scroll.LargeChange = v_scroll.Height;
  1184. v_scroll.SmallChange = item_size.Height;
  1185. width -= v_scroll.Width;
  1186. }
  1187. item_control.Size = new Size (width, height);
  1188. if (header_control.is_visible)
  1189. header_control.Width = width;
  1190. }
  1191. internal int GetReorderedColumnIndex (ColumnHeader column)
  1192. {
  1193. if (reordered_column_indices == null)
  1194. return column.Index;
  1195. for (int i = 0; i < Columns.Count; i++)
  1196. if (reordered_column_indices [i] == column.Index)
  1197. return i;
  1198. return -1;
  1199. }
  1200. internal ColumnHeader GetReorderedColumn (int index)
  1201. {
  1202. if (reordered_column_indices == null)
  1203. return Columns [index];
  1204. else
  1205. return Columns [reordered_column_indices [index]];
  1206. }
  1207. internal void ReorderColumn (ColumnHeader col, int index, bool fireEvent)
  1208. {
  1209. if (fireEvent) {
  1210. ColumnReorderedEventHandler eh = (ColumnReorderedEventHandler) (Events [ColumnReorderedEvent]);
  1211. if (eh != null){
  1212. ColumnReorderedEventArgs args = new ColumnReorderedEventArgs (col.Index, index, col);
  1213. eh (this, args);
  1214. if (args.Cancel) {
  1215. header_control.Invalidate ();
  1216. item_control.Invalidate ();
  1217. return;
  1218. }
  1219. }
  1220. }
  1221. int column_count = Columns.Count;
  1222. if (reordered_column_indices == null) {
  1223. reordered_column_indices = new int [column_count];
  1224. for (int i = 0; i < column_count; i++)
  1225. reordered_column_indices [i] = i;
  1226. }
  1227. if (reordered_column_indices [index] == col.Index)
  1228. return;
  1229. int[] curr = reordered_column_indices;
  1230. int [] result = new int [column_count];
  1231. int curr_idx = 0;
  1232. for (int i = 0; i < column_count; i++) {
  1233. if (curr_idx < column_count && curr [curr_idx] == col.Index)
  1234. curr_idx++;
  1235. if (i == index)
  1236. result [i] = col.Index;
  1237. else
  1238. result [i] = curr [curr_idx++];
  1239. }
  1240. ReorderColumns (result, true);
  1241. }
  1242. internal void ReorderColumns (int [] display_indices, bool redraw)
  1243. {
  1244. reordered_column_indices = display_indices;
  1245. for (int i = 0; i < Columns.Count; i++) {
  1246. ColumnHeader col = Columns [i];
  1247. col.InternalDisplayIndex = reordered_column_indices [i];
  1248. }
  1249. if (redraw && view == View.Details && IsHandleCreated) {
  1250. LayoutDetails ();
  1251. header_control.Invalidate ();
  1252. item_control.Invalidate ();
  1253. }
  1254. }
  1255. internal void AddColumn (ColumnHeader newCol, int index, bool redraw)
  1256. {
  1257. int column_count = Columns.Count;
  1258. newCol.SetListView (this);
  1259. int [] display_indices = new int [column_count];
  1260. for (int i = 0; i < column_count; i++) {
  1261. ColumnHeader col = Columns [i];
  1262. if (i == index) {
  1263. display_indices [i] = index;
  1264. } else {
  1265. int display_index = col.InternalDisplayIndex;
  1266. if (display_index < index) {
  1267. display_indices [i] = display_index;
  1268. } else {
  1269. display_indices [i] = (display_index + 1);
  1270. }
  1271. }
  1272. }
  1273. ReorderColumns (display_indices, redraw);
  1274. Invalidate ();
  1275. }
  1276. Size LargeIconItemSize
  1277. {
  1278. get {
  1279. int image_w = LargeImageList == null ? 12 : LargeImageList.ImageSize.Width;
  1280. int image_h = LargeImageList == null ? 2 : LargeImageList.ImageSize.Height;
  1281. int h = text_size.Height + 2 + Math.Max (CheckBoxSize.Height, image_h);
  1282. int w = Math.Max (text_size.Width, image_w);
  1283. if (check_boxes)
  1284. w += 2 + CheckBoxSize.Width;
  1285. return new Size (w, h);
  1286. }
  1287. }
  1288. Size SmallIconItemSize {
  1289. get {
  1290. int image_w = SmallImageList == null ? 0 : SmallImageList.ImageSize.Width;
  1291. int image_h = SmallImageList == null ? 0 : SmallImageList.ImageSize.Height;
  1292. int h = Math.Max (text_size.Height, Math.Max (CheckBoxSize.Height, image_h));
  1293. int w = text_size.Width + image_w;
  1294. if (check_boxes)
  1295. w += 2 + CheckBoxSize.Width;
  1296. return new Size (w, h);
  1297. }
  1298. }
  1299. Size TileItemSize {
  1300. get {
  1301. // Calculate tile size if needed
  1302. // It appears that using Font.Size instead of a SizeF value can give us
  1303. // a slightly better approach to the proportions defined in .Net
  1304. if (tile_size == Size.Empty) {
  1305. int image_w = LargeImageList == null ? 0 : LargeImageList.ImageSize.Width;
  1306. int image_h = LargeImageList == null ? 0 : LargeImageList.ImageSize.Height;
  1307. int w = (int)Font.Size * ThemeEngine.Current.ListViewTileWidthFactor + image_w + 4;
  1308. int h = Math.Max ((int)Font.Size * ThemeEngine.Current.ListViewTileHeightFactor, image_h);
  1309. tile_size = new Size (w, h);
  1310. }
  1311. return tile_size;
  1312. }
  1313. }
  1314. int GetDetailsItemHeight ()
  1315. {
  1316. int item_height;
  1317. int checkbox_height = CheckBoxes ? CheckBoxSize.Height : 0;
  1318. int small_image_height = SmallImageList == null ? 0 : SmallImageList.ImageSize.Height;
  1319. item_height = Math.Max (checkbox_height, text_size.Height);
  1320. item_height = Math.Max (item_height, small_image_height);
  1321. return item_height;
  1322. }
  1323. void SetItemLocation (int index, int x, int y, int row, int col)
  1324. {
  1325. Point old_location = items_location [index];
  1326. if (old_location.X == x && old_location.Y == y)
  1327. return;
  1328. items_location [index] = new Point (x, y);
  1329. items_matrix_location [index] = new ItemMatrixLocation (row, col);
  1330. //
  1331. // Initial position matches item's position in ListViewItemCollection
  1332. //
  1333. reordered_items_indices [index] = index;
  1334. }
  1335. void ShiftItemsPositions (int from, int to, bool forward)
  1336. {
  1337. if (forward) {
  1338. for (int i = to + 1; i > from; i--) {
  1339. reordered_items_indices [i] = reordered_items_indices [i - 1];
  1340. ListViewItem item = items [reordered_items_indices [i]];
  1341. item.Invalidate ();
  1342. item.DisplayIndex = i;
  1343. item.Invalidate ();
  1344. }
  1345. } else {
  1346. for (int i = from - 1; i < to; i++) {
  1347. reordered_items_indices [i] = reordered_items_indices [i + 1];
  1348. ListViewItem item = items [reordered_items_indices [i]];
  1349. item.Invalidate ();
  1350. item.DisplayIndex = i;
  1351. item.Invalidate ();
  1352. }
  1353. }
  1354. }
  1355. internal void ChangeItemLocation (int display_index, Point new_pos)
  1356. {
  1357. int new_display_index = GetDisplayIndexFromLocation (new_pos);
  1358. if (new_display_index == display_index)
  1359. return;
  1360. int item_index = reordered_items_indices [display_index];
  1361. ListViewItem item = items [item_index];
  1362. bool forward = new_display_index < display_index;
  1363. int index_from, index_to;
  1364. if (forward) {
  1365. index_from = new_display_index;
  1366. index_to = display_index - 1;
  1367. } else {
  1368. index_from = display_index + 1;
  1369. index_to = new_display_index;
  1370. }
  1371. ShiftItemsPositions (index_from, index_to, forward);
  1372. reordered_items_indices [new_display_index] = item_index;
  1373. item.Invalidate ();
  1374. item.DisplayIndex = new_display_index;
  1375. item.Invalidate ();
  1376. }
  1377. int GetDisplayIndexFromLocation (Point loc)
  1378. {
  1379. int display_index = -1;
  1380. Rectangle item_area;
  1381. // First item
  1382. if (loc.X < 0 || loc.Y < 0)
  1383. return 0;
  1384. // Adjustment to put in the next position refered by 'loc'
  1385. loc.X -= item_size.Width / 2;
  1386. if (loc.X < 0)
  1387. loc.X = 0;
  1388. for (int i = 0; i < items.Count; i++) {
  1389. item_area = new Rectangle (GetItemLocation (i), item_size);
  1390. item_area.Inflate (ThemeEngine.Current.ListViewHorizontalSpacing,
  1391. ThemeEngine.Current.ListViewVerticalSpacing);
  1392. if (item_area.Contains (loc)) {
  1393. display_index = i;
  1394. break;
  1395. }
  1396. }
  1397. // Put in in last position
  1398. if (display_index == -1)
  1399. display_index = items.Count - 1;
  1400. return display_index;
  1401. }
  1402. // When using groups, the items with no group assigned
  1403. // belong to the DefaultGroup
  1404. int GetDefaultGroupItems ()
  1405. {
  1406. int count = 0;
  1407. foreach (ListViewItem item in items)
  1408. if (item.Group == null)
  1409. count++;
  1410. return count;
  1411. }
  1412. // cache the spacing to let virtualmode compute the positions on the fly
  1413. int x_spacing;
  1414. int y_spacing;
  1415. int rows;
  1416. int cols;
  1417. int[,] item_index_matrix;
  1418. void CalculateRowsAndCols (Size item_size, bool left_aligned, int x_spacing, int y_spacing)
  1419. {
  1420. Rectangle area = ClientRectangle;
  1421. if (UseCustomColumnWidth)
  1422. CalculateCustomColumnWidth ();
  1423. if (UsingGroups) {
  1424. // When groups are used the alignment is always top-aligned
  1425. rows = 0;
  1426. cols = 0;
  1427. int items = 0;
  1428. groups.DefaultGroup.ItemCount = GetDefaultGroupItems ();
  1429. for (int i = 0; i < groups.InternalCount; i++) {
  1430. ListViewGroup group = groups.GetInternalGroup (i);
  1431. int items_in_group = group.GetActualItemCount ();
  1432. if (items_in_group == 0)
  1433. continue;
  1434. int group_cols = (int) Math.Floor ((double)(area.Width - v_scroll.Width + x_spacing) / (double)(item_size.Width + x_spacing));
  1435. if (group_cols <= 0)
  1436. group_cols = 1;
  1437. int group_rows = (int) Math.Ceiling ((double)items_in_group / (double)group_cols);
  1438. group.starting_row = rows;
  1439. group.rows = group_rows;
  1440. group.starting_item = items;
  1441. group.current_item = 0; // Reset layout
  1442. cols = Math.Max (group_cols, cols);
  1443. rows += group_rows;
  1444. items += items_in_group;
  1445. }
  1446. } else
  1447. {
  1448. // Simple matrix if no groups are used
  1449. if (left_aligned) {
  1450. rows = (int) Math.Floor ((double)(area.Height - h_scroll.Height + y_spacing) / (double)(item_size.Height + y_spacing));
  1451. if (rows <= 0)
  1452. rows = 1;
  1453. cols = (int) Math.Ceiling ((double)items.Count / (double)rows);
  1454. } else {
  1455. if (UseCustomColumnWidth)
  1456. cols = (int) Math.Floor ((double)(area.Width - v_scroll.Width) / (double)(custom_column_width));
  1457. else
  1458. cols = (int) Math.Floor ((double)(area.Width - v_scroll.Width + x_spacing) / (double)(item_size.Width + x_spacing));
  1459. if (cols < 1)
  1460. cols = 1;
  1461. rows = (int) Math.Ceiling ((double)items.Count / (double)cols);
  1462. }
  1463. }
  1464. item_index_matrix = new int [rows, cols];
  1465. }
  1466. // When using custom column width, we look for the minimum one
  1467. void CalculateCustomColumnWidth ()
  1468. {
  1469. int min_width = Int32.MaxValue;
  1470. for (int i = 0; i < columns.Count; i++) {
  1471. int col_width = columns [i].Width;
  1472. if (col_width < min_width)
  1473. min_width = col_width;
  1474. }
  1475. custom_column_width = min_width;
  1476. }
  1477. void LayoutIcons (Size item_size, bool left_aligned, int x_spacing, int y_spacing)
  1478. {
  1479. header_control.Visible = false;
  1480. header_control.Size = Size.Empty;
  1481. item_control.Visible = true;
  1482. item_control.Location = Point.Empty;
  1483. ItemSize = item_size; // Cache item size
  1484. this.x_spacing = x_spacing;
  1485. this.y_spacing = y_spacing;
  1486. if (items.Count == 0)
  1487. return;
  1488. Size sz = item_size;
  1489. CalculateRowsAndCols (sz, left_aligned, x_spacing, y_spacing);
  1490. layout_wd = UseCustomColumnWidth ? cols * custom_column_width : cols * (sz.Width + x_spacing) - x_spacing;
  1491. layout_ht = rows * (sz.Height + y_spacing) - y_spacing;
  1492. if (virtual_mode) { // no actual assignment is needed on items for virtual mode
  1493. item_control.Size = new Size (layout_wd, layout_ht)

Large files files are truncated, but you can click here to view the full file