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 Color back_color = Color.Empty;
49 private Font font = null;
50 private Color fore_color = Color.Empty;
51 private int image_index = -1;
52 private bool is_checked = false;
53 private bool is_focused = false;
54 private int state_image_index = -1;
55 private ListViewSubItemCollection sub_items;
57 private bool use_item_style = true;
60 internal Rectangle checkbox_rect; // calculated by CalcListViewItem method
61 internal Rectangle entire_rect;
62 internal Rectangle icon_rect;
63 internal Rectangle item_rect;
64 internal Rectangle label_rect;
65 internal Point location = Point.Empty; // set by the ListView control
66 internal ListView owner;
67 internal bool selected;
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 this.fore_color = foreColor;
114 this.back_color = backColor;
117 #endregion // Public Constructors
119 #region Public Instance Properties
120 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
121 public Color BackColor {
123 if (! back_color.IsEmpty)
125 else if (owner != null)
126 return owner.BackColor;
128 return ThemeEngine.Current.ColorWindow;
130 set { this.back_color = value; }
134 public Rectangle Bounds {
136 return GetBounds (ItemBoundsPortion.Entire);
140 [DefaultValue (false)]
141 [RefreshProperties (RefreshProperties.Repaint)]
142 public bool Checked {
143 get { return is_checked; }
144 set { is_checked = value; }
148 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
149 public bool Focused {
150 get { return is_focused; }
151 set { is_focused = value; }
155 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
160 else if (owner != null)
163 return ThemeEngine.Current.DefaultFont;
165 set { font = value; }
168 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
169 public Color ForeColor {
171 if (! fore_color.IsEmpty)
173 else if (owner != null)
174 return owner.ForeColor;
176 return ThemeEngine.Current.ColorWindowText;
178 set { fore_color = value; }
182 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
183 [Editor ("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design,
184 typeof (System.Drawing.Design.UITypeEditor))]
186 [TypeConverter (typeof (ImageIndexConverter))]
187 public int ImageIndex {
188 get { return image_index; }
191 throw new ArgumentException ("Invalid ImageIndex. It must be greater than or equal to -1.");
197 public ImageList ImageList {
201 else if (owner.View == View.LargeIcon)
202 return owner.large_image_list;
204 return owner.small_image_list;
214 return owner.Items.IndexOf (this);
219 public ListView ListView {
220 get { return owner; }
224 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
225 public bool Selected {
226 get { return selected; }
229 if (owner.CanMultiselect == false &&
230 owner.SelectedItems.Count > 0) {
231 owner.SelectedItems.Clear ();
232 owner.SelectedIndices.list.Clear ();
237 //do we need !owner.SelectedItems.Contains (this))
238 owner.SelectedItems.list.Add (this);
239 owner.SelectedIndices.list.Add (this.Index);
242 owner.SelectedItems.list.Remove (this);
243 owner.SelectedIndices.list.Remove (this.Index);
250 [Editor ("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design,
251 typeof (System.Drawing.Design.UITypeEditor))]
253 [TypeConverter (typeof (ImageIndexConverter))]
254 public int StateImageIndex {
255 get { return state_image_index; }
257 if (value < -1 || value > 14)
258 throw new ArgumentOutOfRangeException ("Invalid StateImageIndex. It must be in the range of [-1, 14].");
260 state_image_index = value;
264 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
265 public ListViewSubItemCollection SubItems {
266 get { return sub_items; }
270 [DefaultValue (null)]
271 [Localizable (false)]
272 [TypeConverter (typeof (StringConverter))]
279 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
282 if (this.sub_items.Count > 0)
283 return this.sub_items [0].Text;
287 set { this.sub_items [0].Text = value; }
290 [DefaultValue (true)]
291 public bool UseItemStyleForSubItems {
292 get { return use_item_style; }
293 set { use_item_style = value; }
295 #endregion // Public Instance Properties
297 #region Public Instance Methods
298 public void BeginEdit ()
301 // if (owner != null && owner.LabelEdit
302 // && owner.Activation == ItemActivation.Standard)
305 // throw new InvalidOperationException ();
308 public virtual object Clone ()
310 ListViewItem clone = new ListViewItem ();
311 clone.back_color = this.BackColor;
312 clone.font = this.Font;
313 clone.fore_color = this.ForeColor;
314 clone.image_index = this.image_index;
315 clone.is_checked = this.is_checked;
316 clone.is_focused = this.is_focused;
317 clone.selected = this.selected;
318 clone.state_image_index = this.state_image_index;
319 clone.sub_items = new ListViewSubItemCollection (this);
320 foreach (ListViewSubItem subItem in this.sub_items)
321 clone.sub_items.Add (subItem.Text, subItem.ForeColor,
322 subItem.BackColor, subItem.Font);
323 clone.tag = this.tag;
324 clone.use_item_style = this.use_item_style;
330 public virtual void EnsureVisible ()
332 if (this.owner != null) {
333 owner.EnsureVisible (owner.Items.IndexOf (this));
337 public Rectangle GetBounds (ItemBoundsPortion portion)
340 return Rectangle.Empty;
342 // should we check for dirty flag to optimize this ?
347 case ItemBoundsPortion.Icon:
350 case ItemBoundsPortion.Label:
353 case ItemBoundsPortion.ItemOnly:
356 case ItemBoundsPortion.Entire:
360 throw new ArgumentException ("Invalid value for portion.");
364 void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
369 public virtual void Remove ()
372 owner.Items.Remove (this);
376 public override string ToString ()
378 return string.Format ("ListViewItem: {{0}}", this.Text);
380 #endregion // Public Instance Methods
382 #region Protected Methods
383 protected virtual void Deserialize (SerializationInfo info, StreamingContext context)
388 protected virtual void Serialize (SerializationInfo info, StreamingContext context)
392 #endregion // Protected Methods
394 #region Private Internal Methods
395 internal Rectangle CheckRect {
396 get { return this.checkbox_rect; }
399 internal Rectangle EntireRect {
400 get { return this.entire_rect; }
403 internal Rectangle IconRect {
404 get { return this.icon_rect; }
407 internal Rectangle LabelRect {
408 get { return this.label_rect; }
411 internal void CalcListViewItem ()
414 Size text_size = owner.text_size;
416 if (owner.CheckBoxes)
417 checkbox_rect.Size = owner.CheckBoxSize;
419 checkbox_rect = Rectangle.Empty;
421 checkbox_rect.Location = this.location;
423 switch (owner.View) {
426 // LAMESPEC: MSDN says, "In all views except the details
427 // view of the ListView, this value specifies the same
428 // bounding rectangle as the Entire value." Actually, it
429 // returns same bounding rectangles for Item and Entire
430 // values in the case of Details view.
432 icon_rect.X = checkbox_rect.X + checkbox_rect.Width + 2;
433 icon_rect.Y = checkbox_rect.Y;
435 item_ht = Math.Max (owner.CheckBoxSize.Height + 1,
438 if (owner.SmallImageList != null) {
439 item_ht = Math.Max (item_ht,
440 owner.SmallImageList.ImageSize.Height + 1);
441 icon_rect.Width = owner.SmallImageList.ImageSize.Width;
446 label_rect.Height = checkbox_rect.Height = icon_rect.Height = item_ht;
448 label_rect.X = icon_rect.X + icon_rect.Width;
449 label_rect.Y = icon_rect.Y;
451 if (owner.Columns.Count > 0)
452 label_rect.Width = Math.Max (text_size.Width, owner.Columns[0].Wd);
454 label_rect.Width = text_size.Width;
456 item_rect = entire_rect = Rectangle.Union
457 (Rectangle.Union (checkbox_rect, icon_rect), label_rect);
459 // Take into account the rest of columns. First column
460 // is already taken into account above.
461 for (int i = 1; i < owner.Columns.Count; i++) {
462 item_rect.Width += owner.Columns [i].Wd;
463 entire_rect.Width += owner.Columns [i].Wd;
468 if (owner.LargeImageList != null) {
469 icon_rect.Width = owner.LargeImageList.ImageSize.Width + 16;
470 icon_rect.Height = owner.LargeImageList.ImageSize.Height + 4;
473 icon_rect.Width = 16;
474 icon_rect.Height = 4;
477 if (text_size.Width <= (checkbox_rect.Width + icon_rect.Width)) {
478 icon_rect.X = checkbox_rect.X + checkbox_rect.Width;
479 icon_rect.Y = checkbox_rect.Y;
481 label_rect.X = icon_rect.X + (icon_rect.Width
482 - text_size.Width) / 2;
483 label_rect.Y = Math.Max (checkbox_rect.Bottom,
484 icon_rect.Bottom) + 2;
485 label_rect.Size = text_size;
488 label_rect.X = this.location.X;
490 int centerX = label_rect.X + text_size.Width / 2;
491 icon_rect.X = centerX - icon_rect.Width / 2;
492 checkbox_rect.X = (icon_rect.X - checkbox_rect.Width);
494 icon_rect.Y = checkbox_rect.Y;
496 label_rect.Y = Math.Max (checkbox_rect.Bottom,
497 icon_rect.Bottom) + 2;
498 label_rect.Size = text_size;
501 item_rect = Rectangle.Union (icon_rect, label_rect);
502 entire_rect = Rectangle.Union (item_rect, checkbox_rect);
506 goto case View.SmallIcon;
509 icon_rect.X = checkbox_rect.X + checkbox_rect.Width;
510 icon_rect.Y = checkbox_rect.Y;
512 item_ht = Math.Max (owner.CheckBoxSize.Height, text_size.Height);
514 if (owner.SmallImageList != null) {
515 item_ht = Math.Max (item_ht,
516 owner.SmallImageList.ImageSize.Height + 1);
517 icon_rect.Width = owner.SmallImageList.ImageSize.Width;
522 label_rect.Height = checkbox_rect.Height = icon_rect.Height = item_ht;
524 label_rect.X = icon_rect.X + icon_rect.Width;
525 label_rect.Y = icon_rect.Y;
526 label_rect.Width = text_size.Width;
528 item_rect = Rectangle.Union (icon_rect, label_rect);
529 entire_rect = Rectangle.Union (item_rect, checkbox_rect);
533 #endregion // Private Internal Methods
537 [DefaultProperty ("Text")]
538 [DesignTimeVisible (false)]
540 [ToolboxItem (false)]
541 [TypeConverter (typeof(ListViewSubItemConverter))]
542 public class ListViewSubItem
544 private Color back_color;
546 private Color fore_color;
547 internal ListViewItem owner;
550 #region Public Constructors
551 public ListViewSubItem ()
555 public ListViewSubItem (ListViewItem owner, string text)
556 : this (owner, text, ThemeEngine.Current.ColorWindowText,
557 ThemeEngine.Current.ColorWindow,
558 ThemeEngine.Current.DefaultFont)
562 public ListViewSubItem (ListViewItem owner, string text, Color foreColor,
563 Color backColor, Font font)
567 this.fore_color = foreColor;
568 this.back_color = backColor;
571 #endregion // Public Constructors
573 #region Public Instance Properties
574 public Color BackColor {
575 get { return back_color; }
576 set { back_color = value; }
584 else if (owner != null)
588 set { font = value; }
591 public Color ForeColor {
592 get { return fore_color; }
593 set { fore_color = value; }
599 set { text = value; }
601 #endregion // Public Instance Properties
603 #region Public Methods
604 public void ResetStyle ()
606 font = ThemeEngine.Current.DefaultFont;
607 back_color = ThemeEngine.Current.DefaultControlBackColor;
608 fore_color = ThemeEngine.Current.DefaultControlForeColor;
611 public override string ToString ()
613 return string.Format ("ListViewSubItem {{0}}", text);
615 #endregion // Public Methods
618 public class ListViewSubItemCollection : IList, ICollection, IEnumerable
620 private ArrayList list;
621 internal ListViewItem owner;
623 #region Public Constructors
624 public ListViewSubItemCollection (ListViewItem owner)
627 this.list = new ArrayList ();
629 #endregion // Public Constructors
631 #region Public Properties
633 public virtual int Count {
634 get { return list.Count; }
637 public virtual bool IsReadOnly {
638 get { return false; }
641 public ListViewSubItem this [int index] {
642 get { return (ListViewSubItem) list [index]; }
644 value.owner = this.owner;
645 list [index] = value;
649 bool ICollection.IsSynchronized {
650 get { return list.IsSynchronized; }
653 object ICollection.SyncRoot {
654 get { return list.SyncRoot; }
657 bool IList.IsFixedSize {
658 get { return list.IsFixedSize; }
661 object IList.this [int index] {
662 get { return this [index]; }
664 if (! (value is ListViewSubItem))
665 throw new ArgumentException ("Not of type ListViewSubItem", "value");
666 this [index] = (ListViewSubItem) value;
669 #endregion // Public Properties
671 #region Public Methods
672 public ListViewSubItem Add (ListViewSubItem item)
674 item.owner = this.owner;
679 public ListViewSubItem Add (string text)
681 ListViewSubItem item = new ListViewSubItem (this.owner, text);
686 public ListViewSubItem Add (string text, Color foreColor,
687 Color backColor, Font font)
689 ListViewSubItem item = new ListViewSubItem (this.owner, text,
690 foreColor, backColor, font);
695 public void AddRange (ListViewSubItem [] items)
698 foreach (ListViewSubItem item in items)
702 public void AddRange (string [] items)
705 foreach (string item in items)
709 public void AddRange (string [] items, Color foreColor,
710 Color backColor, Font font)
713 foreach (string item in items)
714 this.Add (item, foreColor, backColor, font);
717 public virtual void Clear ()
722 public bool Contains (ListViewSubItem item)
724 return list.Contains (item);
727 public virtual IEnumerator GetEnumerator ()
729 return list.GetEnumerator ();
732 void ICollection.CopyTo (Array dest, int index)
734 list.CopyTo (dest, index);
737 int IList.Add (object item)
739 if (! (item is ListViewSubItem)) {
740 throw new ArgumentException ("Not of type ListViewSubItem", "item");
743 ListViewSubItem sub_item = (ListViewSubItem) item;
744 sub_item.owner = this.owner;
745 return list.Add (sub_item);
748 bool IList.Contains (object subItem)
750 if (! (subItem is ListViewSubItem)) {
751 throw new ArgumentException ("Not of type ListViewSubItem", "subItem");
754 return this.Contains ((ListViewSubItem) subItem);
757 int IList.IndexOf (object subItem)
759 if (! (subItem is ListViewSubItem)) {
760 throw new ArgumentException ("Not of type ListViewSubItem", "subItem");
763 return this.IndexOf ((ListViewSubItem) subItem);
766 void IList.Insert (int index, object item)
768 if (! (item is ListViewSubItem)) {
769 throw new ArgumentException ("Not of type ListViewSubItem", "item");
772 this.Insert (index, (ListViewSubItem) item);
775 void IList.Remove (object item)
777 if (! (item is ListViewSubItem)) {
778 throw new ArgumentException ("Not of type ListViewSubItem", "item");
781 this.Remove ((ListViewSubItem) item);
784 public int IndexOf (ListViewSubItem subItem)
786 return list.IndexOf (subItem);
789 public void Insert (int index, ListViewSubItem item)
791 item.owner = this.owner;
792 list.Insert (index, item);
795 public void Remove (ListViewSubItem item)
800 public virtual void RemoveAt (int index)
802 list.RemoveAt (index);
804 #endregion // Public Methods
806 #endregion // Subclasses