X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2FManaged.Windows.Forms%2FSystem.Windows.Forms%2FListView.cs;h=c1b7d791f8d2974c14d91a11622fb822eee0dafa;hb=2f9c820c7ee1063d9fabcb2410b57843c17cb926;hp=c2c2c60a7cfe3a8845b67c61e765537fb61d819c;hpb=2c0def8b4cc31625afafaf2b706fe308b543c5fa;p=mono.git diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ListView.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ListView.cs index c2c2c60a7cf..c1b7d791f8d 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ListView.cs +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ListView.cs @@ -37,20 +37,16 @@ using System.ComponentModel.Design; using System.Drawing; using System.Runtime.InteropServices; using System.Globalization; -#if NET_2_0 using System.Collections.Generic; -#endif namespace System.Windows.Forms { [DefaultEvent ("SelectedIndexChanged")] [DefaultProperty ("Items")] [Designer ("System.Windows.Forms.Design.ListViewDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")] -#if NET_2_0 [ClassInterface (ClassInterfaceType.AutoDispatch)] [ComVisible (true)] [Docking (DockingBehavior.Ask)] -#endif public class ListView : Control { private ItemActivation activation = ItemActivation.Standard; @@ -69,11 +65,9 @@ namespace System.Windows.Forms private bool hover_selection; private IComparer item_sorter; private readonly ListViewItemCollection items; -#if NET_2_0 private readonly ListViewGroupCollection groups; private bool owner_draw; private bool show_groups = true; -#endif private bool label_edit; private bool label_wrap = true; private bool multiselect = true; @@ -87,7 +81,7 @@ namespace System.Windows.Forms private View view = View.LargeIcon; private int layout_wd; // We might draw more than our client area private int layout_ht; // therefore we need to have these two. - HeaderControl header_control; + internal HeaderControl header_control; internal ItemControl item_control; internal ScrollBar h_scroll; // used for scrolling horizontally internal ScrollBar v_scroll; // used for scrolling vertically @@ -103,7 +97,6 @@ namespace System.Windows.Forms private Size item_size; // used for caching item size private int custom_column_width; // used when using Columns with SmallIcon/List views private int hot_item_index = -1; -#if NET_2_0 private bool hot_tracking; private ListViewInsertionMark insertion_mark; private bool show_item_tooltips; @@ -112,7 +105,9 @@ namespace System.Windows.Forms private bool virtual_mode; private int virtual_list_size; private bool right_to_left_layout; -#endif + // selection is available after the first time the handle is created, *even* if later + // the handle is either recreated or destroyed - so keep this info around. + private bool is_selection_available; // internal variables internal ImageList large_image_list; @@ -127,7 +122,6 @@ namespace System.Windows.Forms static object ItemCheckEvent = new object (); static object ItemDragEvent = new object (); static object SelectedIndexChangedEvent = new object (); -#if NET_2_0 static object DrawColumnHeaderEvent = new object(); static object DrawItemEvent = new object(); static object DrawSubItemEvent = new object(); @@ -139,30 +133,19 @@ namespace System.Windows.Forms static object RightToLeftLayoutChangedEvent = new object (); static object SearchForVirtualItemEvent = new object (); static object VirtualItemsSelectionRangeChangedEvent = new object (); -#endif public event LabelEditEventHandler AfterLabelEdit { add { Events.AddHandler (AfterLabelEditEvent, value); } remove { Events.RemoveHandler (AfterLabelEditEvent, value); } } -#if !NET_2_0 - [Browsable (false)] - [EditorBrowsable (EditorBrowsableState.Never)] - public new event EventHandler BackgroundImageChanged { - add { base.BackgroundImageChanged += value; } - remove { base.BackgroundImageChanged -= value; } - } -#endif -#if NET_2_0 [Browsable (false)] [EditorBrowsable (EditorBrowsableState.Never)] public new event EventHandler BackgroundImageLayoutChanged { add { base.BackgroundImageLayoutChanged += value; } remove { base.BackgroundImageLayoutChanged -= value; } } -#endif public event LabelEditEventHandler BeforeLabelEdit { add { Events.AddHandler (BeforeLabelEditEvent, value); } @@ -174,7 +157,6 @@ namespace System.Windows.Forms remove { Events.RemoveHandler (ColumnClickEvent, value); } } -#if NET_2_0 public event DrawListViewColumnHeaderEventHandler DrawColumnHeader { add { Events.AddHandler(DrawColumnHeaderEvent, value); } remove { Events.RemoveHandler(DrawColumnHeaderEvent, value); } @@ -189,7 +171,6 @@ namespace System.Windows.Forms add { Events.AddHandler(DrawSubItemEvent, value); } remove { Events.RemoveHandler(DrawSubItemEvent, value); } } -#endif public event EventHandler ItemActivate { add { Events.AddHandler (ItemActivateEvent, value); } @@ -201,19 +182,16 @@ namespace System.Windows.Forms remove { Events.RemoveHandler (ItemCheckEvent, value); } } -#if NET_2_0 public event ItemCheckedEventHandler ItemChecked { add { Events.AddHandler (ItemCheckedEvent, value); } remove { Events.RemoveHandler (ItemCheckedEvent, value); } } -#endif public event ItemDragEventHandler ItemDrag { add { Events.AddHandler (ItemDragEvent, value); } remove { Events.RemoveHandler (ItemDragEvent, value); } } -#if NET_2_0 public event ListViewItemMouseHoverEventHandler ItemMouseHover { add { Events.AddHandler (ItemMouseHoverEvent, value); } remove { Events.RemoveHandler (ItemMouseHoverEvent, value); } @@ -230,7 +208,6 @@ namespace System.Windows.Forms add { base.PaddingChanged += value; } remove { base.PaddingChanged -= value; } } -#endif [Browsable (false)] [EditorBrowsable (EditorBrowsableState.Never)] @@ -251,7 +228,6 @@ namespace System.Windows.Forms remove { base.TextChanged -= value; } } -#if NET_2_0 public event CacheVirtualItemsEventHandler CacheVirtualItems { add { Events.AddHandler (CacheVirtualItemsEvent, value); } remove { Events.RemoveHandler (CacheVirtualItemsEvent, value); } @@ -276,7 +252,6 @@ namespace System.Windows.Forms add { Events.AddHandler (VirtualItemsSelectionRangeChangedEvent, value); } remove { Events.RemoveHandler (VirtualItemsSelectionRangeChangedEvent, value); } } -#endif #endregion // Events @@ -284,10 +259,9 @@ namespace System.Windows.Forms public ListView () { background_color = ThemeEngine.Current.ColorWindow; -#if NET_2_0 groups = new ListViewGroupCollection (this); -#endif items = new ListViewItemCollection (this); + items.Changed += new CollectionChangedHandler (OnItemsChanged); checked_indices = new CheckedIndexCollection (this); checked_items = new CheckedListViewItemCollection (this); columns = new ColumnHeaderCollection (this); @@ -297,11 +271,9 @@ namespace System.Windows.Forms items_location = new Point [16]; items_matrix_location = new ItemMatrixLocation [16]; reordered_items_indices = new int [16]; -#if NET_2_0 item_tooltip = new ToolTip (); item_tooltip.Active = false; insertion_mark = new ListViewInsertionMark (this); -#endif InternalBorderStyle = BorderStyle.Fixed3D; @@ -334,15 +306,12 @@ namespace System.Windows.Forms LostFocus += new EventHandler (FocusChanged); MouseWheel += new MouseEventHandler(ListView_MouseWheel); MouseEnter += new EventHandler (ListView_MouseEnter); + Invalidated += new InvalidateEventHandler (ListView_Invalidated); -#if NET_2_0 BackgroundImageTiled = false; -#endif this.SetStyle (ControlStyles.UserPaint | ControlStyles.StandardClick -#if NET_2_0 | ControlStyles.UseTextForAccessibility -#endif , false); } #endregion // Public Constructors @@ -386,6 +355,13 @@ namespace System.Windows.Forms } } + internal bool UsingGroups { + get { + return show_groups && groups.Count > 0 && view != View.List && + Application.VisualStylesEnabled; + } + } + internal override bool ScaleChildrenInternal { get { return false; } } @@ -396,6 +372,11 @@ namespace System.Windows.Forms } } + internal ColumnHeader EnteredColumnHeader { + get { + return header_control.EnteredColumnHeader; + } + } #endregion // Private Internal Properties #region Protected Properties @@ -406,7 +387,6 @@ namespace System.Windows.Forms protected override Size DefaultSize { get { return ThemeEngine.Current.ListViewDefaultSize; } } -#if NET_2_0 protected override bool DoubleBuffered { get { return base.DoubleBuffered; @@ -415,7 +395,6 @@ namespace System.Windows.Forms base.DoubleBuffered = value; } } -#endif #endregion // Protected Properties #region Public Instance Properties @@ -428,10 +407,8 @@ namespace System.Windows.Forms throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for Activation", value)); } -#if NET_2_0 if (hot_tracking && value != ItemActivation.OneClick) throw new ArgumentException ("When HotTracking is on, activation must be ItemActivation.OneClick"); -#endif activation = value; } @@ -489,16 +466,6 @@ namespace System.Windows.Forms } } -#if !NET_2_0 - [Browsable (false)] - [EditorBrowsable (EditorBrowsableState.Never)] - public override Image BackgroundImage { - get { return base.BackgroundImage; } - set { base.BackgroundImage = value; } - } -#endif - -#if NET_2_0 [Browsable (false)] [EditorBrowsable (EditorBrowsableState.Never)] public override ImageLayout BackgroundImageLayout { @@ -523,7 +490,6 @@ namespace System.Windows.Forms item_control.BackgroundImageLayout = new_image_layout; } } -#endif [DefaultValue (BorderStyle.Fixed3D)] [DispId (-504)] @@ -537,15 +503,16 @@ namespace System.Windows.Forms get { return check_boxes; } set { if (check_boxes != value) { -#if NET_2_0 if (value && View == View.Tile) throw new NotSupportedException ("CheckBoxes are not" + " supported in Tile view. Choose a different" + " view or set CheckBoxes to false."); -#endif check_boxes = value; this.Redraw (true); + + //UIA Framework: Event used by ListView to set/unset Toggle Pattern + OnUIACheckBoxesChanged (); } } } @@ -562,9 +529,7 @@ namespace System.Windows.Forms get { return checked_items; } } -#if NET_2_0 [Editor ("System.Windows.Forms.Design.ColumnHeaderCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))] -#endif [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)] [Localizable (true)] [MergableProperty (false)] @@ -581,7 +546,6 @@ namespace System.Windows.Forms return GetItemAtDisplayIndex (focused_item_index); } -#if NET_2_0 set { if (value == null || value.ListView != this || !IsHandleCreated) @@ -589,7 +553,6 @@ namespace System.Windows.Forms SetFocusedItem (value.DisplayIndex); } -#endif } public override Color ForeColor { @@ -658,7 +621,6 @@ namespace System.Windows.Forms } } -#if NET_2_0 [DefaultValue (false)] public bool HotTracking { get { @@ -675,21 +637,17 @@ namespace System.Windows.Forms } } } -#endif [DefaultValue (false)] public bool HoverSelection { get { return hover_selection; } set { -#if NET_2_0 if (hot_tracking && value == false) throw new ArgumentException ("When HotTracking is on, hover selection must be true"); -#endif hover_selection = value; } } -#if NET_2_0 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] [Browsable (false)] public ListViewInsertionMark InsertionMark { @@ -697,11 +655,8 @@ namespace System.Windows.Forms return insertion_mark; } } -#endif -#if NET_2_0 [Editor ("System.Windows.Forms.Design.ListViewItemCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))] -#endif [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)] [Localizable (true)] [MergableProperty (false)] @@ -712,7 +667,15 @@ namespace System.Windows.Forms [DefaultValue (false)] public bool LabelEdit { get { return label_edit; } - set { label_edit = value; } + set { + if (value != label_edit) { + label_edit = value; + + // UIA Framework: Event used by Value Pattern in ListView.ListItem provider + OnUIALabelEditChanged (); + } + + } } [DefaultValue (true)] @@ -755,11 +718,17 @@ namespace System.Windows.Forms [DefaultValue (true)] public bool MultiSelect { get { return multiselect; } - set { multiselect = value; } + set { + if (value != multiselect) { + multiselect = value; + + // UIA Framework: Event used by Selection Pattern in ListView.ListItem provider + OnUIAMultiSelectChanged (); + } + } } -#if NET_2_0 [DefaultValue(false)] public bool OwnerDraw { get { return owner_draw; } @@ -793,7 +762,6 @@ namespace System.Windows.Forms } } } -#endif [DefaultValue (true)] public bool Scrollable { @@ -818,7 +786,6 @@ namespace System.Windows.Forms get { return selected_items; } } -#if NET_2_0 [DefaultValue(true)] public bool ShowGroups { get { return show_groups; } @@ -826,6 +793,9 @@ namespace System.Windows.Forms if (show_groups != value) { show_groups = value; Redraw(true); + + // UIA Framework: Used to update a11y Tree + OnUIAShowGroupsChanged (); } } } @@ -848,7 +818,6 @@ namespace System.Windows.Forms item_tooltip.Active = false; } } -#endif [DefaultValue (null)] public ImageList SmallImageList { @@ -873,39 +842,22 @@ namespace System.Windows.Forms sort_order = value; -#if NET_2_0 if (virtual_mode) // Sorting is not allowed in virtual mode return; -#endif if (value == SortOrder.None) { if (item_sorter != null) { // ListViewItemSorter should never be reset for SmallIcon // and LargeIcon view if (View != View.SmallIcon && View != View.LargeIcon) -#if NET_2_0 item_sorter = null; -#else - // in .NET 1.1, only internal IComparer would be - // set to null - if (item_sorter is ItemComparer) - item_sorter = null; -#endif } this.Redraw (false); } else { if (item_sorter == null) item_sorter = new ItemComparer (value); if (item_sorter is ItemComparer) { -#if NET_2_0 item_sorter = new ItemComparer (value); -#else - // in .NET 1.1, the sort order is not updated for - // SmallIcon and LargeIcon views if no custom IComparer - // is set - if (View != View.SmallIcon && View != View.LargeIcon) - item_sorter = new ItemComparer (value); -#endif } Sort (); } @@ -950,7 +902,6 @@ namespace System.Windows.Forms } } -#if NET_2_0 [Browsable (true)] public Size TileSize { get { @@ -961,19 +912,17 @@ namespace System.Windows.Forms throw new ArgumentOutOfRangeException ("value"); tile_size = value; - Redraw (true); + if (view == View.Tile) + Redraw (true); } } -#endif [Browsable (false)] [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)] public ListViewItem TopItem { get { -#if NET_2_0 if (view == View.LargeIcon || view == View.SmallIcon || view == View.Tile) throw new InvalidOperationException ("Cannot get the top item in LargeIcon, SmallIcon or Tile view."); -#endif // there is no item if (this.items.Count == 0) return null; @@ -983,15 +932,15 @@ namespace System.Windows.Forms return this.items [0]; // do a hit test for the scrolled position else { + int header_offset = header_control.Height; for (int i = 0; i < items.Count; i++) { Point item_loc = GetItemLocation (i); - if (item_loc.X >= 0 && item_loc.Y >= 0) + if (item_loc.X >= 0 && item_loc.Y - header_offset >= 0) return items [i]; } return null; } } -#if NET_2_0 set { if (view == View.LargeIcon || view == View.SmallIcon || view == View.Tile) throw new InvalidOperationException ("Cannot set the top item in LargeIcon, SmallIcon or Tile view."); @@ -1000,12 +949,11 @@ namespace System.Windows.Forms if (value == null || value.ListView != this) return; - EnsureVisible (value.Index); + // Take advantage this property is only valid for Details view. + SetScrollValue (v_scroll, item_size.Height * value.Index); } -#endif } -#if NET_2_0 [EditorBrowsable (EditorBrowsableState.Advanced)] [DefaultValue (true)] [Browsable (false)] @@ -1017,7 +965,6 @@ namespace System.Windows.Forms set { } } -#endif [DefaultValue (View.LargeIcon)] public View View { @@ -1028,21 +975,25 @@ namespace System.Windows.Forms typeof (View)); if (view != value) { -#if NET_2_0 if (CheckBoxes && value == View.Tile) throw new NotSupportedException ("CheckBoxes are not" + " supported in Tile view. Choose a different" + " view or set CheckBoxes to false."); -#endif + if (VirtualMode && value == View.Tile) + throw new NotSupportedException ("VirtualMode is" + + " not supported in Tile view. Choose a different" + + " view or set ViewMode to false."); h_scroll.Value = v_scroll.Value = 0; view = value; Redraw (true); + + // UIA Framework: Event used to update UIA Tree. + OnUIAViewChanged (); } } } -#if NET_2_0 [DefaultValue (false)] [RefreshProperties (RefreshProperties.Repaint)] public bool VirtualMode { @@ -1055,6 +1006,10 @@ namespace System.Windows.Forms if (!virtual_mode && items.Count > 0) throw new InvalidOperationException (); + if (value && view == View.Tile) + throw new NotSupportedException ("VirtualMode is" + + " not supported in Tile view. Choose a different" + + " view or set ViewMode to false."); virtual_mode = value; Redraw (true); @@ -1081,7 +1036,6 @@ namespace System.Windows.Forms } } } -#endif #endregion // Public Instance Properties #region Internal Methods Properties @@ -1096,6 +1050,27 @@ namespace System.Windows.Forms return 0; Size item_size = ItemSize; + // In virtual mode we always have fixed positions, and we can infer the positon easily + if (virtual_mode) { + int first = 0; + switch (view) { + case View.Details: + first = v_marker / item_size.Height; + break; + case View.LargeIcon: + case View.SmallIcon: + first = (v_marker / (item_size.Height + y_spacing)) * cols; + break; + case View.List: + first = (h_marker / (item_size.Width * x_spacing)) * rows; + break; + } + + if (first >= items.Count) + first = items.Count; + + return first; + } for (int i = 0; i < items.Count; i++) { Rectangle item_rect = new Rectangle (GetItemLocation (i), item_size); if (item_rect.Right >= 0 && item_rect.Bottom >= 0) @@ -1125,7 +1100,7 @@ namespace System.Windows.Forms internal void OnSelectedIndexChanged () { - if (IsHandleCreated) + if (is_selection_available) OnSelectedIndexChanged (EventArgs.Empty); } @@ -1142,17 +1117,15 @@ namespace System.Windows.Forms // Avoid calculations when control is being updated if (updating) return; -#if NET_2_0 // VirtualMode doesn't do any calculations until handle is created if (virtual_mode && !IsHandleCreated) return; -#endif if (recalculate) CalculateListView (this.alignment); - Refresh (); + Invalidate (true); } void InvalidateSelection () @@ -1206,7 +1179,6 @@ namespace System.Windows.Forms { Size temp = Size.Empty; Size ret_size = Size.Empty; -#if NET_2_0 bool use_indent_count = small_image_list != null; // VirtualMode uses the first item text size @@ -1218,7 +1190,6 @@ namespace System.Windows.Forms if (use_indent_count) ret_size.Width += item.IndentCount * small_image_list.ImageSize.Width; } else { -#endif // 0th column holds the item text, we check the size of // the various subitems falling in that column and get // the biggest one's size. @@ -1229,17 +1200,13 @@ namespace System.Windows.Forms temp = Size.Ceiling (TextRenderer.MeasureString (item.SubItems [col].Text, Font)); -#if NET_2_0 if (use_indent_count) temp.Width += item.IndentCount * small_image_list.ImageSize.Width; -#endif if (temp.Width > ret_size.Width) ret_size = temp; } -#if NET_2_0 } -#endif // adjustment for space in Details view if (!ret_size.IsEmpty && view == View.Details) @@ -1295,33 +1262,36 @@ namespace System.Windows.Forms text_size.Height += 2; } - private void Scroll (ScrollBar scrollbar, int delta) + private void SetScrollValue (ScrollBar scrollbar, int val) { - if (delta == 0 || !scrollbar.Visible) - return; - int max; if (scrollbar == h_scroll) - max = h_scroll.Maximum - item_control.Width; + max = h_scroll.Maximum - h_scroll.LargeChange + 1; else - max = v_scroll.Maximum - item_control.Height; + max = v_scroll.Maximum - v_scroll.LargeChange + 1; - int val = scrollbar.Value + delta; if (val > max) val = max; else if (val < scrollbar.Minimum) val = scrollbar.Minimum; + scrollbar.Value = val; } - private void CalculateScrollBars () + private void Scroll (ScrollBar scrollbar, int delta) { - if (!IsHandleCreated) + if (delta == 0 || !scrollbar.Visible) return; + SetScrollValue (scrollbar, scrollbar.Value + delta); + } + + private void CalculateScrollBars () + { Rectangle client_area = ClientRectangle; int height = client_area.Height; int width = client_area.Width; + Size item_size; if (!scrollable) { h_scroll.Visible = false; @@ -1355,6 +1325,8 @@ namespace System.Windows.Forms } + item_size = ItemSize; + if (h_scroll.is_visible) { h_scroll.Location = new Point (client_area.X, client_area.Bottom - h_scroll.Height); h_scroll.Minimum = 0; @@ -1370,8 +1342,12 @@ namespace System.Windows.Forms h_scroll.Width = client_area.Width; } + if (view == View.List) + h_scroll.SmallChange = item_size.Width + ThemeEngine.Current.ListViewHorizontalSpacing; + else + h_scroll.SmallChange = Font.Height; + h_scroll.LargeChange = client_area.Width; - h_scroll.SmallChange = Font.Height; height -= h_scroll.Height; } @@ -1379,18 +1355,25 @@ namespace System.Windows.Forms v_scroll.Location = new Point (client_area.Right - v_scroll.Width, client_area.Y); v_scroll.Minimum = 0; - // if h_scroll is visible, adjust the maximum of the + // if h_scroll is visible, adjust the height of // v_scroll to account for the height of h_scroll if (h_scroll.Visible) { v_scroll.Maximum = layout_ht + h_scroll.Height; - v_scroll.Height = client_area.Height; // - h_scroll.Height already done + v_scroll.Height = client_area.Height > h_scroll.Height ? client_area.Height - h_scroll.Height : 0; } else { v_scroll.Maximum = layout_ht; v_scroll.Height = client_area.Height; } - v_scroll.LargeChange = client_area.Height; - v_scroll.SmallChange = Font.Height; + if (view == View.Details) { + // Need to update Maximum if using LargeChange with value other than the visible area + int headerPlusOneItem = header_control.Height + item_size.Height; + v_scroll.LargeChange = v_scroll.Height > headerPlusOneItem ? v_scroll.Height - headerPlusOneItem : 0; + v_scroll.Maximum = v_scroll.Maximum > headerPlusOneItem ? v_scroll.Maximum - headerPlusOneItem : 0; + } else + v_scroll.LargeChange = v_scroll.Height; + + v_scroll.SmallChange = item_size.Height; width -= v_scroll.Width; } @@ -1400,7 +1383,6 @@ namespace System.Windows.Forms header_control.Width = width; } -#if NET_2_0 internal int GetReorderedColumnIndex (ColumnHeader column) { if (reordered_column_indices == null) @@ -1412,7 +1394,6 @@ namespace System.Windows.Forms return -1; } -#endif internal ColumnHeader GetReorderedColumn (int index) { @@ -1424,7 +1405,6 @@ namespace System.Windows.Forms internal void ReorderColumn (ColumnHeader col, int index, bool fireEvent) { -#if NET_2_0 if (fireEvent) { ColumnReorderedEventHandler eh = (ColumnReorderedEventHandler) (Events [ColumnReorderedEvent]); if (eh != null){ @@ -1438,7 +1418,6 @@ namespace System.Windows.Forms } } } -#endif int column_count = Columns.Count; if (reordered_column_indices == null) { @@ -1533,7 +1512,6 @@ namespace System.Windows.Forms } } -#if NET_2_0 Size TileItemSize { get { // Calculate tile size if needed @@ -1551,7 +1529,6 @@ namespace System.Windows.Forms return tile_size; } } -#endif int GetDetailsItemHeight () { @@ -1569,9 +1546,6 @@ namespace System.Windows.Forms if (old_location.X == x && old_location.Y == y) return; - Size item_size = ItemSize; - Rectangle old_rect = new Rectangle (GetItemLocation (index), item_size); - items_location [index] = new Point (x, y); items_matrix_location [index] = new ItemMatrixLocation (row, col); @@ -1579,13 +1553,9 @@ namespace System.Windows.Forms // Initial position matches item's position in ListViewItemCollection // reordered_items_indices [index] = index; - - // Invalidate both previous and new bounds - item_control.Invalidate (old_rect); - item_control.Invalidate (new Rectangle (GetItemLocation (index), item_size)); } -#if NET_2_0 + void ShiftItemsPositions (int from, int to, bool forward) { if (forward) { @@ -1593,18 +1563,18 @@ namespace System.Windows.Forms reordered_items_indices [i] = reordered_items_indices [i - 1]; ListViewItem item = items [reordered_items_indices [i]]; - item_control.Invalidate (item.Bounds); + item.Invalidate (); item.DisplayIndex = i; - item_control.Invalidate (item.Bounds); + item.Invalidate (); } } else { for (int i = from - 1; i < to; i++) { reordered_items_indices [i] = reordered_items_indices [i + 1]; ListViewItem item = items [reordered_items_indices [i]]; - item_control.Invalidate (item.Bounds); + item.Invalidate (); item.DisplayIndex = i; - item_control.Invalidate (item.Bounds); + item.Invalidate (); } } } @@ -1632,9 +1602,9 @@ namespace System.Windows.Forms reordered_items_indices [new_display_index] = item_index; - item_control.Invalidate (item.Bounds); + item.Invalidate (); item.DisplayIndex = new_display_index; - item_control.Invalidate (item.Bounds); + item.Invalidate (); } int GetDisplayIndexFromLocation (Point loc) @@ -1680,8 +1650,10 @@ namespace System.Windows.Forms return count; } -#endif + // cache the spacing to let virtualmode compute the positions on the fly + int x_spacing; + int y_spacing; int rows; int cols; int[,] item_index_matrix; @@ -1692,8 +1664,7 @@ namespace System.Windows.Forms if (UseCustomColumnWidth) CalculateCustomColumnWidth (); -#if NET_2_0 - if (show_groups && groups.Count > 0 && view != View.List) { + if (UsingGroups) { // When groups are used the alignment is always top-aligned rows = 0; cols = 0; @@ -1722,7 +1693,6 @@ namespace System.Windows.Forms items += items_in_group; } } else -#endif { // Simple matrix if no groups are used if (left_aligned) { @@ -1767,32 +1737,36 @@ namespace System.Windows.Forms item_control.Visible = true; item_control.Location = Point.Empty; ItemSize = item_size; // Cache item size + this.x_spacing = x_spacing; + this.y_spacing = y_spacing; if (items.Count == 0) return; Size sz = item_size; -#if NET_2_0 - bool using_groups = show_groups && groups.Count > 0 && view != View.List; -#endif CalculateRowsAndCols (sz, left_aligned, x_spacing, y_spacing); layout_wd = UseCustomColumnWidth ? cols * custom_column_width : cols * (sz.Width + x_spacing) - x_spacing; layout_ht = rows * (sz.Height + y_spacing) - y_spacing; -#if NET_2_0 - if (using_groups) + + if (virtual_mode) { // no actual assignment is needed on items for virtual mode + item_control.Size = new Size (layout_wd, layout_ht); + return; + } + + bool using_groups = UsingGroups; + if (using_groups) // the groups layout will override layout_ht CalculateGroupsLayout (sz, y_spacing, 0); -#endif int row = 0, col = 0; int x = 0, y = 0; int display_index = 0; for (int i = 0; i < items.Count; i++) { -#if NET_2_0 + ListViewItem item = items [i]; if (using_groups) { - ListViewGroup group = items [i].Group; + ListViewGroup group = item.Group; if (group == null) group = groups.DefaultGroup; @@ -1812,7 +1786,6 @@ namespace System.Windows.Forms item_index_matrix [row + starting_row, col] = i; } else -#endif { x = UseCustomColumnWidth ? col * custom_column_width : col * (item_size.Width + x_spacing); y = row * (item_size.Height + y_spacing); @@ -1834,23 +1807,15 @@ namespace System.Windows.Forms } } } -#if NET_2_0 - if (!virtual_mode) -#endif - { - ListViewItem item = items [i]; - item.Layout (); - item.DisplayIndex = display_index; - item.SetPosition (new Point (x, y)); - } - + item.Layout (); + item.DisplayIndex = display_index; + item.SetPosition (new Point (x, y)); } item_control.Size = new Size (layout_wd, layout_ht); } -#if NET_2_0 void CalculateGroupsLayout (Size item_size, int y_spacing, int y_origin) { int y = y_origin; @@ -1870,7 +1835,7 @@ namespace System.Windows.Forms int LayoutGroupHeader (ListViewGroup group, int y_origin, int item_height, int y_spacing, int rows) { Rectangle client_area = ClientRectangle; - int header_height = text_size.Height + 10; + int header_height = Font.Height + 15; // one line height + some padding group.HeaderBounds = new Rectangle (0, y_origin, client_area.Width - v_scroll.Width, header_height); group.items_area_location = new Point (0, y_origin + header_height); @@ -1883,6 +1848,7 @@ namespace System.Windows.Forms { int items = 0; + groups.DefaultGroup.ItemCount = GetDefaultGroupItems (); for (int i = 0; i < groups.InternalCount; i++) { ListViewGroup group = groups.GetInternalGroup (i); int items_in_group = group.GetActualItemCount (); @@ -1895,7 +1861,6 @@ namespace System.Windows.Forms items += items_in_group; } } -#endif void LayoutHeader () { @@ -1919,7 +1884,7 @@ namespace System.Windows.Forms layout_wd = ClientRectangle.Width; } else { header_control.Width = x; - header_control.Height = columns.Count > 0 ? columns [0].Ht : Font.Height + 5; + header_control.Height = columns.Count > 0 ? columns [0].Ht : ThemeEngine.Current.ListViewGetHeaderHeight (this, Font); header_control.Visible = true; } } @@ -1938,22 +1903,31 @@ namespace System.Windows.Forms item_control.Visible = true; item_control.Location = Point.Empty; item_control.Width = ClientRectangle.Width; + AdjustChildrenZOrder (); int item_height = GetDetailsItemHeight (); ItemSize = new Size (0, item_height); // We only cache Height for details view int y = header_control.Height; -#if NET_2_0 - bool using_groups = show_groups && groups.Count > 0 && view != View.List; + layout_ht = y + (item_height * items.Count); + if (items.Count > 0 && grid_lines) // some space for bottom gridline + layout_ht += 2; + + bool using_groups = UsingGroups; if (using_groups) { + // Observe that this routines will override our layout_ht value CalculateDetailsGroupItemsCount (); CalculateGroupsLayout (ItemSize, 2, y); } -#endif + + if (virtual_mode) // no assgination on items is needed + return; for (int i = 0; i < items.Count; i++) { ListViewItem item = items [i]; + int display_index; -#if NET_2_0 + int item_y; + if (using_groups) { ListViewGroup group = item.Group; if (group == null) @@ -1963,40 +1937,41 @@ namespace System.Windows.Forms Point group_items_loc = group.items_area_location; display_index = group.starting_item + current_item; - y = current_item * (item_height + 2) + group_items_loc.Y; - SetItemLocation (display_index, 0, y, 0, 0); + y = item_y = current_item * (item_height + 2) + group_items_loc.Y; + SetItemLocation (display_index, 0, item_y, 0, 0); SetItemAtDisplayIndex (display_index, i); - item.SetPosition (new Point (0, y)); } else -#endif { display_index = i; - SetItemLocation (i, 0, y, 0, 0); - item.SetPosition (new Point (0, y)); + item_y = y; + SetItemLocation (i, 0, item_y, 0, 0); y += item_height; } -#if NET_2_0 - if (!virtual_mode) // Virtual mode sets Layout until draw time -#endif - { - item.Layout (); - item.DisplayIndex = display_index; - } + item.Layout (); + item.DisplayIndex = display_index; + item.SetPosition (new Point (0, item_y)); } + } - // some space for bottom gridline - if (items.Count > 0 && grid_lines) - y += 2; - -#if NET_2_0 - if (!using_groups) // With groups it has been previously computed -#endif - layout_ht = y; + // Need to make sure HeaderControl is on top, and we can't simply use BringToFront since + // these controls are implicit, so we need to re-populate our collection. + void AdjustChildrenZOrder () + { + SuspendLayout (); + Controls.ClearImplicit (); + Controls.AddImplicit (header_control); + Controls.AddImplicit (item_control); + Controls.AddImplicit (h_scroll); + Controls.AddImplicit (v_scroll); + ResumeLayout (); } private void AdjustItemsPositionArray (int count) { + // In virtual mode we compute the positions on the fly. + if (virtual_mode) + return; if (items_location.Length >= count) return; @@ -2033,13 +2008,14 @@ namespace System.Windows.Forms LayoutIcons (SmallIconItemSize, true, ThemeEngine.Current.ListViewHorizontalSpacing, 2); break; -#if NET_2_0 case View.Tile: + if (!Application.VisualStylesEnabled) + goto case View.LargeIcon; + LayoutIcons (TileItemSize, alignment == ListViewAlignment.Left, ThemeEngine.Current.ListViewHorizontalSpacing, ThemeEngine.Current.ListViewVerticalSpacing); break; -#endif } CalculateScrollBars (); @@ -2047,20 +2023,52 @@ namespace System.Windows.Forms internal Point GetItemLocation (int index) { - Point loc = items_location [index]; + Point loc = Point.Empty; + if (virtual_mode) + loc = GetFixedItemLocation (index); + else + loc = items_location [index]; + loc.X -= h_marker; // Adjust to scroll loc.Y -= v_marker; return loc; } + Point GetFixedItemLocation (int index) + { + Point loc = Point.Empty; + + switch (view) { + case View.LargeIcon: + case View.SmallIcon: + loc.X = index % cols * (item_size.Width + x_spacing); + loc.Y = index / cols * (item_size.Height + y_spacing); + break; + case View.List: + loc.X = index / rows * (item_size.Width + x_spacing); + loc.Y = index % rows * (item_size.Height + y_spacing); + break; + case View.Details: + loc.Y = header_control.Height + (index * item_size.Height); + break; + } + + return loc; + } + internal int GetItemIndex (int display_index) { + if (virtual_mode) + return display_index; // no reordering in virtual mode. return reordered_items_indices [display_index]; } internal ListViewItem GetItemAtDisplayIndex (int display_index) { + // in virtual mode there's no reordering at all. + if (virtual_mode) + return items [display_index]; return items [reordered_items_indices [display_index]]; } @@ -2082,24 +2090,31 @@ namespace System.Windows.Forms keysearch_text += (char)ke.KeyCode; keysearch_tickcnt = current_tickcnt; - int start = FocusedItem == null ? 0 : FocusedItem.DisplayIndex; - int i = start; - while (true) { - if (CultureInfo.CurrentCulture.CompareInfo.IsPrefix (GetItemAtDisplayIndex (i).Text, keysearch_text, - CompareOptions.IgnoreCase)) { - SetFocusedItem (i); - GetItemAtDisplayIndex (i).Selected = true; - EnsureVisible (GetItemIndex (i)); - break; - } - i = (i + 1 < Items.Count) ? i+1 : 0; + int prev_focused = FocusedItem == null ? 0 : FocusedItem.DisplayIndex; + int start = prev_focused + 1 < Items.Count ? prev_focused + 1 : 0; - if (i == start) - break; + ListViewItem item = FindItemWithText (keysearch_text, false, start, true, true); + if (item != null && prev_focused != item.DisplayIndex) { + selected_indices.Clear (); + + SetFocusedItem (item.DisplayIndex); + item.Selected = true; + EnsureVisible (GetItemIndex (item.DisplayIndex)); } + return true; } + private void OnItemsChanged () + { + ResetSearchString (); + } + + private void ResetSearchString () + { + keysearch_text = String.Empty; + } + int GetAdjustedIndex (Keys key) { int result = -1; @@ -2147,6 +2162,9 @@ namespace System.Windows.Forms return result; } + if (virtual_mode) + return GetFixedAdjustedIndex (key); + ItemMatrixLocation item_matrix_location = items_matrix_location [FocusedItem.DisplayIndex]; int row = item_matrix_location.Row; int col = item_matrix_location.Col; @@ -2200,6 +2218,47 @@ namespace System.Windows.Forms return items [adjusted_index].DisplayIndex; } + // Used for virtual mode, where items *cannot* be re-arranged + int GetFixedAdjustedIndex (Keys key) + { + int result; + + switch (key) { + case Keys.Left: + if (view == View.List) + result = focused_item_index - rows; + else + result = focused_item_index - 1; + break; + case Keys.Right: + if (view == View.List) + result = focused_item_index + rows; + else + result = focused_item_index + 1; + break; + case Keys.Up: + if (view != View.List) + result = focused_item_index - cols; + else + result = focused_item_index - 1; + break; + case Keys.Down: + if (view != View.List) + result = focused_item_index + cols; + else + result = focused_item_index + 1; + break; + default: + return -1; + + } + + if (result < 0 || result >= items.Count) + result = focused_item_index; + + return result; + } + ListViewItem selection_start; private bool SelectItems (ArrayList sel_items) @@ -2306,6 +2365,7 @@ namespace System.Windows.Forms break; case Keys.Space: + SelectIndex (focused_item_index); ToggleItemsCheckState (); break; case Keys.Enter: @@ -2382,9 +2442,7 @@ namespace System.Windows.Forms bool hover_processed = false; bool checking = false; ListViewItem prev_hovered_item; -#if NET_2_0 ListViewItem prev_tooltip_item; -#endif int clicks; Point drag_begin = new Point (-1, -1); internal int dragged_item_index = -1; @@ -2396,6 +2454,7 @@ namespace System.Windows.Forms public ItemControl (ListView owner) { this.owner = owner; + this.SetStyle (ControlStyles.DoubleBuffer, true); DoubleClick += new EventHandler(ItemsDoubleClick); MouseDown += new MouseEventHandler(ItemsMouseDown); MouseMove += new MouseEventHandler(ItemsMouseMove); @@ -2486,7 +2545,8 @@ namespace System.Windows.Forms ArrayList result = new ArrayList (); for (int i = 0; i < owner.Items.Count; i++) { bool intersects; - if (owner.View == View.Details && !owner.FullRowSelect) + // Can't iterate over specific items properties in virtualmode + if (owner.View == View.Details && !owner.FullRowSelect && !owner.VirtualMode) intersects = BoxIntersectsText (i); else intersects = BoxIntersectsItem (i); @@ -2566,9 +2626,6 @@ namespace System.Windows.Forms // and if we are in 1.1 profile only take into account // double clicks if (owner.StateImageList != null && owner.StateImageList.Images.Count < 2 -#if !NET_2_0 - && me.Clicks == 1 -#endif ) return; @@ -2585,7 +2642,7 @@ namespace System.Windows.Forms if (owner.View == View.Details) { bool over_text = item.TextBounds.Contains (pt); if (owner.FullRowSelect) { - clicked_item = owner.items [i]; + clicked_item = item; bool over_item_column = (me.X > owner.Columns[0].X && me.X < owner.Columns[0].X + owner.Columns[0].Width); if (!over_text && over_item_column && owner.MultiSelect) box_selecting = true; @@ -2613,7 +2670,6 @@ namespace System.Windows.Forms clicked_item.Selected = true; } -#if NET_2_0 if (owner.VirtualMode && changed) { // Broken event - It's not fired from Item.Selected also ListViewVirtualItemsSelectionRangeChangedEventArgs args = @@ -2621,7 +2677,6 @@ namespace System.Windows.Forms owner.OnVirtualItemsSelectionRangeChanged (args); } -#endif // Report clicks only if the item was clicked. On MS the // clicks are only raised if you click an item clicks = me.Clicks; @@ -2632,6 +2687,9 @@ namespace System.Windows.Forms if (owner.LabelEdit && !changed) BeginEdit (clicked_item); // this is probably not the correct place to execute BeginEdit } + + drag_begin = me.Location; + dragged_item_index = clicked_item.Index; } else { if (owner.MultiSelect) box_selecting = true; @@ -2662,9 +2720,7 @@ namespace System.Windows.Forms return; if ((me.Button != MouseButtons.Left && me.Button != MouseButtons.Right) && !hover_processed && owner.Activation != ItemActivation.OneClick -#if NET_2_0 && !owner.ShowItemToolTips -#endif ) return; @@ -2679,18 +2735,14 @@ namespace System.Windows.Forms // Need to invalidate the item in HotTracking to show/hide the underline style if (owner.Activation == ItemActivation.OneClick) { if (item == null && owner.HotItemIndex != -1) { -#if NET_2_0 if (owner.HotTracking) Invalidate (owner.Items [owner.HotItemIndex].Bounds); // Previous one -#endif Cursor = Cursors.Default; owner.HotItemIndex = -1; } else if (item != null && owner.HotItemIndex == -1) { -#if NET_2_0 if (owner.HotTracking) Invalidate (item.Bounds); -#endif Cursor = Cursors.Hand; owner.HotItemIndex = item.Index; @@ -2698,13 +2750,7 @@ namespace System.Windows.Forms } if (me.Button == MouseButtons.Left || me.Button == MouseButtons.Right) { - if (drag_begin.X == -1 && drag_begin.Y == -1) { - if (item != null) { - drag_begin = new Point (me.X, me.Y); - dragged_item_index = item.Index; - } - - } else { + if (drag_begin != new Point (-1, -1)) { Rectangle r = new Rectangle (drag_begin, SystemInformation.DragSize); if (!r.Contains (me.X, me.Y)) { ListViewItem dragged_item = owner.items [dragged_item_index]; @@ -2716,7 +2762,6 @@ namespace System.Windows.Forms } } -#if NET_2_0 if (owner.ShowItemToolTips) { if (item == null) { owner.item_tooltip.Active = false; @@ -2727,7 +2772,6 @@ namespace System.Windows.Forms prev_tooltip_item = item; } } -#endif } @@ -2759,9 +2803,7 @@ namespace System.Windows.Forms Select (); // Make sure we have the focus, since MouseHover doesn't give it to us } -#if NET_2_0 owner.OnItemMouseHover (new ListViewItemMouseHoverEventArgs (item)); -#endif } void HandleClicks (MouseEventArgs me) @@ -2769,17 +2811,11 @@ namespace System.Windows.Forms // if the click is not on an item, // clicks remains as 0 if (clicks > 1) { -#if !NET_2_0 - owner.OnDoubleClick (EventArgs.Empty); - } else if (clicks == 1) { - owner.OnClick (EventArgs.Empty); -#else owner.OnDoubleClick (EventArgs.Empty); owner.OnMouseDoubleClick (me); } else if (clicks == 1) { owner.OnClick (EventArgs.Empty); owner.OnMouseClick (me); -#endif } clicks = 0; @@ -3194,12 +3230,20 @@ namespace System.Windows.Forms ListViewItem focused_item = FocusedItem; if (focused_item.ListView != null) { - item_control.Invalidate (focused_item.Bounds); + focused_item.Invalidate (); focused_item.Layout (); - item_control.Invalidate (focused_item.Bounds); + focused_item.Invalidate (); } } + private void ListView_Invalidated (object sender, InvalidateEventArgs e) + { + // When the ListView is invalidated, we need to invalidate + // the child controls. + header_control.Invalidate (); + item_control.Invalidate (); + } + private void ListView_MouseEnter (object sender, EventArgs args) { hover_pending = true; // Need a hover event for every Enter/Leave cycle @@ -3226,17 +3270,18 @@ namespace System.Windows.Forms case View.List: Scroll (h_scroll, -ItemSize.Width * lines); break; -#if NET_2_0 case View.Tile: + if (!Application.VisualStylesEnabled) + goto case View.LargeIcon; + Scroll (v_scroll, -(ItemSize.Height + ThemeEngine.Current.ListViewVerticalSpacing) * 2 * lines); break; -#endif } } private void ListView_SizeChanged (object sender, EventArgs e) { - CalculateListView (alignment); + Redraw (true); } private void SetFocusedItem (int display_index) @@ -3245,8 +3290,11 @@ namespace System.Windows.Forms GetItemAtDisplayIndex (display_index).Focused = true; else if (focused_item_index != -1 && focused_item_index < items.Count) // Previous focused item GetItemAtDisplayIndex (focused_item_index).Focused = false; - focused_item_index = display_index; + if (display_index == -1) + OnUIAFocusedItemChanged (); + // otherwise the event will have been fired + // when the ListViewItem's Focused was set } private void HorizontalScroller (object sender, EventArgs e) @@ -3296,6 +3344,7 @@ namespace System.Windows.Forms protected override void CreateHandle () { base.CreateHandle (); + is_selection_available = true; for (int i = 0; i < SelectedItems.Count; i++) OnSelectedIndexChanged (EventArgs.Empty); } @@ -3303,9 +3352,6 @@ namespace System.Windows.Forms protected override void Dispose (bool disposing) { if (disposing) { - h_scroll.Dispose (); - v_scroll.Dispose (); - large_image_list = null; small_image_list = null; state_image_list = null; @@ -3313,9 +3359,7 @@ namespace System.Windows.Forms foreach (ColumnHeader col in columns) col.SetListView (null); -#if NET_2_0 if (!virtual_mode) // In virtual mode we don't save the items -#endif foreach (ListViewItem item in items) item.Owner = null; } @@ -3350,13 +3394,11 @@ namespace System.Windows.Forms eh (this, e); } -#if NET_2_0 protected override void OnBackgroundImageChanged (EventArgs e) { item_control.BackgroundImage = BackgroundImage; base.OnBackgroundImageChanged (e); } -#endif protected virtual void OnBeforeLabelEdit (LabelEditEventArgs e) { @@ -3365,14 +3407,13 @@ namespace System.Windows.Forms eh (this, e); } - protected virtual void OnColumnClick (ColumnClickEventArgs e) + protected internal virtual void OnColumnClick (ColumnClickEventArgs e) { ColumnClickEventHandler eh = (ColumnClickEventHandler)(Events [ColumnClickEvent]); if (eh != null) eh (this, e); } -#if NET_2_0 protected internal virtual void OnDrawColumnHeader(DrawListViewColumnHeaderEventArgs e) { DrawListViewColumnHeaderEventHandler eh = (DrawListViewColumnHeaderEventHandler)(Events[DrawColumnHeaderEvent]); @@ -3394,13 +3435,6 @@ namespace System.Windows.Forms eh(this, e); } -#else - protected override void OnEnabledChanged (EventArgs e) - { - base.OnEnabledChanged (e); - } -#endif - protected override void OnFontChanged (EventArgs e) { base.OnFontChanged (e); @@ -3411,9 +3445,7 @@ namespace System.Windows.Forms { base.OnHandleCreated (e); CalculateListView (alignment); -#if NET_2_0 if (!virtual_mode) // Sorting is not allowed in virtual mode -#endif Sort (); } @@ -3436,14 +3468,12 @@ namespace System.Windows.Forms eh (this, ice); } -#if NET_2_0 protected internal virtual void OnItemChecked (ItemCheckedEventArgs e) { ItemCheckedEventHandler eh = (ItemCheckedEventHandler)(Events [ItemCheckedEvent]); if (eh != null) eh (this, e); } -#endif protected virtual void OnItemDrag (ItemDragEventArgs e) { @@ -3452,7 +3482,6 @@ namespace System.Windows.Forms eh (this, e); } -#if NET_2_0 protected virtual void OnItemMouseHover (ListViewItemMouseHoverEventArgs e) { ListViewItemMouseHoverEventHandler eh = (ListViewItemMouseHoverEventHandler)(Events [ItemMouseHoverEvent]); @@ -3477,7 +3506,6 @@ namespace System.Windows.Forms { base.OnParentChanged (e); } -#endif protected virtual void OnSelectedIndexChanged (EventArgs e) { @@ -3491,10 +3519,9 @@ namespace System.Windows.Forms base.OnSystemColorsChanged (e); } -#if NET_2_0 - protected virtual void OnCacheVirtualItems (CacheVirtualItemsEventArgs e) + protected internal virtual void OnCacheVirtualItems (CacheVirtualItemsEventArgs e) { - EventHandler eh = (EventHandler)Events [CacheVirtualItemsEvent]; + CacheVirtualItemsEventHandler eh = (CacheVirtualItemsEventHandler)Events [CacheVirtualItemsEvent]; if (eh != null) eh (this, e); } @@ -3528,7 +3555,6 @@ namespace System.Windows.Forms if (eh != null) eh (this, e); } -#endif protected void RealizeProperties () { @@ -3576,14 +3602,10 @@ namespace System.Windows.Forms public void ArrangeIcons (ListViewAlignment value) { // Icons are arranged only if view is set to LargeIcon or SmallIcon - if (view == View.LargeIcon || view == View.SmallIcon) { - this.CalculateListView (value); - // we have done the calculations already - this.Redraw (false); - } + if (view == View.LargeIcon || view == View.SmallIcon) + Redraw (true); } -#if NET_2_0 public void AutoResizeColumn (int columnIndex, ColumnHeaderAutoResizeStyle headerAutoResize) { if (columnIndex < 0 || columnIndex >= columns.Count) @@ -3599,7 +3621,6 @@ namespace System.Windows.Forms col.AutoResize (headerAutoResize); EndUpdate (); } -#endif public void BeginUpdate () { @@ -3624,11 +3645,17 @@ namespace System.Windows.Forms public void EnsureVisible (int index) { - if (index < 0 || index >= items.Count || scrollable == false) + if (index < 0 || index >= items.Count || scrollable == false || updating) return; Rectangle view_rect = item_control.ClientRectangle; - Rectangle bounds = new Rectangle (GetItemLocation (index), ItemSize); + // Avoid direct access to items in virtual mode, and use item bounds otherwise, since we could have reordered items + Rectangle bounds = virtual_mode ? new Rectangle (GetItemLocation (index), ItemSize) : items [index].Bounds; + + if (view == View.Details && header_style != ColumnHeaderStyle.None) { + view_rect.Y += header_control.Height; + view_rect.Height -= header_control.Height; + } if (view_rect.Contains (bounds)) return; @@ -3640,13 +3667,12 @@ namespace System.Windows.Forms h_scroll.Value += (bounds.Right - view_rect.Right); } - if (bounds.Top < 0) - v_scroll.Value += bounds.Top; + if (bounds.Top < view_rect.Y) + v_scroll.Value += bounds.Top - view_rect.Y; else if (bounds.Bottom > view_rect.Bottom) v_scroll.Value += (bounds.Bottom - view_rect.Bottom); } -#if NET_2_0 public ListViewItem FindItemWithText (string text) { if (items.Count == 0) @@ -3657,10 +3683,15 @@ namespace System.Windows.Forms public ListViewItem FindItemWithText (string text, bool includeSubItemsInSearch, int startIndex) { - return FindItemWithText (text, includeSubItemsInSearch, startIndex, true); + return FindItemWithText (text, includeSubItemsInSearch, startIndex, true, false); } public ListViewItem FindItemWithText (string text, bool includeSubItemsInSearch, int startIndex, bool isPrefixSearch) + { + return FindItemWithText (text, includeSubItemsInSearch, startIndex, isPrefixSearch, false); + } + + internal ListViewItem FindItemWithText (string text, bool includeSubItemsInSearch, int startIndex, bool isPrefixSearch, bool roundtrip) { if (startIndex < 0 || startIndex >= items.Count) throw new ArgumentOutOfRangeException ("startIndex"); @@ -3681,20 +3712,39 @@ namespace System.Windows.Forms return null; } - for (int i = startIndex; i < items.Count; i++) { + int i = startIndex; + while (true) { ListViewItem lvi = items [i]; - if ((isPrefixSearch && lvi.Text.StartsWith (text, true, CultureInfo.CurrentCulture)) // prefix search - || String.Compare (lvi.Text, text, true) == 0) // match + if (isPrefixSearch) { // prefix search + if (CultureInfo.CurrentCulture.CompareInfo.IsPrefix (lvi.Text, text, CompareOptions.IgnoreCase)) + return lvi; + } else if (String.Compare (lvi.Text, text, true) == 0) // match return lvi; + + if (i + 1 >= items.Count) { + if (!roundtrip) + break; + + i = 0; + } else + i++; + + if (i == startIndex) + break; } + // Subitems have a minor priority, so we have to do a second linear search + // Also, we don't need to to a roundtrip search for them by now if (includeSubItemsInSearch) { - for (int i = startIndex; i < items.Count; i++) { + for (i = startIndex; i < items.Count; i++) { ListViewItem lvi = items [i]; foreach (ListViewItem.ListViewSubItem sub_item in lvi.SubItems) - if ((isPrefixSearch && sub_item.Text.StartsWith (text, true, CultureInfo.CurrentCulture)) - || String.Compare (sub_item.Text, text, true) == 0) + if (isPrefixSearch) { + if (CultureInfo.CurrentCulture.CompareInfo.IsPrefix (sub_item.Text, + text, CompareOptions.IgnoreCase)) + return lvi; + } else if (String.Compare (sub_item.Text, text, true) == 0) return lvi; } } @@ -3778,7 +3828,6 @@ namespace System.Windows.Forms return item; } -#endif public ListViewItem GetItemAt (int x, int y) { @@ -3806,7 +3855,6 @@ namespace System.Windows.Forms return items [index].GetBounds (portion); } -#if NET_2_0 public ListViewHitTestInfo HitTest (Point point) { return HitTest (point.X, point.Y); @@ -3856,19 +3904,16 @@ namespace System.Windows.Forms return; for (int i = startIndex; i <= endIndex; i++) - item_control.Invalidate (items [i].Bounds); + items [i].Invalidate (); if (!invalidateOnly) Update (); } -#endif public void Sort () { -#if NET_2_0 if (virtual_mode) throw new InvalidOperationException (); -#endif Sort (true); } @@ -3907,7 +3952,7 @@ namespace System.Windows.Forms #region Subclasses - class HeaderControl : Control { + internal class HeaderControl : Control { ListView owner; bool column_resize_active = false; @@ -3916,13 +3961,41 @@ namespace System.Windows.Forms ColumnHeader drag_column; int drag_x; int drag_to_index = -1; + ColumnHeader entered_column_header; public HeaderControl (ListView owner) { this.owner = owner; + this.SetStyle (ControlStyles.DoubleBuffer, true); MouseDown += new MouseEventHandler (HeaderMouseDown); MouseMove += new MouseEventHandler (HeaderMouseMove); MouseUp += new MouseEventHandler (HeaderMouseUp); + MouseLeave += new EventHandler (OnMouseLeave); + } + + internal ColumnHeader EnteredColumnHeader { + get { return entered_column_header; } + private set { + if (entered_column_header == value) + return; + if (ThemeEngine.Current.ListViewHasHotHeaderStyle) { + Region region_to_invalidate = new Region (); + region_to_invalidate.MakeEmpty (); + if (entered_column_header != null) + region_to_invalidate.Union (GetColumnHeaderInvalidateArea (entered_column_header)); + entered_column_header = value; + if (entered_column_header != null) + region_to_invalidate.Union (GetColumnHeaderInvalidateArea (entered_column_header)); + Invalidate (region_to_invalidate); + region_to_invalidate.Dispose (); + } else + entered_column_header = value; + } + } + + void OnMouseLeave (object sender, EventArgs e) + { + EnteredColumnHeader = null; } private ColumnHeader ColumnAtX (int x) @@ -3968,13 +4041,23 @@ namespace System.Windows.Forms drag_to_index = GetReorderedIndex (clicked_column); } clicked_column.Pressed = true; - Rectangle bounds = clicked_column.Rect; - bounds.X -= owner.h_marker; - Invalidate (bounds); + Invalidate (clicked_column); return; } } + void Invalidate (ColumnHeader columnHeader) + { + Invalidate (GetColumnHeaderInvalidateArea (columnHeader)); + } + + Rectangle GetColumnHeaderInvalidateArea (ColumnHeader columnHeader) + { + Rectangle bounds = columnHeader.Rect; + bounds.X -= owner.h_marker; + return bounds; + } + void StopResize () { column_resize_active = false; @@ -4023,17 +4106,16 @@ namespace System.Windows.Forms ColumnHeader over = ColumnAtX (me.X + owner.h_marker); bool pressed = clicked_column.Pressed; clicked_column.Pressed = over == clicked_column; - if (clicked_column.Pressed ^ pressed) { - Rectangle bounds = clicked_column.Rect; - bounds.X -= owner.h_marker; - Invalidate (bounds); - } + if (clicked_column.Pressed ^ pressed) + Invalidate (clicked_column); } return; } for (int i = 0; i < owner.Columns.Count; i++) { Rectangle zone = owner.Columns [i].Rect; + if (zone.Contains (pt)) + EnteredColumnHeader = owner.Columns [i]; zone.X = zone.Right - 5; zone.Width = 10; if (zone.Contains (pt)) { @@ -4063,9 +4145,7 @@ namespace System.Windows.Forms if (clicked_column != null && clicked_column.Pressed) { clicked_column.Pressed = false; - Rectangle bounds = clicked_column.Rect; - bounds.X -= owner.h_marker; - Invalidate (bounds); + Invalidate (clicked_column); owner.OnColumnClick (new ColumnClickEventArgs (clicked_column.Index)); } @@ -4133,9 +4213,7 @@ namespace System.Windows.Forms } } -#if NET_2_0 [ListBindable (false)] -#endif public class CheckedIndexCollection : IList, ICollection, IEnumerable { private readonly ListView owner; @@ -4269,9 +4347,7 @@ namespace System.Windows.Forms } } // CheckedIndexCollection -#if NET_2_0 [ListBindable (false)] -#endif public class CheckedListViewItemCollection : IList, ICollection, IEnumerable { private readonly ListView owner; @@ -4302,10 +4378,8 @@ namespace System.Windows.Forms public ListViewItem this [int index] { get { -#if NET_2_0 if (owner.VirtualMode) throw new InvalidOperationException (); -#endif ArrayList checked_items = List; if (index < 0 || index >= checked_items.Count) throw new ArgumentOutOfRangeException ("index"); @@ -4313,14 +4387,12 @@ namespace System.Windows.Forms } } -#if NET_2_0 public virtual ListViewItem this [string key] { get { int idx = IndexOfKey (key); return idx == -1 ? null : (ListViewItem) List [idx]; } } -#endif bool ICollection.IsSynchronized { get { return false; } @@ -4348,19 +4420,15 @@ namespace System.Windows.Forms return List.Contains (item); } -#if NET_2_0 public virtual bool ContainsKey (string key) { return IndexOfKey (key) != -1; } -#endif public void CopyTo (Array dest, int index) { -#if NET_2_0 if (owner.VirtualMode) throw new InvalidOperationException (); -#endif if (!owner.CheckBoxes) return; List.CopyTo (dest, index); @@ -4368,10 +4436,8 @@ namespace System.Windows.Forms public IEnumerator GetEnumerator () { -#if NET_2_0 if (owner.VirtualMode) throw new InvalidOperationException (); -#endif if (!owner.CheckBoxes) return (new ListViewItem [0]).GetEnumerator (); return List.GetEnumerator (); @@ -4418,22 +4484,17 @@ namespace System.Windows.Forms public int IndexOf (ListViewItem item) { -#if NET_2_0 if (owner.VirtualMode) throw new InvalidOperationException (); -#endif if (!owner.CheckBoxes) return -1; return List.IndexOf (item); } -#if NET_2_0 public virtual int IndexOfKey (string key) { -#if NET_2_0 if (owner.VirtualMode) throw new InvalidOperationException (); -#endif if (key == null || key.Length == 0) return -1; @@ -4446,7 +4507,6 @@ namespace System.Windows.Forms return -1; } -#endif #endregion // Public Methods internal ArrayList List { @@ -4474,14 +4534,44 @@ namespace System.Windows.Forms } } // CheckedListViewItemCollection -#if NET_2_0 [ListBindable (false)] -#endif public class ColumnHeaderCollection : IList, ICollection, IEnumerable { internal ArrayList list; private ListView owner; + #region UIA Framework Events + //NOTE: + // We are using Reflection to add/remove internal events. + // Class ListViewProvider uses the events when View is Details. + // + //Event used to generate UIA StructureChangedEvent + static object UIACollectionChangedEvent = new object (); + + internal event CollectionChangeEventHandler UIACollectionChanged { + add { + if (owner != null) + owner.Events.AddHandler (UIACollectionChangedEvent, value); + } + remove { + if (owner != null) + owner.Events.RemoveHandler (UIACollectionChangedEvent, value); + } + } + + internal void OnUIACollectionChangedEvent (CollectionChangeEventArgs args) + { + if (owner == null) + return; + + CollectionChangeEventHandler eh + = (CollectionChangeEventHandler) owner.Events [UIACollectionChangedEvent]; + if (eh != null) + eh (owner, args); + } + + #endregion UIA Framework Events + #region Public Constructor public ColumnHeaderCollection (ListView owner) { @@ -4508,7 +4598,6 @@ namespace System.Windows.Forms } } -#if NET_2_0 public virtual ColumnHeader this [string key] { get { int idx = IndexOfKey (key); @@ -4518,7 +4607,6 @@ namespace System.Windows.Forms return (ColumnHeader) list [idx]; } } -#endif bool ICollection.IsSynchronized { get { return true; } @@ -4543,23 +4631,21 @@ namespace System.Windows.Forms { int idx = list.Add (value); owner.AddColumn (value, idx, true); + + //UIA Framework event: Item Added + OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, value)); + return idx; } -#if NET_2_0 public virtual ColumnHeader Add (string text, int width, HorizontalAlignment textAlign) { string str = text; -#else - public virtual ColumnHeader Add (string str, int width, HorizontalAlignment textAlign) - { -#endif ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width); this.Add (colHeader); return colHeader; } -#if NET_2_0 public virtual ColumnHeader Add (string text) { return Add (String.Empty, text); @@ -4599,7 +4685,6 @@ namespace System.Windows.Forms Add (colHeader); return colHeader; } -#endif public virtual void AddRange (ColumnHeader [] values) { @@ -4617,6 +4702,10 @@ namespace System.Windows.Forms col.SetListView (null); list.Clear (); owner.ReorderColumns (new int [0], true); + + //UIA Framework event: Items cleared + OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Refresh, null)); + } public bool Contains (ColumnHeader value) @@ -4624,12 +4713,10 @@ namespace System.Windows.Forms return list.Contains (value); } -#if NET_2_0 public virtual bool ContainsKey (string key) { return IndexOfKey (key) != -1; } -#endif public IEnumerator GetEnumerator () { @@ -4691,7 +4778,6 @@ namespace System.Windows.Forms return list.IndexOf (value); } -#if NET_2_0 public virtual int IndexOfKey (string key) { if (key == null || key.Length == 0) @@ -4705,7 +4791,6 @@ namespace System.Windows.Forms return -1; } -#endif public void Insert (int index, ColumnHeader value) { @@ -4716,9 +4801,11 @@ namespace System.Windows.Forms list.Insert (index, value); owner.AddColumn (value, index, true); + + //UIA Framework event: Item added + OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, value)); } -#if NET_2_0 public void Insert (int index, string text) { Insert (index, String.Empty, text); @@ -4756,16 +4843,10 @@ namespace System.Windows.Forms colHeader.ImageKey = imageKey; Insert (index, colHeader); } -#endif -#if NET_2_0 public void Insert (int index, string text, int width, HorizontalAlignment textAlign) { string str = text; -#else - public void Insert (int index, string str, int width, HorizontalAlignment textAlign) - { -#endif ColumnHeader colHeader = new ColumnHeader (this.owner, str, textAlign, width); this.Insert (index, colHeader); } @@ -4792,16 +4873,17 @@ namespace System.Windows.Forms column.InternalDisplayIndex = -1; owner.ReorderColumns (display_indices, true); + + //UIA Framework event: Item Removed + OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Remove, column)); } -#if NET_2_0 public virtual void RemoveByKey (string key) { int idx = IndexOfKey (key); if (idx != -1) RemoveAt (idx); } -#endif public virtual void RemoveAt (int index) { @@ -4816,16 +4898,44 @@ namespace System.Windows.Forms } // ColumnHeaderCollection -#if NET_2_0 [ListBindable (false)] -#endif public class ListViewItemCollection : IList, ICollection, IEnumerable { private readonly ArrayList list; private ListView owner; -#if NET_2_0 private ListViewGroup group; -#endif + + #region UIA Framework Events + //NOTE: + // We are using Reflection to add/remove internal events. + // Class ListViewProvider uses the events. + // + //Event used to generate UIA StructureChangedEvent + static object UIACollectionChangedEvent = new object (); + + internal event CollectionChangeEventHandler UIACollectionChanged { + add { + if (owner != null) + owner.Events.AddHandler (UIACollectionChangedEvent, value); + } + remove { + if (owner != null) + owner.Events.RemoveHandler (UIACollectionChangedEvent, value); + } + } + + internal void OnUIACollectionChangedEvent (CollectionChangeEventArgs args) + { + if (owner == null) + return; + + CollectionChangeEventHandler eh + = (CollectionChangeEventHandler) owner.Events [UIACollectionChangedEvent]; + if (eh != null) + eh (owner, args); + } + + #endregion UIA Framework Events // The collection can belong to a ListView (main) or to a ListViewGroup (sub-collection) // In the later case ListViewItem.ListView never gets modified @@ -4839,22 +4949,18 @@ namespace System.Windows.Forms } #endregion // Public Constructor -#if NET_2_0 internal ListViewItemCollection (ListView owner, ListViewGroup group) : this (owner) { this.group = group; is_main_collection = false; } -#endif #region Public Properties [Browsable (false)] public int Count { get { -#if NET_2_0 if (owner != null && owner.VirtualMode) return owner.VirtualListSize; -#endif return list.Count; } @@ -4864,38 +4970,22 @@ namespace System.Windows.Forms get { return false; } } -#if NET_2_0 public virtual ListViewItem this [int index] { -#else - public virtual ListViewItem this [int displayIndex] { -#endif get { -#if !NET_2_0 - int index = displayIndex; -#endif - if (index < 0 || index >= Count) throw new ArgumentOutOfRangeException ("index"); -#if NET_2_0 if (owner != null && owner.VirtualMode) return RetrieveVirtualItemFromOwner (index); -#endif return (ListViewItem) list [index]; } set { -#if !NET_2_0 - int index = displayIndex; -#endif - if (index < 0 || index >= Count) throw new ArgumentOutOfRangeException ("index"); -#if NET_2_0 if (owner != null && owner.VirtualMode) throw new InvalidOperationException (); -#endif if (list.Contains (value)) throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "value"); @@ -4905,21 +4995,26 @@ namespace System.Windows.Forms if (is_main_collection) value.Owner = owner; -#if NET_2_0 else { if (value.Group != null) value.Group.Items.Remove (value); value.SetGroup (group); } -#endif + + //UIA Framework event: Item Replaced + OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Remove, list [index])); list [index] = value; + CollectionChanged (true); + + //UIA Framework event: Item Replaced + OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, value)); + } } -#if NET_2_0 public virtual ListViewItem this [string key] { get { int idx = IndexOfKey (key); @@ -4929,7 +5024,6 @@ namespace System.Windows.Forms return this [idx]; } } -#endif bool ICollection.IsSynchronized { get { return true; } @@ -4946,11 +5040,17 @@ namespace System.Windows.Forms object IList.this [int index] { get { return this [index]; } set { + //UIA Framework event: Item Replaced + OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Remove, this [index])); + if (value is ListViewItem) this [index] = (ListViewItem) value; else this [index] = new ListViewItem (value.ToString ()); + OnChange (); + //UIA Framework event: Item Replaced + OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, value)); } } #endregion // Public Properties @@ -4958,10 +5058,8 @@ namespace System.Windows.Forms #region Public Methods public virtual ListViewItem Add (ListViewItem value) { -#if NET_2_0 if (owner != null && owner.VirtualMode) throw new InvalidOperationException (); -#endif AddItem (value); @@ -4969,6 +5067,9 @@ namespace System.Windows.Forms if (is_main_collection || value.ListView != null) CollectionChanged (true); + //UIA Framework event: Item Added + OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, value)); + return value; } @@ -4984,7 +5085,6 @@ namespace System.Windows.Forms return this.Add (item); } -#if NET_2_0 public virtual ListViewItem Add (string text, string imageKey) { ListViewItem item = new ListViewItem (text, imageKey); @@ -5004,30 +5104,28 @@ namespace System.Windows.Forms item.Name = key; return this.Add (item); } -#endif -#if NET_2_0 public void AddRange (ListViewItem [] items) { -#else - public void AddRange (ListViewItem [] values) - { - ListViewItem [] items = values; -#endif if (items == null) throw new ArgumentNullException ("Argument cannot be null!", "items"); -#if NET_2_0 if (owner != null && owner.VirtualMode) throw new InvalidOperationException (); -#endif - foreach (ListViewItem item in items) + owner.BeginUpdate (); + + foreach (ListViewItem item in items) { AddItem (item); + //UIA Framework event: Item Added + OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, item)); + } + + owner.EndUpdate (); + CollectionChanged (true); } -#if NET_2_0 public void AddRange (ListViewItemCollection items) { if (items == null) @@ -5037,32 +5135,55 @@ namespace System.Windows.Forms items.CopyTo (itemArray,0); this.AddRange (itemArray); } -#endif public virtual void Clear () { -#if NET_2_0 if (owner != null && owner.VirtualMode) throw new InvalidOperationException (); -#endif if (is_main_collection && owner != null) { owner.SetFocusedItem (-1); owner.h_scroll.Value = owner.v_scroll.Value = 0; - + + // first remove any item in the groups that *are* part of this LV too + foreach (ListViewGroup group in owner.groups) + group.Items.ClearItemsWithSameListView (); + foreach (ListViewItem item in list) { owner.item_control.CancelEdit (item); item.Owner = null; } - } -#if NET_2_0 else foreach (ListViewItem item in list) item.SetGroup (null); -#endif list.Clear (); CollectionChanged (false); + + //UIA Framework event: Items Removed + OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Refresh, null)); + + } + + // This method is intended to be used from ListViewGroup.Items, not from ListView.Items, + // added for performance reasons (avoid calling manually Remove for every item on ListViewGroup.Items) + void ClearItemsWithSameListView () + { + if (is_main_collection) + return; + + int counter = list.Count - 1; + while (counter >= 0) { + ListViewItem item = list [counter] as ListViewItem; + + // remove only if the items in group have being added to the ListView too + if (item.ListView == group.ListView) { + list.RemoveAt (counter); + item.SetGroup (null); + } + + counter--; + } } public bool Contains (ListViewItem item) @@ -5070,19 +5191,16 @@ namespace System.Windows.Forms return IndexOf (item) != -1; } -#if NET_2_0 public virtual bool ContainsKey (string key) { return IndexOfKey (key) != -1; } -#endif public void CopyTo (Array dest, int index) { list.CopyTo (dest, index); } -#if NET_2_0 public ListViewItem [] Find (string key, bool searchAllSubItems) { if (key == null) @@ -5101,16 +5219,15 @@ namespace System.Windows.Forms return retval; } -#endif public IEnumerator GetEnumerator () { -#if NET_2_0 if (owner != null && owner.VirtualMode) throw new InvalidOperationException (); -#endif - - return list.GetEnumerator (); + + // This enumerator makes a copy of the collection so + // it can be deleted from in a foreach + return new Control.ControlCollection.ControlCollectionEnumerator (list); } int IList.Add (object item) @@ -5118,10 +5235,8 @@ namespace System.Windows.Forms int result; ListViewItem li; -#if NET_2_0 if (owner != null && owner.VirtualMode) throw new InvalidOperationException (); -#endif if (item is ListViewItem) { li = (ListViewItem) item; @@ -5135,9 +5250,14 @@ namespace System.Windows.Forms li = new ListViewItem (item.ToString ()); li.Owner = owner; + + result = list.Add (li); CollectionChanged (true); + //UIA Framework event: Item Added + OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, li)); + return result; } @@ -5157,6 +5277,9 @@ namespace System.Windows.Forms this.Insert (index, (ListViewItem) item); else this.Insert (index, item.ToString ()); + + //UIA Framework event: Item Added + OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, this [index])); } void IList.Remove (object item) @@ -5166,7 +5289,6 @@ namespace System.Windows.Forms public int IndexOf (ListViewItem item) { -#if NET_2_0 if (owner != null && owner.VirtualMode) { for (int i = 0; i < Count; i++) if (RetrieveVirtualItemFromOwner (i) == item) @@ -5174,12 +5296,10 @@ namespace System.Windows.Forms return -1; } -#endif return list.IndexOf (item); } -#if NET_2_0 public virtual int IndexOfKey (string key) { if (key == null || key.Length == 0) @@ -5193,17 +5313,14 @@ namespace System.Windows.Forms return -1; } -#endif public ListViewItem Insert (int index, ListViewItem item) { if (index < 0 || index > list.Count) throw new ArgumentOutOfRangeException ("index"); -#if NET_2_0 if (owner != null && owner.VirtualMode) throw new InvalidOperationException (); -#endif if (list.Contains (item)) throw new ArgumentException ("An item cannot be added more than once. To add an item again, you need to clone it.", "item"); @@ -5213,20 +5330,24 @@ namespace System.Windows.Forms if (is_main_collection) item.Owner = owner; -#if NET_2_0 else { if (item.Group != null) item.Group.Items.Remove (item); item.SetGroup (group); } -#endif list.Insert (index, item); if (is_main_collection || item.ListView != null) CollectionChanged (true); + // force an update of the selected info if the new item is selected. + if (item.Selected) + item.SetSelectedCore (true); + //UIA Framework event: Item Added + OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Add, item)); + return item; } @@ -5240,7 +5361,6 @@ namespace System.Windows.Forms return this.Insert (index, new ListViewItem (text, imageIndex)); } -#if NET_2_0 public ListViewItem Insert (int index, string text, string imageKey) { ListViewItem lvi = new ListViewItem (text, imageKey); @@ -5260,14 +5380,11 @@ namespace System.Windows.Forms lvi.Name = key; return Insert (index, lvi); } -#endif public virtual void Remove (ListViewItem item) { -#if NET_2_0 if (owner != null && owner.VirtualMode) throw new InvalidOperationException (); -#endif int idx = list.IndexOf (item); if (idx != -1) @@ -5279,10 +5396,8 @@ namespace System.Windows.Forms if (index < 0 || index >= Count) throw new ArgumentOutOfRangeException ("index"); -#if NET_2_0 if (owner != null && owner.VirtualMode) throw new InvalidOperationException (); -#endif ListViewItem item = (ListViewItem) list [index]; @@ -5299,26 +5414,28 @@ namespace System.Windows.Forms list.RemoveAt (index); - if (is_main_collection) + if (is_main_collection) { item.Owner = null; -#if NET_2_0 - else + if (item.Group != null) + item.Group.Items.Remove (item); + } else item.SetGroup (null); -#endif CollectionChanged (false); if (selection_changed && owner != null) owner.OnSelectedIndexChanged (EventArgs.Empty); + + + //UIA Framework event: Item Removed + OnUIACollectionChangedEvent (new CollectionChangeEventArgs (CollectionChangeAction.Remove, item)); } -#if NET_2_0 public virtual void RemoveByKey (string key) { int idx = IndexOfKey (key); if (idx != -1) RemoveAt (idx); } -#endif #endregion // Public Methods @@ -5331,7 +5448,6 @@ namespace System.Windows.Forms } } -#if NET_2_0 internal ListViewGroup Group { get { return group; @@ -5340,7 +5456,6 @@ namespace System.Windows.Forms group = value; } } -#endif void AddItem (ListViewItem value) { @@ -5351,30 +5466,31 @@ namespace System.Windows.Forms throw new ArgumentException ("Cannot add or insert the item '" + value.Text + "' in more than one place. You must first remove it from its current location or clone it.", "value"); if (is_main_collection) value.Owner = owner; -#if NET_2_0 else { if (value.Group != null) value.Group.Items.Remove (value); value.SetGroup (group); } -#endif list.Add (value); + + // force an update of the selected info if the new item is selected. + if (value.Selected) + value.SetSelectedCore (true); } void CollectionChanged (bool sort) { if (owner != null) { - if (sort) - owner.Sort (false); + if (sort) + owner.Sort (false); OnChange (); owner.Redraw (true); } } -#if NET_2_0 ListViewItem RetrieveVirtualItemFromOwner (int displayIndex) { RetrieveVirtualItemEventArgs args = new RetrieveVirtualItemEventArgs (displayIndex); @@ -5383,10 +5499,10 @@ namespace System.Windows.Forms ListViewItem retval = args.Item; retval.Owner = owner; retval.DisplayIndex = displayIndex; + retval.Layout (); return retval; } -#endif internal event CollectionChangedHandler Changed; @@ -5409,9 +5525,7 @@ namespace System.Windows.Forms // // In virtual mode, SelectedIndexCollection directly saves the selection // information, instead of getting it from Items, making List read-and-write -#if NET_2_0 [ListBindable (false)] -#endif public class SelectedIndexCollection : IList, ICollection, IEnumerable { private readonly ListView owner; @@ -5429,7 +5543,7 @@ namespace System.Windows.Forms [Browsable (false)] public int Count { get { - if (!owner.IsHandleCreated) + if (!owner.is_selection_available) return 0; return List.Count; @@ -5438,17 +5552,13 @@ namespace System.Windows.Forms public bool IsReadOnly { get { -#if NET_2_0 return false; -#else - return true; -#endif } } public int this [int index] { get { - if (!owner.IsHandleCreated || index < 0 || index >= List.Count) + if (!owner.is_selection_available || index < 0 || index >= List.Count) throw new ArgumentOutOfRangeException ("index"); return (int) List [index]; @@ -5465,11 +5575,7 @@ namespace System.Windows.Forms bool IList.IsFixedSize { get { -#if NET_2_0 return false; -#else - return true; -#endif } } @@ -5480,32 +5586,25 @@ namespace System.Windows.Forms #endregion // Public Properties #region Public Methods -#if NET_2_0 public int Add (int itemIndex) { if (itemIndex < 0 || itemIndex >= owner.Items.Count) throw new ArgumentOutOfRangeException ("index"); - if (owner.virtual_mode && !owner.IsHandleCreated) + if (owner.virtual_mode && !owner.is_selection_available) return -1; owner.Items [itemIndex].Selected = true; - if (!owner.IsHandleCreated) + if (!owner.is_selection_available) return 0; return List.Count; } -#endif -#if NET_2_0 - public -#else - internal -#endif - void Clear () + public void Clear () { - if (!owner.IsHandleCreated) + if (!owner.is_selection_available) return; int [] indexes = (int []) List.ToArray (typeof (int)); @@ -5569,13 +5668,12 @@ namespace System.Windows.Forms public int IndexOf (int selectedIndex) { - if (!owner.IsHandleCreated) + if (!owner.is_selection_available) return -1; return List.IndexOf (selectedIndex); } -#if NET_2_0 public void Remove (int itemIndex) { if (itemIndex < 0 || itemIndex >= owner.Items.Count) @@ -5583,16 +5681,13 @@ namespace System.Windows.Forms owner.Items [itemIndex].Selected = false; } -#endif #endregion // Public Methods internal ArrayList List { get { if (list == null) { list = new ArrayList (); -#if NET_2_0 if (!owner.VirtualMode) -#endif for (int i = 0; i < owner.Items.Count; i++) { if (owner.Items [i].Selected) list.Add (i); @@ -5613,7 +5708,6 @@ namespace System.Windows.Forms Reset (); } -#if NET_2_0 internal void RemoveIndex (int index) { int idx = List.BinarySearch (index); @@ -5641,13 +5735,10 @@ namespace System.Windows.Forms List.Insert (iMin, index); } -#endif } // SelectedIndexCollection -#if NET_2_0 [ListBindable (false)] -#endif public class SelectedListViewItemCollection : IList, ICollection, IEnumerable { private readonly ListView owner; @@ -5673,7 +5764,7 @@ namespace System.Windows.Forms public ListViewItem this [int index] { get { - if (!owner.IsHandleCreated || index < 0 || index >= Count) + if (!owner.is_selection_available || index < 0 || index >= Count) throw new ArgumentOutOfRangeException ("index"); int item_index = owner.SelectedIndices [index]; @@ -5681,7 +5772,6 @@ namespace System.Windows.Forms } } -#if NET_2_0 public virtual ListViewItem this [string key] { get { int idx = IndexOfKey (key); @@ -5691,7 +5781,6 @@ namespace System.Windows.Forms return this [idx]; } } -#endif bool ICollection.IsSynchronized { get { return false; } @@ -5722,16 +5811,14 @@ namespace System.Windows.Forms return IndexOf (item) != -1; } -#if NET_2_0 public virtual bool ContainsKey (string key) { return IndexOfKey (key) != -1; } -#endif public void CopyTo (Array dest, int index) { - if (!owner.IsHandleCreated) + if (!owner.is_selection_available) return; if (index > Count) // Throws ArgumentException instead of IOOR exception throw new ArgumentException ("index"); @@ -5742,7 +5829,7 @@ namespace System.Windows.Forms public IEnumerator GetEnumerator () { - if (!owner.IsHandleCreated) + if (!owner.is_selection_available) return (new ListViewItem [0]).GetEnumerator (); ListViewItem [] items = new ListViewItem [Count]; @@ -5788,7 +5875,7 @@ namespace System.Windows.Forms public int IndexOf (ListViewItem item) { - if (!owner.IsHandleCreated) + if (!owner.is_selection_available) return -1; for (int i = 0; i < Count; i++) @@ -5798,10 +5885,9 @@ namespace System.Windows.Forms return -1; } -#if NET_2_0 public virtual int IndexOfKey (string key) { - if (!owner.IsHandleCreated || key == null || key.Length == 0) + if (!owner.is_selection_available || key == null || key.Length == 0) return -1; for (int i = 0; i < Count; i++) { @@ -5812,7 +5898,6 @@ namespace System.Windows.Forms return -1; } -#endif #endregion // Public Methods } // SelectedListViewItemCollection @@ -5852,7 +5937,6 @@ namespace System.Windows.Forms } #endregion // Subclasses -#if NET_2_0 protected override void OnResize (EventArgs e) { base.OnResize (e); @@ -5932,18 +6016,131 @@ namespace System.Windows.Forms cwceh (this, changing); return !changing.Cancel; } -#else - // - // 1.0 profile based implementation - // - bool CanProceedWithResize (ColumnHeader col, int width) + + internal void RaiseColumnWidthChanged (ColumnHeader column) { - return true; + int index = Columns.IndexOf (column); + RaiseColumnWidthChanged (index); } - void RaiseColumnWidthChanged (int resize_column) + + #region UIA Framework: Methods, Properties and Events + + static object UIALabelEditChangedEvent = new object (); + static object UIAShowGroupsChangedEvent = new object (); + static object UIAMultiSelectChangedEvent = new object (); + static object UIAViewChangedEvent = new object (); + static object UIACheckBoxesChangedEvent = new object (); + static object UIAFocusedItemChangedEvent = new object (); + + internal Rectangle UIAHeaderControl { + get { return header_control.Bounds; } + } + + internal int UIAColumns { + get { return cols; } + } + + internal int UIARows { + get { return rows; } + } + + internal ListViewGroup UIADefaultListViewGroup + { + get { return groups.DefaultGroup; } + } + + internal ScrollBar UIAHScrollBar { + get { return h_scroll; } + } + + internal ScrollBar UIAVScrollBar { + get { return v_scroll; } + } + + internal event EventHandler UIAShowGroupsChanged { + add { Events.AddHandler (UIAShowGroupsChangedEvent, value); } + remove { Events.RemoveHandler (UIAShowGroupsChangedEvent, value); } + } + + internal event EventHandler UIACheckBoxesChanged { + add { Events.AddHandler (UIACheckBoxesChangedEvent, value); } + remove { Events.RemoveHandler (UIACheckBoxesChangedEvent, value); } + } + + internal event EventHandler UIAMultiSelectChanged { + add { Events.AddHandler (UIAMultiSelectChangedEvent, value); } + remove { Events.RemoveHandler (UIAMultiSelectChangedEvent, value); } + } + + internal event EventHandler UIALabelEditChanged { + add { Events.AddHandler (UIALabelEditChangedEvent, value); } + remove { Events.RemoveHandler (UIALabelEditChangedEvent, value); } + } + + internal event EventHandler UIAViewChanged { + add { Events.AddHandler (UIAViewChangedEvent, value); } + remove { Events.RemoveHandler (UIAViewChangedEvent, value); } + } + + internal event EventHandler UIAFocusedItemChanged { + add { Events.AddHandler (UIAFocusedItemChangedEvent, value); } + remove { Events.RemoveHandler (UIAFocusedItemChangedEvent, value); } + } + + internal Rectangle UIAGetHeaderBounds (ListViewGroup group) + { + return group.HeaderBounds; + } + + internal int UIAItemsLocationLength + { + get { return items_location.Length; } + } + + private void OnUIACheckBoxesChanged () { + EventHandler eh = (EventHandler) Events [UIACheckBoxesChangedEvent]; + if (eh != null) + eh (this, EventArgs.Empty); } -#endif + + private void OnUIAShowGroupsChanged () + { + EventHandler eh = (EventHandler) Events [UIAShowGroupsChangedEvent]; + if (eh != null) + eh (this, EventArgs.Empty); + } + + private void OnUIAMultiSelectChanged () + { + EventHandler eh = (EventHandler) Events [UIAMultiSelectChangedEvent]; + if (eh != null) + eh (this, EventArgs.Empty); + } + + private void OnUIALabelEditChanged () + { + EventHandler eh = (EventHandler) Events [UIALabelEditChangedEvent]; + if (eh != null) + eh (this, EventArgs.Empty); + } + + private void OnUIAViewChanged () + { + EventHandler eh = (EventHandler) Events [UIAViewChangedEvent]; + if (eh != null) + eh (this, EventArgs.Empty); + } + + internal void OnUIAFocusedItemChanged () + { + EventHandler eh = (EventHandler) Events [UIAFocusedItemChangedEvent]; + if (eh != null) + eh (this, EventArgs.Empty); + } + + #endregion // UIA Framework: Methods, Properties and Events + } }