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)
26 // - Drawing of focus rectangle
33 using System.Collections;
34 using System.ComponentModel;
36 using System.Runtime.Serialization;
38 namespace System.Windows.Forms
40 [DefaultProperty ("Text")]
41 [DesignTimeVisible (false)]
44 [TypeConverter (typeof (ListViewItemConverter))]
45 public class ListViewItem : ICloneable, ISerializable
47 #region Instance Variables
48 private int image_index = -1;
49 private bool is_checked = false;
50 private bool is_focused = false;
51 private int state_image_index = -1;
52 private ListViewSubItemCollection sub_items;
54 private bool use_item_style = true;
57 internal Rectangle checkbox_rect; // calculated by CalcListViewItem method
58 internal Rectangle entire_rect;
59 internal Rectangle icon_rect;
60 internal Rectangle item_rect;
61 internal Rectangle label_rect;
62 internal Point location = Point.Empty; // set by the ListView control
63 internal ListView owner;
64 internal bool selected;
66 #endregion Instance Variables
68 #region Public Constructors
69 public ListViewItem ()
71 this.sub_items = new ListViewSubItemCollection (this);
72 this.sub_items.Add ("");
75 public ListViewItem (string text) : this (text, -1)
79 public ListViewItem (string [] items) : this (items, -1)
83 public ListViewItem (ListViewItem.ListViewSubItem [] subItems, int imageIndex)
85 this.sub_items = new ListViewSubItemCollection (this);
86 this.sub_items.AddRange (subItems);
87 this.image_index = imageIndex;
90 public ListViewItem (string text, int imageIndex)
92 this.image_index = imageIndex;
93 this.sub_items = new ListViewSubItemCollection (this);
94 this.sub_items.Add (text);
97 public ListViewItem (string [] items, int imageIndex)
99 this.sub_items = new ListViewSubItemCollection (this);
100 this.sub_items.AddRange (items);
101 this.image_index = imageIndex;
104 public ListViewItem (string [] items, int imageIndex, Color foreColor,
105 Color backColor, Font font)
107 this.sub_items = new ListViewSubItemCollection (this);
108 this.sub_items.AddRange (items);
109 this.image_index = imageIndex;
110 ForeColor = foreColor;
111 BackColor = backColor;
114 #endregion // Public Constructors
116 #region Public Instance Properties
117 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
118 public Color BackColor {
120 if (sub_items.Count > 0)
121 return sub_items[0].BackColor;
124 return owner.BackColor;
126 return ThemeEngine.Current.ColorWindow;
129 set { sub_items[0].BackColor = value; }
133 public Rectangle Bounds {
135 return GetBounds (ItemBoundsPortion.Entire);
139 [DefaultValue (false)]
140 [RefreshProperties (RefreshProperties.Repaint)]
141 public bool Checked {
142 get { return is_checked; }
144 if (is_checked == value)
150 if (owner.CheckedItems.Contains (this) == false) {
151 owner.CheckedItems.list.Add (this);
152 owner.CheckedIndices.list.Add (this.Index);
156 owner.CheckedItems.list.Remove (this);
157 owner.CheckedIndices.list.Remove (this.Index);
160 owner.Invalidate (Bounds);
166 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
167 public bool Focused {
168 get { return is_focused; }
170 if (is_focused == value)
176 owner.Invalidate (Bounds);
181 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
184 if (sub_items.Count > 0)
185 return sub_items[0].Font;
190 return ThemeEngine.Current.DefaultFont;
193 if (sub_items[0].Font == value)
196 sub_items[0].Font = value;
199 owner.Invalidate (Bounds);
203 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
204 public Color ForeColor {
206 if (sub_items.Count > 0)
207 return sub_items[0].ForeColor;
210 return owner.ForeColor;
212 return ThemeEngine.Current.ColorWindowText;
214 set { sub_items[0].ForeColor = value; }
218 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
219 [Editor ("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design,
220 typeof (System.Drawing.Design.UITypeEditor))]
222 [TypeConverter (typeof (ImageIndexConverter))]
223 public int ImageIndex {
224 get { return image_index; }
227 throw new ArgumentException ("Invalid ImageIndex. It must be greater than or equal to -1.");
232 owner.Invalidate (Bounds);
237 public ImageList ImageList {
241 else if (owner.View == View.LargeIcon)
242 return owner.large_image_list;
244 return owner.small_image_list;
254 return owner.Items.IndexOf (this);
259 public ListView ListView {
260 get { return owner; }
264 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
265 public bool Selected {
266 get { return selected; }
269 if (owner.CanMultiselect == false &&
270 owner.SelectedItems.Count > 0) {
271 owner.SelectedItems.Clear ();
272 owner.SelectedIndices.list.Clear ();
277 if (owner.SelectedItems.Contains (this) == false) {
278 owner.SelectedItems.list.Add (this);
279 owner.SelectedIndices.list.Add (this.Index);
283 owner.SelectedItems.list.Remove (this);
284 owner.SelectedIndices.list.Remove (this.Index);
287 owner.Invalidate (Bounds);
293 [Editor ("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design,
294 typeof (System.Drawing.Design.UITypeEditor))]
296 [TypeConverter (typeof (ImageIndexConverter))]
297 public int StateImageIndex {
298 get { return state_image_index; }
300 if (value < -1 || value > 14)
301 throw new ArgumentOutOfRangeException ("Invalid StateImageIndex. It must be in the range of [-1, 14].");
303 state_image_index = value;
307 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
308 public ListViewSubItemCollection SubItems {
309 get { return sub_items; }
313 [DefaultValue (null)]
314 [Localizable (false)]
315 [TypeConverter (typeof (StringConverter))]
322 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
325 if (this.sub_items.Count > 0)
326 return this.sub_items [0].Text;
330 set { this.sub_items [0].Text = value; }
333 [DefaultValue (true)]
334 public bool UseItemStyleForSubItems {
335 get { return use_item_style; }
336 set { use_item_style = value; }
338 #endregion // Public Instance Properties
340 #region Public Instance Methods
341 public void BeginEdit ()
344 // if (owner != null && owner.LabelEdit
345 // && owner.Activation == ItemActivation.Standard)
348 // throw new InvalidOperationException ();
351 public virtual object Clone ()
353 ListViewItem clone = new ListViewItem ();
354 clone.image_index = this.image_index;
355 clone.is_checked = this.is_checked;
356 clone.is_focused = this.is_focused;
357 clone.selected = this.selected;
358 clone.state_image_index = this.state_image_index;
359 clone.sub_items = new ListViewSubItemCollection (this);
361 foreach (ListViewSubItem subItem in this.sub_items)
362 clone.sub_items.Add (subItem.Text, subItem.ForeColor,
363 subItem.BackColor, subItem.Font);
364 clone.tag = this.tag;
365 clone.use_item_style = this.use_item_style;
371 public virtual void EnsureVisible ()
373 if (this.owner != null) {
374 owner.EnsureVisible (owner.Items.IndexOf (this));
378 public Rectangle GetBounds (ItemBoundsPortion portion)
381 return Rectangle.Empty;
383 /* Original Ravi's design calculated all items in a virtual space
384 We convert them real screen positions
388 case ItemBoundsPortion.Icon: {
389 Rectangle rect = icon_rect;
390 rect.X -= owner.h_marker;
391 rect.Y -= owner.v_marker;
395 case ItemBoundsPortion.Label: {
396 Rectangle rect = label_rect;
397 rect.X -= owner.h_marker;
398 rect.Y -= owner.v_marker;
402 case ItemBoundsPortion.ItemOnly: {
403 Rectangle rect = item_rect;
404 rect.X -= owner.h_marker;
405 rect.Y -= owner.v_marker;
409 case ItemBoundsPortion.Entire: {
410 Rectangle rect = entire_rect;
411 rect.X -= owner.h_marker;
412 rect.Y -= owner.v_marker;
417 throw new ArgumentException ("Invalid value for portion.");
421 void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
426 public virtual void Remove ()
429 owner.Items.Remove (this);
433 public override string ToString ()
435 return string.Format ("ListViewItem: {0}", this.Text);
437 #endregion // Public Instance Methods
439 #region Protected Methods
440 protected virtual void Deserialize (SerializationInfo info, StreamingContext context)
445 protected virtual void Serialize (SerializationInfo info, StreamingContext context)
449 #endregion // Protected Methods
451 #region Private Internal Methods
452 internal Rectangle CheckRectReal {
454 Rectangle rect = checkbox_rect;
455 rect.X -= owner.h_marker;
456 rect.Y -= owner.v_marker;
461 internal Rectangle CheckRect {
462 get { return this.checkbox_rect; }
465 internal Rectangle EntireRect {
466 get { return this.entire_rect; }
469 internal Rectangle IconRect {
470 get { return this.icon_rect; }
473 internal Rectangle LabelRect {
474 get { return this.label_rect; }
477 internal void CalcListViewItem ()
480 Size text_size = owner.text_size;
482 if (owner.CheckBoxes)
483 checkbox_rect.Size = owner.CheckBoxSize;
485 checkbox_rect = Rectangle.Empty;
487 checkbox_rect.Location = this.location;
489 switch (owner.View) {
492 // LAMESPEC: MSDN says, "In all views except the details
493 // view of the ListView, this value specifies the same
494 // bounding rectangle as the Entire value." Actually, it
495 // returns same bounding rectangles for Item and Entire
496 // values in the case of Details view.
498 icon_rect.X = checkbox_rect.X + checkbox_rect.Width + 2;
499 icon_rect.Y = checkbox_rect.Y;
501 item_ht = Math.Max (owner.CheckBoxSize.Height + 1,
504 if (owner.SmallImageList != null) {
505 item_ht = Math.Max (item_ht,
506 owner.SmallImageList.ImageSize.Height + 1);
507 icon_rect.Width = owner.SmallImageList.ImageSize.Width;
512 label_rect.Height = checkbox_rect.Height = icon_rect.Height = item_ht;
514 label_rect.X = icon_rect.X + icon_rect.Width;
515 label_rect.Y = icon_rect.Y;
517 if (owner.Columns.Count > 0)
518 label_rect.Width = Math.Max (text_size.Width, owner.Columns[0].Wd);
520 label_rect.Width = text_size.Width;
522 item_rect = entire_rect = Rectangle.Union
523 (Rectangle.Union (checkbox_rect, icon_rect), label_rect);
525 // Take into account the rest of columns. First column
526 // is already taken into account above.
527 for (int i = 1; i < owner.Columns.Count; i++) {
528 item_rect.Width += owner.Columns [i].Wd;
529 entire_rect.Width += owner.Columns [i].Wd;
534 if (owner.LargeImageList != null) {
535 icon_rect.Width = owner.LargeImageList.ImageSize.Width + 16;
536 icon_rect.Height = owner.LargeImageList.ImageSize.Height + 4;
539 icon_rect.Width = 16;
540 icon_rect.Height = 4;
543 if (text_size.Width <= (checkbox_rect.Width + icon_rect.Width)) {
544 icon_rect.X = checkbox_rect.X + checkbox_rect.Width;
545 icon_rect.Y = checkbox_rect.Y;
547 label_rect.X = icon_rect.X + (icon_rect.Width
548 - text_size.Width) / 2;
549 label_rect.Y = Math.Max (checkbox_rect.Bottom,
550 icon_rect.Bottom) + 2;
551 label_rect.Size = text_size;
554 label_rect.X = this.location.X;
556 int centerX = label_rect.X + text_size.Width / 2;
557 icon_rect.X = centerX - icon_rect.Width / 2;
558 checkbox_rect.X = (icon_rect.X - checkbox_rect.Width);
560 icon_rect.Y = checkbox_rect.Y;
562 label_rect.Y = Math.Max (checkbox_rect.Bottom,
563 icon_rect.Bottom) + 2;
564 label_rect.Size = text_size;
567 item_rect = Rectangle.Union (icon_rect, label_rect);
568 entire_rect = Rectangle.Union (item_rect, checkbox_rect);
572 goto case View.SmallIcon;
575 icon_rect.X = checkbox_rect.X + checkbox_rect.Width;
576 icon_rect.Y = checkbox_rect.Y;
578 item_ht = Math.Max (owner.CheckBoxSize.Height, text_size.Height);
580 if (owner.SmallImageList != null) {
581 item_ht = Math.Max (item_ht,
582 owner.SmallImageList.ImageSize.Height + 1);
583 icon_rect.Width = owner.SmallImageList.ImageSize.Width;
588 label_rect.Height = checkbox_rect.Height = icon_rect.Height = item_ht;
590 label_rect.X = icon_rect.X + icon_rect.Width;
591 label_rect.Y = icon_rect.Y;
592 label_rect.Width = text_size.Width;
594 item_rect = Rectangle.Union (icon_rect, label_rect);
595 entire_rect = Rectangle.Union (item_rect, checkbox_rect);
600 #endregion // Private Internal Methods
604 [DefaultProperty ("Text")]
605 [DesignTimeVisible (false)]
607 [ToolboxItem (false)]
608 [TypeConverter (typeof(ListViewSubItemConverter))]
609 public class ListViewSubItem
611 private Color back_color;
613 private Color fore_color;
614 internal ListViewItem owner;
617 #region Public Constructors
618 public ListViewSubItem ()
622 public ListViewSubItem (ListViewItem owner, string text)
623 : this (owner, text, ThemeEngine.Current.ColorWindowText,
624 ThemeEngine.Current.ColorWindow,
625 ThemeEngine.Current.DefaultFont)
629 public ListViewSubItem (ListViewItem owner, string text, Color foreColor,
630 Color backColor, Font font)
634 this.fore_color = foreColor;
635 this.back_color = backColor;
638 #endregion // Public Constructors
640 #region Public Instance Properties
641 public Color BackColor {
642 get { return back_color; }
654 else if (owner != null)
664 public Color ForeColor {
665 get { return fore_color; }
680 #endregion // Public Instance Properties
682 #region Public Methods
683 public void ResetStyle ()
685 font = ThemeEngine.Current.DefaultFont;
686 back_color = ThemeEngine.Current.DefaultControlBackColor;
687 fore_color = ThemeEngine.Current.DefaultControlForeColor;
691 public override string ToString ()
693 return string.Format ("ListViewSubItem {{0}}", text);
695 #endregion // Public Methods
698 #region Private Methods
699 private void Invalidate ()
701 if (owner == null || owner.owner == null)
704 owner.owner.Invalidate ();
706 #endregion // Private Methods
709 public class ListViewSubItemCollection : IList, ICollection, IEnumerable
711 private ArrayList list;
712 internal ListViewItem owner;
714 #region Public Constructors
715 public ListViewSubItemCollection (ListViewItem owner)
718 this.list = new ArrayList ();
720 #endregion // Public Constructors
722 #region Public Properties
724 public virtual int Count {
725 get { return list.Count; }
728 public virtual bool IsReadOnly {
729 get { return false; }
732 public ListViewSubItem this [int index] {
733 get { return (ListViewSubItem) list [index]; }
735 value.owner = this.owner;
736 list [index] = value;
740 bool ICollection.IsSynchronized {
741 get { return list.IsSynchronized; }
744 object ICollection.SyncRoot {
745 get { return list.SyncRoot; }
748 bool IList.IsFixedSize {
749 get { return list.IsFixedSize; }
752 object IList.this [int index] {
753 get { return this [index]; }
755 if (! (value is ListViewSubItem))
756 throw new ArgumentException ("Not of type ListViewSubItem", "value");
757 this [index] = (ListViewSubItem) value;
760 #endregion // Public Properties
762 #region Public Methods
763 public ListViewSubItem Add (ListViewSubItem item)
765 item.owner = this.owner;
770 public ListViewSubItem Add (string text)
772 ListViewSubItem item = new ListViewSubItem (this.owner, text);
777 public ListViewSubItem Add (string text, Color foreColor,
778 Color backColor, Font font)
780 ListViewSubItem item = new ListViewSubItem (this.owner, text,
781 foreColor, backColor, font);
786 public void AddRange (ListViewSubItem [] items)
789 foreach (ListViewSubItem item in items)
793 public void AddRange (string [] items)
796 foreach (string item in items)
800 public void AddRange (string [] items, Color foreColor,
801 Color backColor, Font font)
804 foreach (string item in items)
805 this.Add (item, foreColor, backColor, font);
808 public virtual void Clear ()
813 public bool Contains (ListViewSubItem item)
815 return list.Contains (item);
818 public virtual IEnumerator GetEnumerator ()
820 return list.GetEnumerator ();
823 void ICollection.CopyTo (Array dest, int index)
825 list.CopyTo (dest, index);
828 int IList.Add (object item)
830 if (! (item is ListViewSubItem)) {
831 throw new ArgumentException ("Not of type ListViewSubItem", "item");
834 ListViewSubItem sub_item = (ListViewSubItem) item;
835 sub_item.owner = this.owner;
836 return list.Add (sub_item);
839 bool IList.Contains (object subItem)
841 if (! (subItem is ListViewSubItem)) {
842 throw new ArgumentException ("Not of type ListViewSubItem", "subItem");
845 return this.Contains ((ListViewSubItem) subItem);
848 int IList.IndexOf (object subItem)
850 if (! (subItem is ListViewSubItem)) {
851 throw new ArgumentException ("Not of type ListViewSubItem", "subItem");
854 return this.IndexOf ((ListViewSubItem) subItem);
857 void IList.Insert (int index, object item)
859 if (! (item is ListViewSubItem)) {
860 throw new ArgumentException ("Not of type ListViewSubItem", "item");
863 this.Insert (index, (ListViewSubItem) item);
866 void IList.Remove (object item)
868 if (! (item is ListViewSubItem)) {
869 throw new ArgumentException ("Not of type ListViewSubItem", "item");
872 this.Remove ((ListViewSubItem) item);
875 public int IndexOf (ListViewSubItem subItem)
877 return list.IndexOf (subItem);
880 public void Insert (int index, ListViewSubItem item)
882 item.owner = this.owner;
883 list.Insert (index, item);
886 public void Remove (ListViewSubItem item)
891 public virtual void RemoveAt (int index)
893 list.RemoveAt (index);
895 #endregion // Public Methods
897 #endregion // Subclasses