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>
31 using System.Collections;
32 using System.ComponentModel;
34 using System.Runtime.Serialization;
36 namespace System.Windows.Forms
38 [DefaultProperty ("Text")]
39 [DesignTimeVisible (false)]
42 [TypeConverter (typeof (ListViewItemConverter))]
43 public class ListViewItem : ICloneable, ISerializable
45 #region Instance Variables
46 private int image_index = -1;
47 private bool is_checked = false;
48 private bool is_focused = false;
49 private int state_image_index = -1;
50 private ListViewSubItemCollection sub_items;
52 private bool use_item_style = true;
54 private string name = String.Empty;
58 Rectangle checkbox_rect; // calculated by CalcListViewItem method
69 #endregion Instance Variables
71 #region Public Constructors
72 public ListViewItem ()
74 this.sub_items = new ListViewSubItemCollection (this);
75 this.sub_items.Add ("");
78 public ListViewItem (string text) : this (text, -1)
82 public ListViewItem (string [] items) : this (items, -1)
86 public ListViewItem (ListViewItem.ListViewSubItem [] subItems, int imageIndex)
88 this.sub_items = new ListViewSubItemCollection (this);
89 this.sub_items.AddRange (subItems);
90 this.image_index = imageIndex;
93 public ListViewItem (string text, int imageIndex)
95 this.image_index = imageIndex;
96 this.sub_items = new ListViewSubItemCollection (this);
97 this.sub_items.Add (text);
100 public ListViewItem (string [] items, int imageIndex)
102 this.sub_items = new ListViewSubItemCollection (this);
103 this.sub_items.AddRange (items);
104 this.image_index = imageIndex;
107 public ListViewItem (string [] items, int imageIndex, Color foreColor,
108 Color backColor, Font font)
110 this.sub_items = new ListViewSubItemCollection (this);
111 this.sub_items.AddRange (items);
112 this.image_index = imageIndex;
113 ForeColor = foreColor;
114 BackColor = backColor;
117 #endregion // Public Constructors
119 #region Public Instance Properties
120 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
121 public Color BackColor {
123 if (sub_items.Count > 0)
124 return sub_items[0].BackColor;
127 return owner.BackColor;
129 return ThemeEngine.Current.ColorWindow;
132 set { sub_items[0].BackColor = value; }
136 public Rectangle Bounds {
138 return GetBounds (ItemBoundsPortion.Entire);
142 [DefaultValue (false)]
143 [RefreshProperties (RefreshProperties.Repaint)]
144 public bool Checked {
145 get { return is_checked; }
147 if (is_checked == value)
153 // force re-population of list
154 owner.CheckedItems.Reset ();
162 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
163 public bool Focused {
164 get { return is_focused; }
166 if (is_focused == value)
179 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
184 else if (owner != null)
187 return ThemeEngine.Current.DefaultFont;
201 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
202 public Color ForeColor {
204 if (sub_items.Count > 0)
205 return sub_items[0].ForeColor;
208 return owner.ForeColor;
210 return ThemeEngine.Current.ColorWindowText;
212 set { sub_items[0].ForeColor = value; }
216 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
217 [Editor ("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design,
218 typeof (System.Drawing.Design.UITypeEditor))]
220 [TypeConverter (typeof (ImageIndexConverter))]
221 public int ImageIndex {
222 get { return image_index; }
225 throw new ArgumentException ("Invalid ImageIndex. It must be greater than or equal to -1.");
236 public ImageList ImageList {
240 else if (owner.View == View.LargeIcon)
241 return owner.large_image_list;
243 return owner.small_image_list;
253 return owner.Items.IndexOf (this);
258 public ListView ListView {
259 get { return owner; }
270 name = value == null ? String.Empty : name;
276 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
277 public bool Selected {
278 get { return selected; }
280 if (selected == value)
284 if (value && !owner.MultiSelect)
285 owner.SelectedItems.Clear ();
287 // force re-population of list
288 owner.SelectedItems.Reset ();
290 owner.OnSelectedIndexChanged ();
299 [Editor ("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design,
300 typeof (System.Drawing.Design.UITypeEditor))]
302 [TypeConverter (typeof (ImageIndexConverter))]
303 public int StateImageIndex {
304 get { return state_image_index; }
306 if (value < -1 || value > 14)
307 throw new ArgumentOutOfRangeException ("Invalid StateImageIndex. It must be in the range of [-1, 14].");
309 state_image_index = value;
313 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
314 public ListViewSubItemCollection SubItems {
315 get { return sub_items; }
319 [DefaultValue (null)]
320 [Localizable (false)]
321 [TypeConverter (typeof (StringConverter))]
328 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
331 if (this.sub_items.Count > 0)
332 return this.sub_items [0].Text;
337 if (sub_items [0].Text == value)
340 sub_items [0].Text = value;
348 [DefaultValue (true)]
349 public bool UseItemStyleForSubItems {
350 get { return use_item_style; }
351 set { use_item_style = value; }
353 #endregion // Public Instance Properties
355 #region Public Instance Methods
356 public void BeginEdit ()
358 if (owner != null && owner.LabelEdit) {
359 owner.item_control.BeginEdit (this);
362 // if (owner != null && owner.LabelEdit
363 // && owner.Activation == ItemActivation.Standard)
366 // throw new InvalidOperationException ();
369 public virtual object Clone ()
371 ListViewItem clone = new ListViewItem ();
372 clone.image_index = this.image_index;
373 clone.is_checked = this.is_checked;
374 clone.is_focused = this.is_focused;
375 clone.selected = this.selected;
376 clone.font = this.font;
377 clone.state_image_index = this.state_image_index;
378 clone.sub_items = new ListViewSubItemCollection (this);
380 foreach (ListViewSubItem subItem in this.sub_items)
381 clone.sub_items.Add (subItem.Text, subItem.ForeColor,
382 subItem.BackColor, subItem.Font);
383 clone.tag = this.tag;
384 clone.use_item_style = this.use_item_style;
393 public virtual void EnsureVisible ()
395 if (this.owner != null) {
396 owner.EnsureVisible (owner.Items.IndexOf (this));
400 public Rectangle GetBounds (ItemBoundsPortion portion)
403 return Rectangle.Empty;
408 case ItemBoundsPortion.Icon:
412 case ItemBoundsPortion.Label:
416 case ItemBoundsPortion.ItemOnly:
420 case ItemBoundsPortion.Entire:
422 rect.X -= owner.h_marker;
423 rect.Y -= owner.v_marker;
427 throw new ArgumentException ("Invalid value for portion.");
430 rect.X += bounds.X - owner.h_marker;
431 rect.Y += bounds.Y - owner.v_marker;
435 void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
440 public virtual void Remove ()
443 owner.Items.Remove (this);
447 public override string ToString ()
449 return string.Format ("ListViewItem: {0}", this.Text);
451 #endregion // Public Instance Methods
453 #region Protected Methods
454 protected virtual void Deserialize (SerializationInfo info, StreamingContext context)
459 protected virtual void Serialize (SerializationInfo info, StreamingContext context)
463 #endregion // Protected Methods
465 #region Private Internal Methods
466 internal Rectangle CheckRectReal {
468 Rectangle rect = checkbox_rect;
469 rect.X += bounds.X - owner.h_marker;
470 rect.Y += bounds.Y - owner.v_marker;
475 internal Point Location {
477 if (bounds.X == value.X && bounds.Y == value.Y)
480 Rectangle prev = Bounds;
484 if (prev != Rectangle.Empty)
485 owner.item_control.Invalidate (prev);
486 owner.item_control.Invalidate (Bounds);
491 internal ListView Owner {
503 private void Invalidate ()
505 if (owner == null || owner.item_control == null)
508 owner.item_control.Invalidate (Bounds);
511 internal void Layout ()
515 Size text_size = owner.text_size;
517 checkbox_rect = Rectangle.Empty;
518 if (owner.CheckBoxes)
519 checkbox_rect.Size = owner.CheckBoxSize;
521 switch (owner.View) {
523 // LAMESPEC: MSDN says, "In all views except the details
524 // view of the ListView, this value specifies the same
525 // bounding rectangle as the Entire value." Actually, it
526 // returns same bounding rectangles for Item and Entire
527 // values in the case of Details view.
529 icon_rect = label_rect = Rectangle.Empty;
530 icon_rect.X = checkbox_rect.Width + 2;
531 item_ht = Math.Max (owner.CheckBoxSize.Height, text_size.Height);
533 if (owner.SmallImageList != null) {
534 item_ht = Math.Max (item_ht, owner.SmallImageList.ImageSize.Height);
535 icon_rect.Width = owner.SmallImageList.ImageSize.Width;
538 label_rect.Height = icon_rect.Height = item_ht;
539 checkbox_rect.Y = item_ht - checkbox_rect.Height;
541 label_rect.X = icon_rect.Right + 1;
543 if (owner.Columns.Count > 0)
544 label_rect.Width = Math.Max (text_size.Width, owner.Columns[0].Wd);
546 label_rect.Width = text_size.Width;
548 item_rect = total = Rectangle.Union
549 (Rectangle.Union (checkbox_rect, icon_rect), label_rect);
550 bounds.Size = total.Size;
552 // Take into account the rest of columns. First column
553 // is already taken into account above.
554 for (int i = 1; i < owner.Columns.Count; i++) {
555 item_rect.Width += owner.Columns [i].Wd;
556 bounds.Width += owner.Columns [i].Wd;
561 label_rect = icon_rect = Rectangle.Empty;
563 SizeF sz = owner.DeviceContext.MeasureString (Text, Font);
564 if ((int) sz.Width > text_size.Width) {
566 int text_width = text_size.Width;
567 StringFormat format = new StringFormat ();
568 format.Alignment = StringAlignment.Center;
569 sz = owner.DeviceContext.MeasureString (Text, Font, text_width, format);
570 text_size.Height = (int) sz.Height;
572 text_size.Height = 2 * (int) sz.Height;
575 if (owner.LargeImageList != null) {
576 icon_rect.Width = owner.LargeImageList.ImageSize.Width;
577 icon_rect.Height = owner.LargeImageList.ImageSize.Height;
580 if (checkbox_rect.Height > icon_rect.Height)
581 icon_rect.Y = checkbox_rect.Height - icon_rect.Height;
583 checkbox_rect.Y = icon_rect.Height - checkbox_rect.Height;
585 if (text_size.Width <= icon_rect.Width) {
586 icon_rect.X = checkbox_rect.Width + 1;
587 label_rect.X = icon_rect.X + (icon_rect.Width - text_size.Width) / 2;
588 label_rect.Y = icon_rect.Bottom + 2;
589 label_rect.Size = text_size;
591 int centerX = text_size.Width / 2;
592 icon_rect.X = checkbox_rect.Width + 1 + centerX - icon_rect.Width / 2;
593 label_rect.X = checkbox_rect.Width + 1;
594 label_rect.Y = icon_rect.Bottom + 2;
595 label_rect.Size = text_size;
598 item_rect = Rectangle.Union (icon_rect, label_rect);
599 total = Rectangle.Union (item_rect, checkbox_rect);
600 bounds.Size = total.Size;
605 label_rect = icon_rect = Rectangle.Empty;
606 icon_rect.X = checkbox_rect.Width + 1;
607 item_ht = Math.Max (owner.CheckBoxSize.Height, text_size.Height);
609 if (owner.SmallImageList != null) {
610 item_ht = Math.Max (item_ht, owner.SmallImageList.ImageSize.Height);
611 icon_rect.Width = owner.SmallImageList.ImageSize.Width;
612 icon_rect.Height = owner.SmallImageList.ImageSize.Height;
615 checkbox_rect.Y = item_ht - checkbox_rect.Height;
616 label_rect.X = icon_rect.Right + 1;
617 label_rect.Width = text_size.Width;
618 label_rect.Height = icon_rect.Height = item_ht;
620 item_rect = Rectangle.Union (icon_rect, label_rect);
621 total = Rectangle.Union (item_rect, checkbox_rect);
622 bounds.Size = total.Size;
627 #endregion // Private Internal Methods
631 [DefaultProperty ("Text")]
632 [DesignTimeVisible (false)]
634 [ToolboxItem (false)]
635 [TypeConverter (typeof(ListViewSubItemConverter))]
636 public class ListViewSubItem
638 private Color back_color;
640 private Color fore_color;
641 internal ListViewItem owner;
644 #region Public Constructors
645 public ListViewSubItem ()
649 public ListViewSubItem (ListViewItem owner, string text)
650 : this (owner, text, ThemeEngine.Current.ColorWindowText,
651 ThemeEngine.Current.ColorWindow, null)
655 public ListViewSubItem (ListViewItem owner, string text, Color foreColor,
656 Color backColor, Font font)
660 this.fore_color = foreColor;
661 this.back_color = backColor;
664 #endregion // Public Constructors
666 #region Public Instance Properties
667 public Color BackColor {
668 get { return back_color; }
680 else if (owner != null)
682 return ThemeEngine.Current.DefaultFont;
692 public Color ForeColor {
693 get { return fore_color; }
708 #endregion // Public Instance Properties
710 #region Public Methods
711 public void ResetStyle ()
713 font = ThemeEngine.Current.DefaultFont;
714 back_color = ThemeEngine.Current.DefaultControlBackColor;
715 fore_color = ThemeEngine.Current.DefaultControlForeColor;
719 public override string ToString ()
721 return string.Format ("ListViewSubItem {{0}}", text);
723 #endregion // Public Methods
726 #region Private Methods
727 private void Invalidate ()
729 if (owner == null || owner.owner == null)
732 owner.owner.Invalidate ();
734 #endregion // Private Methods
737 public class ListViewSubItemCollection : IList, ICollection, IEnumerable
739 private ArrayList list;
740 internal ListViewItem owner;
742 #region Public Constructors
743 public ListViewSubItemCollection (ListViewItem owner)
746 this.list = new ArrayList ();
748 #endregion // Public Constructors
750 #region Public Properties
753 get { return list.Count; }
756 public bool IsReadOnly {
757 get { return false; }
760 public ListViewSubItem this [int index] {
761 get { return (ListViewSubItem) list [index]; }
763 value.owner = this.owner;
764 list [index] = value;
768 bool ICollection.IsSynchronized {
769 get { return list.IsSynchronized; }
772 object ICollection.SyncRoot {
773 get { return list.SyncRoot; }
776 bool IList.IsFixedSize {
777 get { return list.IsFixedSize; }
780 object IList.this [int index] {
781 get { return this [index]; }
783 if (! (value is ListViewSubItem))
784 throw new ArgumentException ("Not of type ListViewSubItem", "value");
785 this [index] = (ListViewSubItem) value;
788 #endregion // Public Properties
790 #region Public Methods
791 public ListViewSubItem Add (ListViewSubItem item)
793 item.owner = this.owner;
798 public ListViewSubItem Add (string text)
800 ListViewSubItem item = new ListViewSubItem (this.owner, text);
805 public ListViewSubItem Add (string text, Color foreColor,
806 Color backColor, Font font)
808 ListViewSubItem item = new ListViewSubItem (this.owner, text,
809 foreColor, backColor, font);
814 public void AddRange (ListViewSubItem [] items)
817 foreach (ListViewSubItem item in items)
821 public void AddRange (string [] items)
824 foreach (string item in items)
828 public void AddRange (string [] items, Color foreColor,
829 Color backColor, Font font)
832 foreach (string item in items)
833 this.Add (item, foreColor, backColor, font);
841 public bool Contains (ListViewSubItem item)
843 return list.Contains (item);
846 public IEnumerator GetEnumerator ()
848 return list.GetEnumerator ();
851 void ICollection.CopyTo (Array dest, int index)
853 list.CopyTo (dest, index);
856 int IList.Add (object item)
858 if (! (item is ListViewSubItem)) {
859 throw new ArgumentException ("Not of type ListViewSubItem", "item");
862 ListViewSubItem sub_item = (ListViewSubItem) item;
863 sub_item.owner = this.owner;
864 return list.Add (sub_item);
867 bool IList.Contains (object subItem)
869 if (! (subItem is ListViewSubItem)) {
870 throw new ArgumentException ("Not of type ListViewSubItem", "subItem");
873 return this.Contains ((ListViewSubItem) subItem);
876 int IList.IndexOf (object subItem)
878 if (! (subItem is ListViewSubItem)) {
879 throw new ArgumentException ("Not of type ListViewSubItem", "subItem");
882 return this.IndexOf ((ListViewSubItem) subItem);
885 void IList.Insert (int index, object item)
887 if (! (item is ListViewSubItem)) {
888 throw new ArgumentException ("Not of type ListViewSubItem", "item");
891 this.Insert (index, (ListViewSubItem) item);
894 void IList.Remove (object item)
896 if (! (item is ListViewSubItem)) {
897 throw new ArgumentException ("Not of type ListViewSubItem", "item");
900 this.Remove ((ListViewSubItem) item);
903 public int IndexOf (ListViewSubItem subItem)
905 return list.IndexOf (subItem);
908 public void Insert (int index, ListViewSubItem item)
910 item.owner = this.owner;
911 list.Insert (index, item);
914 public void Remove (ListViewSubItem item)
919 public void RemoveAt (int index)
921 list.RemoveAt (index);
923 #endregion // Public Methods
925 #endregion // Subclasses