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:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
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.
20 // Copyright (c) 2004 Novell, Inc. (http://www.novell.com)
23 // Ravindra (rkumar@novell.com)
24 // Mike Kestner <mkestner@novell.com>
25 // Daniel Nauck (dna(at)mono-project(dot)de)
27 using System.Collections;
28 using System.ComponentModel;
30 using System.Runtime.Serialization;
32 namespace System.Windows.Forms
34 [DefaultProperty ("Text")]
35 [DesignTimeVisible (false)]
38 [TypeConverter (typeof (ListViewItemConverter))]
39 public class ListViewItem : ICloneable, ISerializable
41 #region Instance Variables
42 private int image_index = -1;
43 private bool is_checked = false;
44 private int state_image_index = -1;
45 private ListViewSubItemCollection sub_items;
47 private bool use_item_style = true;
48 int display_index = -1; // actual position in ListView
49 private ListViewGroup group = null;
50 private string name = String.Empty;
51 private string image_key = String.Empty;
52 string tooltip_text = String.Empty;
54 Point position = new Point (-1, -1); // cached to mimic .Net behaviour
55 Rectangle bounds = Rectangle.Empty;
56 Rectangle checkbox_rect; // calculated by CalcListViewItem method
62 Font hot_font; // cached font for hot tracking
69 #region UIA Framework: Methods, Properties and Events
71 internal event EventHandler UIATextChanged;
73 internal event LabelEditEventHandler UIASubItemTextChanged;
75 internal void OnUIATextChanged ()
77 if (UIATextChanged != null)
78 UIATextChanged (this, EventArgs.Empty);
81 internal void OnUIASubItemTextChanged (LabelEditEventArgs args)
83 //If our index is 0 we also generate TextChanged for the ListViewItem
84 //because ListViewItem.Text is the same as ListViewItem.SubItems [0].Text
88 if (UIASubItemTextChanged != null)
89 UIASubItemTextChanged (this, args);
92 #endregion // UIA Framework: Methods, Properties and Events
95 #endregion Instance Variables
97 #region Public Constructors
98 public ListViewItem () : this (string.Empty)
102 public ListViewItem (string text) : this (text, -1)
106 public ListViewItem (string [] items) : this (items, -1)
110 public ListViewItem (ListViewItem.ListViewSubItem [] subItems, int imageIndex)
112 this.sub_items = new ListViewSubItemCollection (this, null);
113 for (int i = 0; i < subItems.Length; i++)
114 sub_items.Add (subItems [i]);
115 this.image_index = imageIndex;
118 public ListViewItem (string text, int imageIndex)
120 this.image_index = imageIndex;
121 this.sub_items = new ListViewSubItemCollection (this, text);
124 public ListViewItem (string [] items, int imageIndex)
126 this.sub_items = new ListViewSubItemCollection (this, null);
128 for (int i = 0; i < items.Length; i++)
129 sub_items.Add (new ListViewSubItem (this, items [i]));
131 this.image_index = imageIndex;
134 public ListViewItem (string [] items, int imageIndex, Color foreColor,
135 Color backColor, Font font) : this (items, imageIndex)
137 ForeColor = foreColor;
138 BackColor = backColor;
142 public ListViewItem(string[] items, string imageKey) : this(items)
144 this.ImageKey = imageKey;
147 public ListViewItem(string text, string imageKey) : this(text)
149 this.ImageKey = imageKey;
152 public ListViewItem(ListViewSubItem[] subItems, string imageKey)
154 this.sub_items = new ListViewSubItemCollection (this, null);
155 for (int i = 0; i < subItems.Length; i++)
156 this.sub_items.Add (subItems [i]);
157 this.ImageKey = imageKey;
160 public ListViewItem(string[] items, string imageKey, Color foreColor,
161 Color backColor, Font font) : this(items, imageKey)
163 ForeColor = foreColor;
164 BackColor = backColor;
168 public ListViewItem(ListViewGroup group) : this()
173 public ListViewItem(string text, ListViewGroup group) : this(text)
178 public ListViewItem(string[] items, ListViewGroup group) : this(items)
183 public ListViewItem(ListViewSubItem[] subItems, int imageIndex, ListViewGroup group)
184 : this(subItems, imageIndex)
189 public ListViewItem(ListViewSubItem[] subItems, string imageKey, ListViewGroup group)
190 : this(subItems, imageKey)
195 public ListViewItem(string text, int imageIndex, ListViewGroup group)
196 : this(text, imageIndex)
201 public ListViewItem(string text, string imageKey, ListViewGroup group)
202 : this(text, imageKey)
207 public ListViewItem(string[] items, int imageIndex, ListViewGroup group)
208 : this(items, imageIndex)
213 public ListViewItem(string[] items, string imageKey, ListViewGroup group)
214 : this(items, imageKey)
219 public ListViewItem(string[] items, int imageIndex, Color foreColor, Color backColor,
220 Font font, ListViewGroup group)
221 : this(items, imageIndex, foreColor, backColor, font)
226 public ListViewItem(string[] items, string imageKey, Color foreColor, Color backColor,
227 Font font, ListViewGroup group)
228 : this(items, imageKey, foreColor, backColor, font)
232 #endregion // Public Constructors
234 protected ListViewItem (SerializationInfo info, StreamingContext context)
236 Deserialize (info, context);
239 #region Public Instance Properties
240 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
241 public Color BackColor {
243 if (sub_items.Count > 0)
244 return sub_items[0].BackColor;
247 return owner.BackColor;
249 return ThemeEngine.Current.ColorWindow;
251 set { SubItems [0].BackColor = value; }
255 public Rectangle Bounds {
257 return GetBounds (ItemBoundsPortion.Entire);
261 [DefaultValue (false)]
262 [RefreshProperties (RefreshProperties.Repaint)]
263 public bool Checked {
264 get { return is_checked; }
266 if (is_checked == value)
270 CheckState current_value = is_checked ? CheckState.Checked : CheckState.Unchecked;
271 CheckState new_value = value ? CheckState.Checked : CheckState.Unchecked;
273 ItemCheckEventArgs icea = new ItemCheckEventArgs (Index,
274 new_value, current_value);
275 owner.OnItemCheck (icea);
277 if (new_value != current_value) {
278 // force re-population of list
279 owner.CheckedItems.Reset ();
280 is_checked = new_value == CheckState.Checked;
283 ItemCheckedEventArgs args = new ItemCheckedEventArgs (this);
284 owner.OnItemChecked (args);
292 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
293 public bool Focused {
298 // In virtual mode the checks are always done using indexes
299 if (owner.VirtualMode)
300 return Index == owner.focused_item_index;
303 return owner.FocusedItem == this;
310 if (Focused == value)
313 ListViewItem prev_focused_item = owner.FocusedItem;
314 if (prev_focused_item != null)
315 prev_focused_item.UpdateFocusedState ();
317 owner.focused_item_index = value ? Index : -1;
319 owner.OnUIAFocusedItemChanged ();
321 UpdateFocusedState ();
326 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
331 else if (owner != null)
334 return ThemeEngine.Current.DefaultFont;
349 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
350 public Color ForeColor {
352 if (sub_items.Count > 0)
353 return sub_items[0].ForeColor;
356 return owner.ForeColor;
358 return ThemeEngine.Current.ColorWindowText;
360 set { SubItems [0].ForeColor = value; }
364 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
365 [Editor ("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design,
366 typeof (System.Drawing.Design.UITypeEditor))]
368 [RefreshProperties (RefreshProperties.Repaint)]
369 [TypeConverter (typeof (NoneExcludedImageIndexConverter))]
370 public int ImageIndex {
371 get { return image_index; }
374 throw new ArgumentException ("Invalid ImageIndex. It must be greater than or equal to -1.");
377 image_key = String.Empty;
386 [LocalizableAttribute (true)]
387 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
388 [Editor ("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design,
389 typeof (System.Drawing.Design.UITypeEditor))]
390 [RefreshProperties (RefreshProperties.Repaint)]
391 [TypeConverter (typeof (ImageKeyConverter))]
392 public string ImageKey {
397 image_key = value == null ? String.Empty : value;
407 public ImageList ImageList {
411 else if (owner.View == View.LargeIcon)
412 return owner.large_image_list;
414 return owner.small_image_list;
419 public int IndentCount {
425 throw new ArgumentOutOfRangeException ("value");
427 if (value == indent_count)
430 indent_count = value;
440 if (owner.VirtualMode)
441 return display_index;
443 if (display_index == -1)
444 return owner.Items.IndexOf (this);
446 return owner.GetItemIndex (display_index);
451 public ListView ListView {
452 get { return owner; }
457 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
463 name = value == null ? String.Empty : value;
467 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
469 public Point Position {
471 if (owner != null && owner.VirtualMode)
472 return owner.GetItemLocation (display_index);
474 if (owner != null && !owner.IsHandleCreated)
475 return new Point (-1, -1);
480 if (owner == null || owner.View == View.Details || owner.View == View.List)
483 if (owner.VirtualMode)
484 throw new InvalidOperationException ();
486 owner.ChangeItemLocation (display_index, value);
490 // When ListView uses VirtualMode, selection state info
491 // lives in the ListView, not in the item
492 // Also, in VirtualMode we can't Reset() the selection
494 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
495 public bool Selected {
497 if (owner != null && owner.VirtualMode)
498 return owner.SelectedIndices.Contains (Index);
503 if (selected == value && owner != null && !owner.VirtualMode)
506 SetSelectedCore (value);
510 // Expose this method as internal so we can force an update in the selection.
511 internal void SetSelectedCore (bool value)
514 if (value && !owner.MultiSelect)
515 owner.SelectedIndices.Clear ();
516 if (owner.VirtualMode) {
518 owner.SelectedIndices.InsertIndex (Index);
520 owner.SelectedIndices.RemoveIndex (Index);
523 owner.SelectedIndices.Reset (); // force re-population of list
526 owner.OnItemSelectionChanged (new ListViewItemSelectionChangedEventArgs (this, Index, value));
527 owner.OnSelectedIndexChanged ();
534 [Editor ("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design,
535 typeof (System.Drawing.Design.UITypeEditor))]
537 [RefreshProperties (RefreshProperties.Repaint)]
538 [RelatedImageListAttribute ("ListView.StateImageList")]
539 [TypeConverter (typeof (NoneExcludedImageIndexConverter))]
540 public int StateImageIndex {
541 get { return state_image_index; }
543 if (value < -1 || value > 14)
544 throw new ArgumentOutOfRangeException ("Invalid StateImageIndex. It must be in the range of [-1, 14].");
546 state_image_index = value;
550 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
551 [Editor ("System.Windows.Forms.Design.ListViewSubItemCollectionEditor, " + Consts.AssemblySystem_Design,
552 typeof (System.Drawing.Design.UITypeEditor))]
553 public ListViewSubItemCollection SubItems {
555 if (sub_items.Count == 0)
556 this.sub_items.Add (string.Empty);
562 [DefaultValue (null)]
563 [Localizable (false)]
564 [TypeConverter (typeof (StringConverter))]
571 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
574 if (this.sub_items.Count > 0)
575 return this.sub_items [0].Text;
580 if (SubItems [0].Text == value)
583 sub_items [0].Text = value;
589 //UIA Framework: Generates Text changed
595 [DefaultValue (true)]
596 public bool UseItemStyleForSubItems {
597 get { return use_item_style; }
598 set { use_item_style = value; }
601 [LocalizableAttribute(true)]
602 [DefaultValue (null)]
603 public ListViewGroup Group {
604 get { return this.group; }
606 if (group != value) {
608 group.Items.Remove (this);
610 value.Items.Add (this);
618 public string ToolTipText {
624 value = String.Empty;
626 tooltip_text = value;
630 #endregion // Public Instance Properties
632 #region Public Instance Methods
633 public void BeginEdit ()
635 if (owner != null && owner.LabelEdit) {
636 owner.item_control.BeginEdit (this);
639 // if (owner != null && owner.LabelEdit
640 // && owner.Activation == ItemActivation.Standard)
643 // throw new InvalidOperationException ();
646 public virtual object Clone ()
648 ListViewItem clone = new ListViewItem ();
649 clone.image_index = this.image_index;
650 clone.is_checked = this.is_checked;
651 clone.selected = this.selected;
652 clone.font = this.font;
653 clone.state_image_index = this.state_image_index;
654 clone.sub_items = new ListViewSubItemCollection (this, null);
656 foreach (ListViewSubItem subItem in this.sub_items)
657 clone.sub_items.Add (subItem.Text, subItem.ForeColor,
658 subItem.BackColor, subItem.Font);
659 clone.tag = this.tag;
660 clone.use_item_style = this.use_item_style;
663 clone.tooltip_text = tooltip_text;
668 public virtual void EnsureVisible ()
670 if (this.owner != null) {
671 owner.EnsureVisible (owner.Items.IndexOf (this));
675 public ListViewItem FindNearestItem (SearchDirectionHint searchDirection)
680 Point loc = owner.GetItemLocation (display_index);
681 return owner.FindNearestItem (searchDirection, loc);
684 public Rectangle GetBounds (ItemBoundsPortion portion)
687 return Rectangle.Empty;
692 case ItemBoundsPortion.Icon:
696 case ItemBoundsPortion.Label:
700 case ItemBoundsPortion.ItemOnly:
704 case ItemBoundsPortion.Entire:
709 throw new ArgumentException ("Invalid value for portion.");
712 Point item_loc = owner.GetItemLocation (DisplayIndex);
713 rect.X += item_loc.X;
714 rect.Y += item_loc.Y;
718 void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
720 Serialize (info, context);
723 public ListViewSubItem GetSubItemAt (int x, int y)
725 if (owner != null && owner.View != View.Details)
728 foreach (ListViewSubItem sub_item in sub_items)
729 if (sub_item.Bounds.Contains (x, y))
735 public virtual void Remove ()
740 owner.item_control.CancelEdit (this);
741 owner.Items.Remove (this);
745 public override string ToString ()
747 return string.Format ("ListViewItem: {0}", this.Text);
749 #endregion // Public Instance Methods
751 #region Protected Methods
752 protected virtual void Deserialize (SerializationInfo info, StreamingContext context)
754 sub_items = new ListViewSubItemCollection (this, null);
755 int sub_items_count = 0;
757 foreach (SerializationEntry entry in info) {
758 switch (entry.Name) {
760 sub_items.Add ((string)entry.Value);
763 font = (Font)entry.Value;
766 is_checked = (bool)entry.Value;
769 image_index = (int)entry.Value;
771 case "StateImageIndex":
772 state_image_index = (int)entry.Value;
774 case "UseItemStyleForSubItems":
775 use_item_style = (bool)entry.Value;
778 sub_items_count = (int)entry.Value;
781 group = (ListViewGroup)entry.Value;
784 if (image_index == -1)
785 image_key = (string)entry.Value;
790 Type subitem_type = typeof (ListViewSubItem);
791 if (sub_items_count > 0) {
792 sub_items.Clear (); // .net fixup
793 Text = info.GetString ("Text");
794 for (int i = 0; i < sub_items_count - 1; i++)
795 sub_items.Add ((ListViewSubItem)info.GetValue ("SubItem" + (i + 1), subitem_type));
798 // After any sub item has been added.
799 ForeColor = (Color)info.GetValue ("ForeColor", typeof (Color));
800 BackColor = (Color)info.GetValue ("BackColor", typeof (Color));
803 protected virtual void Serialize (SerializationInfo info, StreamingContext context)
805 info.AddValue ("Text", Text);
806 info.AddValue ("Font", Font);
807 info.AddValue ("ImageIndex", image_index);
808 info.AddValue ("Checked", is_checked);
809 info.AddValue ("StateImageIndex", state_image_index);
810 info.AddValue ("UseItemStyleForSubItems", use_item_style);
811 info.AddValue ("BackColor", BackColor);
812 info.AddValue ("ForeColor", ForeColor);
813 info.AddValue ("ImageKey", image_key);
814 info.AddValue ("Group", group);
815 if (sub_items.Count > 1) {
816 info.AddValue ("SubItemCount", sub_items.Count);
817 for (int i = 1; i < sub_items.Count; i++) {
818 info.AddValue ("SubItem" + i, sub_items [i]);
822 #endregion // Protected Methods
824 #region Private Internal Methods
825 internal Rectangle CheckRectReal {
827 Rectangle rect = checkbox_rect;
828 Point item_loc = owner.GetItemLocation (DisplayIndex);
829 rect.X += item_loc.X;
830 rect.Y += item_loc.Y;
835 Rectangle text_bounds;
836 internal Rectangle TextBounds {
838 // Call Layout() if it hasn't been called before.
839 if (owner.VirtualMode && bounds == new Rectangle (-1, -1, -1, -1))
841 Rectangle result = text_bounds;
842 Point loc = owner.GetItemLocation (DisplayIndex);
849 internal int DisplayIndex {
851 // Special case for Details view
852 // and no columns (which means no Layout at all)
853 if (display_index == -1)
854 return owner.Items.IndexOf (this);
856 return display_index;
859 display_index = value;
865 return Index == owner.HotItemIndex;
869 internal Font HotFont {
871 if (hot_font == null)
872 hot_font = new Font (Font, Font.Style | FontStyle.Underline);
878 internal ListView Owner {
887 internal void SetGroup (ListViewGroup group)
892 internal void SetPosition (Point position)
894 this.position = position;
897 // When focus changed, we need to invalidate area
898 // with previous layout and with the new one
899 void UpdateFocusedState ()
908 internal void Invalidate ()
910 if (owner == null || owner.item_control == null || owner.updating)
913 // Add some padding to bounds (focused extra space, selection)
914 Rectangle rect = Bounds;
916 owner.item_control.Invalidate (rect);
919 internal void Layout ()
925 Size text_size = owner.text_size;
927 checkbox_rect = Rectangle.Empty;
928 if (owner.CheckBoxes)
929 checkbox_rect.Size = owner.CheckBoxSize;
930 switch (owner.View) {
932 // LAMESPEC: MSDN says, "In all views except the details
933 // view of the ListView, this value specifies the same
934 // bounding rectangle as the Entire value." Actually, it
935 // returns same bounding rectangles for Item and Entire
936 // values in the case of Details view.
939 if (owner.SmallImageList != null)
940 x_offset = indent_count * owner.SmallImageList.ImageSize.Width;
942 // Handle reordered column
943 if (owner.Columns.Count > 0)
944 checkbox_rect.X = owner.Columns[0].Rect.X + x_offset;
946 icon_rect = label_rect = Rectangle.Empty;
947 icon_rect.X = checkbox_rect.Right + 2;
948 item_ht = owner.ItemSize.Height;
950 if (owner.SmallImageList != null)
951 icon_rect.Width = owner.SmallImageList.ImageSize.Width;
953 label_rect.Height = icon_rect.Height = item_ht;
954 checkbox_rect.Y = item_ht - checkbox_rect.Height;
956 label_rect.X = icon_rect.Width > 0 ? icon_rect.Right + 1 : icon_rect.Right;
958 if (owner.Columns.Count > 0)
959 label_rect.Width = owner.Columns[0].Wd - label_rect.X + checkbox_rect.X;
961 label_rect.Width = text_size.Width;
963 SizeF text_sz = TextRenderer.MeasureString (Text, Font);
964 text_bounds = label_rect;
965 text_bounds.Width = (int) text_sz.Width;
967 item_rect = total = Rectangle.Union
968 (Rectangle.Union (checkbox_rect, icon_rect), label_rect);
969 bounds.Size = total.Size;
973 for (int i = 0; i < owner.Columns.Count; i++) {
974 item_rect.Width += owner.Columns [i].Wd;
975 bounds.Width += owner.Columns [i].Wd;
978 // Bounds for sub items
979 int n = Math.Min (owner.Columns.Count, sub_items.Count);
980 for (int i = 0; i < n; i++) {
981 Rectangle col_rect = owner.Columns [i].Rect;
982 sub_items [i].SetBounds (col_rect.X, 0, col_rect.Width, item_ht);
987 label_rect = icon_rect = Rectangle.Empty;
989 SizeF sz = TextRenderer.MeasureString (Text, Font);
990 if ((int) sz.Width > text_size.Width) {
991 if (Focused && owner.InternalContainsFocus) {
992 int text_width = text_size.Width;
993 StringFormat format = new StringFormat ();
994 format.Alignment = StringAlignment.Center;
995 sz = TextRenderer.MeasureString (Text, Font, text_width, format);
996 text_size.Height = (int) sz.Height;
998 text_size.Height = 2 * (int) sz.Height;
1001 if (owner.LargeImageList != null) {
1002 icon_rect.Width = owner.LargeImageList.ImageSize.Width;
1003 icon_rect.Height = owner.LargeImageList.ImageSize.Height;
1006 if (checkbox_rect.Height > icon_rect.Height)
1007 icon_rect.Y = checkbox_rect.Height - icon_rect.Height;
1009 checkbox_rect.Y = icon_rect.Height - checkbox_rect.Height;
1011 if (text_size.Width <= icon_rect.Width) {
1012 icon_rect.X = checkbox_rect.Width + 1;
1013 label_rect.X = icon_rect.X + (icon_rect.Width - text_size.Width) / 2;
1014 label_rect.Y = icon_rect.Bottom + 2;
1015 label_rect.Size = text_size;
1017 int centerX = text_size.Width / 2;
1018 icon_rect.X = checkbox_rect.Width + 1 + centerX - icon_rect.Width / 2;
1019 label_rect.X = checkbox_rect.Width + 1;
1020 label_rect.Y = icon_rect.Bottom + 2;
1021 label_rect.Size = text_size;
1024 item_rect = Rectangle.Union (icon_rect, label_rect);
1025 total = Rectangle.Union (item_rect, checkbox_rect);
1026 bounds.Size = total.Size;
1030 case View.SmallIcon:
1031 label_rect = icon_rect = Rectangle.Empty;
1032 icon_rect.X = checkbox_rect.Width + 1;
1033 item_ht = Math.Max (owner.CheckBoxSize.Height, text_size.Height);
1035 if (owner.SmallImageList != null) {
1036 item_ht = Math.Max (item_ht, owner.SmallImageList.ImageSize.Height);
1037 icon_rect.Width = owner.SmallImageList.ImageSize.Width;
1038 icon_rect.Height = owner.SmallImageList.ImageSize.Height;
1041 checkbox_rect.Y = item_ht - checkbox_rect.Height;
1042 label_rect.X = icon_rect.Right + 1;
1043 label_rect.Width = text_size.Width;
1044 label_rect.Height = icon_rect.Height = item_ht;
1046 item_rect = Rectangle.Union (icon_rect, label_rect);
1047 total = Rectangle.Union (item_rect, checkbox_rect);
1048 bounds.Size = total.Size;
1051 if (!Application.VisualStylesEnabled)
1052 goto case View.LargeIcon;
1054 label_rect = icon_rect = Rectangle.Empty;
1056 if (owner.LargeImageList != null) {
1057 icon_rect.Width = owner.LargeImageList.ImageSize.Width;
1058 icon_rect.Height = owner.LargeImageList.ImageSize.Height;
1062 SizeF tsize = TextRenderer.MeasureString (Text, Font);
1063 int main_item_height = (int) Math.Ceiling (tsize.Height);
1064 int main_item_width = (int) Math.Ceiling (tsize.Width);
1065 sub_items [0].bounds.Height = main_item_height;
1067 // Set initial values for subitem's layout
1068 int total_height = main_item_height;
1069 int max_subitem_width = main_item_width;
1071 int count = Math.Min (owner.Columns.Count, sub_items.Count);
1072 for (int i = 1; i < count; i++) { // Ignore first column and first subitem
1073 ListViewSubItem sub_item = sub_items [i];
1074 if (sub_item.Text == null || sub_item.Text.Length == 0)
1077 tsize = TextRenderer.MeasureString (sub_item.Text, sub_item.Font);
1079 int width = (int)Math.Ceiling (tsize.Width);
1080 if (width > max_subitem_width)
1081 max_subitem_width = width;
1083 int height = (int)Math.Ceiling (tsize.Height);
1084 total_height += height + separation;
1086 sub_item.bounds.Height = height;
1089 max_subitem_width = Math.Min (max_subitem_width, owner.TileSize.Width - (icon_rect.Width + 4));
1090 label_rect.X = icon_rect.Right + 4;
1091 label_rect.Y = owner.TileSize.Height / 2 - total_height / 2;
1092 label_rect.Width = max_subitem_width;
1093 label_rect.Height = total_height;
1095 // Main item - always set bounds for it
1096 sub_items [0].SetBounds (label_rect.X, label_rect.Y, max_subitem_width, sub_items [0].bounds.Height);
1098 // Second pass to assign bounds for every sub item
1099 int current_y = sub_items [0].bounds.Bottom + separation;
1100 for (int j = 1; j < count; j++) {
1101 ListViewSubItem sub_item = sub_items [j];
1102 if (sub_item.Text == null || sub_item.Text.Length == 0)
1105 sub_item.SetBounds (label_rect.X, current_y, max_subitem_width, sub_item.bounds.Height);
1106 current_y += sub_item.Bounds.Height + separation;
1109 item_rect = Rectangle.Union (icon_rect, label_rect);
1110 bounds.Size = item_rect.Size;
1115 #endregion // Private Internal Methods
1119 [DefaultProperty ("Text")]
1120 [DesignTimeVisible (false)]
1122 [ToolboxItem (false)]
1123 [TypeConverter (typeof(ListViewSubItemConverter))]
1124 public class ListViewSubItem
1127 internal ListViewItem owner;
1128 private string text = string.Empty;
1129 private string name;
1130 private object userData;
1131 private SubItemStyle style;
1133 internal Rectangle bounds;
1136 #region UIA Framework: Methods, Properties and Events
1138 [field:NonSerialized]
1139 internal event EventHandler UIATextChanged;
1141 private void OnUIATextChanged ()
1143 if (UIATextChanged != null)
1144 UIATextChanged (this, EventArgs.Empty);
1147 #endregion // UIA Framework: Methods, Properties and Events
1150 #region Public Constructors
1151 public ListViewSubItem ()
1152 : this (null, string.Empty, Color.Empty,
1157 public ListViewSubItem (ListViewItem owner, string text)
1158 : this (owner, text, Color.Empty,
1163 public ListViewSubItem (ListViewItem owner, string text, Color foreColor,
1164 Color backColor, Font font)
1168 this.style = new SubItemStyle (foreColor,
1171 #endregion // Public Constructors
1173 #region Public Instance Properties
1174 public Color BackColor {
1176 if (style.backColor != Color.Empty)
1177 return style.backColor;
1178 if (this.owner != null && this.owner.ListView != null)
1179 return this.owner.ListView.BackColor;
1180 return ThemeEngine.Current.ColorWindow;
1183 style.backColor = value;
1189 public Rectangle Bounds {
1191 Rectangle retval = bounds;
1192 if (owner != null) {
1193 retval.X += owner.Bounds.X;
1194 retval.Y += owner.Bounds.Y;
1201 [Localizable (true)]
1204 if (style.font != null)
1206 else if (owner != null)
1208 return ThemeEngine.Current.DefaultFont;
1211 if (style.font == value)
1218 public Color ForeColor {
1220 if (style.foreColor != Color.Empty)
1221 return style.foreColor;
1222 if (this.owner != null && this.owner.ListView != null)
1223 return this.owner.ListView.ForeColor;
1224 return ThemeEngine.Current.ColorWindowText;
1227 style.foreColor = value;
1232 [Localizable (true)]
1233 public string Name {
1236 return string.Empty;
1244 [TypeConverter (typeof (StringConverter))]
1245 [BindableAttribute (true)]
1246 [DefaultValue (null)]
1247 [Localizable (false)]
1257 [Localizable (true)]
1258 public string Text {
1259 get { return text; }
1265 text = string.Empty;
1271 // UIA Framework: Generates SubItem TextChanged
1272 OnUIATextChanged ();
1275 #endregion // Public Instance Properties
1277 #region Public Methods
1278 public void ResetStyle ()
1284 public override string ToString ()
1286 return string.Format ("ListViewSubItem {{0}}", text);
1288 #endregion // Public Methods
1290 #region Private Methods
1291 private void Invalidate ()
1293 if (owner == null || owner.owner == null)
1296 owner.Invalidate ();
1300 void OnDeserialized (StreamingContext context)
1306 internal int Height {
1308 return bounds.Height;
1312 internal void SetBounds (int x, int y, int width, int height)
1314 bounds = new Rectangle (x, y, width, height);
1317 #endregion // Private Methods
1322 public SubItemStyle ()
1326 public SubItemStyle (Color foreColor, Color backColor, Font font)
1328 this.foreColor = foreColor;
1329 this.backColor = backColor;
1333 public void Reset ()
1335 foreColor = Color.Empty;
1336 backColor = Color.Empty;
1340 public Color backColor;
1341 public Color foreColor;
1346 public class ListViewSubItemCollection : IList, ICollection, IEnumerable
1348 private ArrayList list;
1349 internal ListViewItem owner;
1351 #region Public Constructors
1352 public ListViewSubItemCollection (ListViewItem owner) : this (owner, owner.Text)
1355 #endregion // Public Constructors
1357 internal ListViewSubItemCollection (ListViewItem owner, string text)
1360 this.list = new ArrayList ();
1364 #region Public Properties
1367 get { return list.Count; }
1370 public bool IsReadOnly {
1371 get { return false; }
1374 public ListViewSubItem this [int index] {
1375 get { return (ListViewSubItem) list [index]; }
1377 value.owner = owner;
1378 list [index] = value;
1380 owner.Invalidate ();
1384 public virtual ListViewSubItem this [string key] {
1386 int idx = IndexOfKey (key);
1390 return (ListViewSubItem) list [idx];
1394 bool ICollection.IsSynchronized {
1395 get { return list.IsSynchronized; }
1398 object ICollection.SyncRoot {
1399 get { return list.SyncRoot; }
1402 bool IList.IsFixedSize {
1403 get { return list.IsFixedSize; }
1406 object IList.this [int index] {
1407 get { return this [index]; }
1409 if (! (value is ListViewSubItem))
1410 throw new ArgumentException ("Not of type ListViewSubItem", "value");
1411 this [index] = (ListViewSubItem) value;
1414 #endregion // Public Properties
1416 #region Public Methods
1417 public ListViewSubItem Add (ListViewSubItem item)
1421 owner.Invalidate ();
1425 public ListViewSubItem Add (string text)
1427 ListViewSubItem item = new ListViewSubItem (owner, text);
1431 public ListViewSubItem Add (string text, Color foreColor,
1432 Color backColor, Font font)
1434 ListViewSubItem item = new ListViewSubItem (owner, text,
1435 foreColor, backColor, font);
1439 public void AddRange (ListViewSubItem [] items)
1442 throw new ArgumentNullException ("items");
1444 foreach (ListViewSubItem item in items) {
1450 owner.Invalidate ();
1453 public void AddRange (string [] items)
1456 throw new ArgumentNullException ("items");
1458 foreach (string item in items) {
1461 AddSubItem (new ListViewSubItem (owner, item));
1464 owner.Invalidate ();
1467 public void AddRange (string [] items, Color foreColor,
1468 Color backColor, Font font)
1471 throw new ArgumentNullException ("items");
1473 foreach (string item in items) {
1477 AddSubItem (new ListViewSubItem (owner, item, foreColor, backColor, font));
1480 owner.Invalidate ();
1483 void AddSubItem (ListViewSubItem subItem)
1485 subItem.owner = owner;
1489 subItem.UIATextChanged += OnUIASubItemTextChanged;
1492 public void Clear ()
1497 public bool Contains (ListViewSubItem subItem)
1499 return list.Contains (subItem);
1502 public virtual bool ContainsKey (string key)
1504 return IndexOfKey (key) != -1;
1507 public IEnumerator GetEnumerator ()
1509 return list.GetEnumerator ();
1512 void ICollection.CopyTo (Array dest, int index)
1514 list.CopyTo (dest, index);
1517 int IList.Add (object item)
1519 if (! (item is ListViewSubItem)) {
1520 throw new ArgumentException ("Not of type ListViewSubItem", "item");
1523 ListViewSubItem sub_item = (ListViewSubItem) item;
1524 sub_item.owner = this.owner;
1526 sub_item.UIATextChanged += OnUIASubItemTextChanged;
1527 return list.Add (sub_item);
1530 bool IList.Contains (object subItem)
1532 if (! (subItem is ListViewSubItem)) {
1533 throw new ArgumentException ("Not of type ListViewSubItem", "subItem");
1536 return this.Contains ((ListViewSubItem) subItem);
1539 int IList.IndexOf (object subItem)
1541 if (! (subItem is ListViewSubItem)) {
1542 throw new ArgumentException ("Not of type ListViewSubItem", "subItem");
1545 return this.IndexOf ((ListViewSubItem) subItem);
1548 void IList.Insert (int index, object item)
1550 if (! (item is ListViewSubItem)) {
1551 throw new ArgumentException ("Not of type ListViewSubItem", "item");
1554 this.Insert (index, (ListViewSubItem) item);
1557 void IList.Remove (object item)
1559 if (! (item is ListViewSubItem)) {
1560 throw new ArgumentException ("Not of type ListViewSubItem", "item");
1563 this.Remove ((ListViewSubItem) item);
1566 public int IndexOf (ListViewSubItem subItem)
1568 return list.IndexOf (subItem);
1571 public virtual int IndexOfKey (string key)
1573 if (key == null || key.Length == 0)
1576 for (int i = 0; i < list.Count; i++) {
1577 ListViewSubItem l = (ListViewSubItem) list [i];
1578 if (String.Compare (l.Name, key, true) == 0)
1585 public void Insert (int index, ListViewSubItem item)
1587 item.owner = this.owner;
1588 list.Insert (index, item);
1590 owner.Invalidate ();
1593 item.UIATextChanged += OnUIASubItemTextChanged;
1596 public void Remove (ListViewSubItem item)
1600 owner.Invalidate ();
1603 item.UIATextChanged -= OnUIASubItemTextChanged;
1606 public virtual void RemoveByKey (string key)
1608 int idx = IndexOfKey (key);
1613 public void RemoveAt (int index)
1616 if (index >= 0 && index < list.Count)
1617 ((ListViewSubItem) list [index]).UIATextChanged -= OnUIASubItemTextChanged;
1619 list.RemoveAt (index);
1622 #endregion // Public Methods
1623 #region UIA Event Handler
1625 private void OnUIASubItemTextChanged (object sender, EventArgs args)
1627 owner.OnUIASubItemTextChanged (new LabelEditEventArgs (list.IndexOf (sender)));
1634 #endregion // Subclasses