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;
55 Rectangle checkbox_rect; // calculated by CalcListViewItem method
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 // force re-population of list
151 owner.CheckedItems.Reset ();
159 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
160 public bool Focused {
161 get { return is_focused; }
163 if (is_focused == value)
176 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
181 else if (owner != null)
184 return ThemeEngine.Current.DefaultFont;
198 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
199 public Color ForeColor {
201 if (sub_items.Count > 0)
202 return sub_items[0].ForeColor;
205 return owner.ForeColor;
207 return ThemeEngine.Current.ColorWindowText;
209 set { sub_items[0].ForeColor = value; }
213 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
214 [Editor ("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design,
215 typeof (System.Drawing.Design.UITypeEditor))]
217 [TypeConverter (typeof (ImageIndexConverter))]
218 public int ImageIndex {
219 get { return image_index; }
222 throw new ArgumentException ("Invalid ImageIndex. It must be greater than or equal to -1.");
233 public ImageList ImageList {
237 else if (owner.View == View.LargeIcon)
238 return owner.large_image_list;
240 return owner.small_image_list;
250 return owner.Items.IndexOf (this);
255 public ListView ListView {
256 get { return owner; }
260 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
261 public bool Selected {
262 get { return selected; }
264 if (selected == value)
268 if (value && !owner.MultiSelect)
269 owner.SelectedItems.Clear ();
271 // force re-population of list
272 owner.SelectedItems.Reset ();
274 owner.OnSelectedIndexChanged ();
283 [Editor ("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design,
284 typeof (System.Drawing.Design.UITypeEditor))]
286 [TypeConverter (typeof (ImageIndexConverter))]
287 public int StateImageIndex {
288 get { return state_image_index; }
290 if (value < -1 || value > 14)
291 throw new ArgumentOutOfRangeException ("Invalid StateImageIndex. It must be in the range of [-1, 14].");
293 state_image_index = value;
297 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
298 public ListViewSubItemCollection SubItems {
299 get { return sub_items; }
303 [DefaultValue (null)]
304 [Localizable (false)]
305 [TypeConverter (typeof (StringConverter))]
312 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
315 if (this.sub_items.Count > 0)
316 return this.sub_items [0].Text;
321 if (sub_items [0].Text == value)
324 sub_items [0].Text = value;
332 [DefaultValue (true)]
333 public bool UseItemStyleForSubItems {
334 get { return use_item_style; }
335 set { use_item_style = value; }
337 #endregion // Public Instance Properties
339 #region Public Instance Methods
340 public void BeginEdit ()
342 if (owner != null && owner.LabelEdit) {
343 owner.item_control.BeginEdit (this);
346 // if (owner != null && owner.LabelEdit
347 // && owner.Activation == ItemActivation.Standard)
350 // throw new InvalidOperationException ();
353 public virtual object Clone ()
355 ListViewItem clone = new ListViewItem ();
356 clone.image_index = this.image_index;
357 clone.is_checked = this.is_checked;
358 clone.is_focused = this.is_focused;
359 clone.selected = this.selected;
360 clone.font = this.font;
361 clone.state_image_index = this.state_image_index;
362 clone.sub_items = new ListViewSubItemCollection (this);
364 foreach (ListViewSubItem subItem in this.sub_items)
365 clone.sub_items.Add (subItem.Text, subItem.ForeColor,
366 subItem.BackColor, subItem.Font);
367 clone.tag = this.tag;
368 clone.use_item_style = this.use_item_style;
374 public virtual void EnsureVisible ()
376 if (this.owner != null) {
377 owner.EnsureVisible (owner.Items.IndexOf (this));
381 public Rectangle GetBounds (ItemBoundsPortion portion)
384 return Rectangle.Empty;
389 case ItemBoundsPortion.Icon:
393 case ItemBoundsPortion.Label:
397 case ItemBoundsPortion.ItemOnly:
401 case ItemBoundsPortion.Entire:
403 rect.X -= owner.h_marker;
404 rect.Y -= owner.v_marker;
408 throw new ArgumentException ("Invalid value for portion.");
411 rect.X += bounds.X - owner.h_marker;
412 rect.Y += bounds.Y - owner.v_marker;
416 void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
421 public virtual void Remove ()
424 owner.Items.Remove (this);
428 public override string ToString ()
430 return string.Format ("ListViewItem: {0}", this.Text);
432 #endregion // Public Instance Methods
434 #region Protected Methods
435 protected virtual void Deserialize (SerializationInfo info, StreamingContext context)
440 protected virtual void Serialize (SerializationInfo info, StreamingContext context)
444 #endregion // Protected Methods
446 #region Private Internal Methods
447 internal Rectangle CheckRectReal {
449 Rectangle rect = checkbox_rect;
450 rect.X += bounds.X - owner.h_marker;
451 rect.Y += bounds.Y - owner.v_marker;
456 Rectangle CheckRect {
457 get { return this.checkbox_rect; }
461 get { return this.icon_rect; }
464 Rectangle LabelRect {
465 get { return this.label_rect; }
468 internal Point Location {
470 if (bounds.X == value.X && bounds.Y == value.Y)
473 Rectangle prev = Bounds;
477 if (prev != Rectangle.Empty)
478 owner.item_control.Invalidate (prev);
479 owner.item_control.Invalidate (Bounds);
484 internal ListView Owner {
496 private void Invalidate ()
498 if (owner == null || owner.item_control == null)
501 owner.item_control.Invalidate (Bounds);
504 internal void Layout ()
508 Size text_size = owner.text_size;
510 checkbox_rect = Rectangle.Empty;
511 if (owner.CheckBoxes)
512 checkbox_rect.Size = owner.CheckBoxSize;
514 switch (owner.View) {
516 // LAMESPEC: MSDN says, "In all views except the details
517 // view of the ListView, this value specifies the same
518 // bounding rectangle as the Entire value." Actually, it
519 // returns same bounding rectangles for Item and Entire
520 // values in the case of Details view.
522 icon_rect = label_rect = Rectangle.Empty;
523 icon_rect.X = checkbox_rect.Width + 2;
524 item_ht = Math.Max (owner.CheckBoxSize.Height, text_size.Height);
526 if (owner.SmallImageList != null) {
527 item_ht = Math.Max (item_ht, owner.SmallImageList.ImageSize.Height);
528 icon_rect.Width = owner.SmallImageList.ImageSize.Width;
531 label_rect.Height = icon_rect.Height = item_ht;
532 checkbox_rect.Y = item_ht - checkbox_rect.Height;
534 label_rect.X = icon_rect.Right + 1;
536 if (owner.Columns.Count > 0)
537 label_rect.Width = Math.Max (text_size.Width, owner.Columns[0].Wd);
539 label_rect.Width = text_size.Width;
541 item_rect = total = Rectangle.Union
542 (Rectangle.Union (checkbox_rect, icon_rect), label_rect);
543 bounds.Size = total.Size;
545 // Take into account the rest of columns. First column
546 // is already taken into account above.
547 for (int i = 1; i < owner.Columns.Count; i++) {
548 item_rect.Width += owner.Columns [i].Wd;
549 bounds.Width += owner.Columns [i].Wd;
554 label_rect = icon_rect = Rectangle.Empty;
556 SizeF sz = owner.DeviceContext.MeasureString (Text, Font);
557 if ((int) sz.Width > text_size.Width) {
559 int text_width = text_size.Width;
560 StringFormat format = new StringFormat ();
561 format.Alignment = StringAlignment.Center;
562 sz = owner.DeviceContext.MeasureString (Text, Font, text_width, format);
563 text_size.Height = (int) sz.Height;
565 text_size.Height = 2 * (int) sz.Height;
568 if (owner.LargeImageList != null) {
569 icon_rect.Width = owner.LargeImageList.ImageSize.Width;
570 icon_rect.Height = owner.LargeImageList.ImageSize.Height;
573 if (checkbox_rect.Height > icon_rect.Height)
574 icon_rect.Y = checkbox_rect.Height - icon_rect.Height;
576 checkbox_rect.Y = icon_rect.Height - checkbox_rect.Height;
578 if (text_size.Width <= icon_rect.Width) {
579 icon_rect.X = checkbox_rect.Width + 1;
580 label_rect.X = icon_rect.X + (icon_rect.Width - text_size.Width) / 2;
581 label_rect.Y = icon_rect.Bottom + 2;
582 label_rect.Size = text_size;
584 int centerX = text_size.Width / 2;
585 icon_rect.X = checkbox_rect.Width + 1 + centerX - icon_rect.Width / 2;
586 label_rect.X = checkbox_rect.Width + 1;
587 label_rect.Y = icon_rect.Bottom + 2;
588 label_rect.Size = text_size;
591 item_rect = Rectangle.Union (icon_rect, label_rect);
592 total = Rectangle.Union (item_rect, checkbox_rect);
593 bounds.Size = total.Size;
598 label_rect = icon_rect = Rectangle.Empty;
599 icon_rect.X = checkbox_rect.Width + 1;
600 item_ht = Math.Max (owner.CheckBoxSize.Height, text_size.Height);
602 if (owner.SmallImageList != null) {
603 item_ht = Math.Max (item_ht, owner.SmallImageList.ImageSize.Height);
604 icon_rect.Width = owner.SmallImageList.ImageSize.Width;
605 icon_rect.Height = owner.SmallImageList.ImageSize.Height;
608 checkbox_rect.Y = item_ht - checkbox_rect.Height;
609 label_rect.X = icon_rect.Right + 1;
610 label_rect.Width = text_size.Width;
611 label_rect.Height = icon_rect.Height = item_ht;
613 item_rect = Rectangle.Union (icon_rect, label_rect);
614 total = Rectangle.Union (item_rect, checkbox_rect);
615 bounds.Size = total.Size;
620 #endregion // Private Internal Methods
624 [DefaultProperty ("Text")]
625 [DesignTimeVisible (false)]
627 [ToolboxItem (false)]
628 [TypeConverter (typeof(ListViewSubItemConverter))]
629 public class ListViewSubItem
631 private Color back_color;
633 private Color fore_color;
634 internal ListViewItem owner;
637 #region Public Constructors
638 public ListViewSubItem ()
642 public ListViewSubItem (ListViewItem owner, string text)
643 : this (owner, text, ThemeEngine.Current.ColorWindowText,
644 ThemeEngine.Current.ColorWindow, null)
648 public ListViewSubItem (ListViewItem owner, string text, Color foreColor,
649 Color backColor, Font font)
653 this.fore_color = foreColor;
654 this.back_color = backColor;
657 #endregion // Public Constructors
659 #region Public Instance Properties
660 public Color BackColor {
661 get { return back_color; }
673 else if (owner != null)
675 return ThemeEngine.Current.DefaultFont;
685 public Color ForeColor {
686 get { return fore_color; }
701 #endregion // Public Instance Properties
703 #region Public Methods
704 public void ResetStyle ()
706 font = ThemeEngine.Current.DefaultFont;
707 back_color = ThemeEngine.Current.DefaultControlBackColor;
708 fore_color = ThemeEngine.Current.DefaultControlForeColor;
712 public override string ToString ()
714 return string.Format ("ListViewSubItem {{0}}", text);
716 #endregion // Public Methods
719 #region Private Methods
720 private void Invalidate ()
722 if (owner == null || owner.owner == null)
725 owner.owner.Invalidate ();
727 #endregion // Private Methods
730 public class ListViewSubItemCollection : IList, ICollection, IEnumerable
732 private ArrayList list;
733 internal ListViewItem owner;
735 #region Public Constructors
736 public ListViewSubItemCollection (ListViewItem owner)
739 this.list = new ArrayList ();
741 #endregion // Public Constructors
743 #region Public Properties
746 get { return list.Count; }
749 public bool IsReadOnly {
750 get { return false; }
753 public ListViewSubItem this [int index] {
754 get { return (ListViewSubItem) list [index]; }
756 value.owner = this.owner;
757 list [index] = value;
761 bool ICollection.IsSynchronized {
762 get { return list.IsSynchronized; }
765 object ICollection.SyncRoot {
766 get { return list.SyncRoot; }
769 bool IList.IsFixedSize {
770 get { return list.IsFixedSize; }
773 object IList.this [int index] {
774 get { return this [index]; }
776 if (! (value is ListViewSubItem))
777 throw new ArgumentException ("Not of type ListViewSubItem", "value");
778 this [index] = (ListViewSubItem) value;
781 #endregion // Public Properties
783 #region Public Methods
784 public ListViewSubItem Add (ListViewSubItem item)
786 item.owner = this.owner;
791 public ListViewSubItem Add (string text)
793 ListViewSubItem item = new ListViewSubItem (this.owner, text);
798 public ListViewSubItem Add (string text, Color foreColor,
799 Color backColor, Font font)
801 ListViewSubItem item = new ListViewSubItem (this.owner, text,
802 foreColor, backColor, font);
807 public void AddRange (ListViewSubItem [] items)
810 foreach (ListViewSubItem item in items)
814 public void AddRange (string [] items)
817 foreach (string item in items)
821 public void AddRange (string [] items, Color foreColor,
822 Color backColor, Font font)
825 foreach (string item in items)
826 this.Add (item, foreColor, backColor, font);
834 public bool Contains (ListViewSubItem item)
836 return list.Contains (item);
839 public IEnumerator GetEnumerator ()
841 return list.GetEnumerator ();
844 void ICollection.CopyTo (Array dest, int index)
846 list.CopyTo (dest, index);
849 int IList.Add (object item)
851 if (! (item is ListViewSubItem)) {
852 throw new ArgumentException ("Not of type ListViewSubItem", "item");
855 ListViewSubItem sub_item = (ListViewSubItem) item;
856 sub_item.owner = this.owner;
857 return list.Add (sub_item);
860 bool IList.Contains (object subItem)
862 if (! (subItem is ListViewSubItem)) {
863 throw new ArgumentException ("Not of type ListViewSubItem", "subItem");
866 return this.Contains ((ListViewSubItem) subItem);
869 int IList.IndexOf (object subItem)
871 if (! (subItem is ListViewSubItem)) {
872 throw new ArgumentException ("Not of type ListViewSubItem", "subItem");
875 return this.IndexOf ((ListViewSubItem) subItem);
878 void IList.Insert (int index, object item)
880 if (! (item is ListViewSubItem)) {
881 throw new ArgumentException ("Not of type ListViewSubItem", "item");
884 this.Insert (index, (ListViewSubItem) item);
887 void IList.Remove (object item)
889 if (! (item is ListViewSubItem)) {
890 throw new ArgumentException ("Not of type ListViewSubItem", "item");
893 this.Remove ((ListViewSubItem) item);
896 public int IndexOf (ListViewSubItem subItem)
898 return list.IndexOf (subItem);
901 public void Insert (int index, ListViewSubItem item)
903 item.owner = this.owner;
904 list.Insert (index, item);
907 public void Remove (ListViewSubItem item)
912 public void RemoveAt (int index)
914 list.RemoveAt (index);
916 #endregion // Public Methods
918 #endregion // Subclasses