2007-01-10 Jonathan Pobst <jpobst@novell.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ListViewItem.cs
index b4916428e613e955a48a8505afa1f80af6beff73..f16cd3bb813e0f584c85ff3a43a4a22887bc6e26 100644 (file)
 // Author:
 //      Ravindra (rkumar@novell.com)
 //      Mike Kestner <mkestner@novell.com>
+//      Daniel Nauck (dna(at)mono-project(dot)de)
 
 
 
-// NOT COMPLETE
-
-
 using System.Collections;
 using System.ComponentModel;
 using System.Drawing;
@@ -50,13 +48,18 @@ namespace System.Windows.Forms
                private ListViewSubItemCollection sub_items;
                private object tag;
                private bool use_item_style = true;
-
+#if NET_2_0
+               private ListViewGroup group = null;
+               private string name = String.Empty;
+               private string image_key = String.Empty;
+#endif
                Rectangle bounds;
                Rectangle checkbox_rect;        // calculated by CalcListViewItem method
                Rectangle icon_rect;
                Rectangle item_rect;
                Rectangle label_rect;
                ListView owner;
+               Font font;
                bool selected;
 
                internal int row;
@@ -68,7 +71,7 @@ namespace System.Windows.Forms
                public ListViewItem ()
                {
                        this.sub_items = new ListViewSubItemCollection (this);
-                       this.sub_items.Add ("");                        
+                       this.sub_items.Add ("");
                }
 
                public ListViewItem (string text) : this (text, -1)
@@ -108,8 +111,102 @@ namespace System.Windows.Forms
                        this.image_index = imageIndex;
                        ForeColor = foreColor;
                        BackColor = backColor;
-                       Font = font;
+                       this.font = font;
+               }
+
+#if NET_2_0
+               public ListViewItem(string[] items, string imageKey) : this(items)
+               {
+                       this.ImageKey = imageKey;
+               }
+
+               public ListViewItem(string text, string imageKey) : this(text)
+               {
+                       this.ImageKey = imageKey;
+               }
+
+               public ListViewItem(ListViewSubItem[] subItems, string imageKey) : this()
+               {
+                       this.sub_items.AddRange(subItems);
+                       this.ImageKey = imageKey;
+               }
+
+               public ListViewItem(string[] items, string imageKey, Color foreColor,
+                                       Color backColor, Font font) : this()
+               {
+                       this.sub_items = new ListViewSubItemCollection(this);
+                       this.sub_items.AddRange(items);
+                       ForeColor = foreColor;
+                       BackColor = backColor;
+                       this.font = font;
+                       this.ImageKey = imageKey;
+               }
+
+               public ListViewItem(ListViewGroup group) : this()
+               {
+                       this.group = group;
+               }
+
+               public ListViewItem(string text, ListViewGroup group) : this(text)
+               {
+                       this.group = group;
                }
+
+               public ListViewItem(string[] items, ListViewGroup group) : this(items)
+               {
+                       this.group = group;
+               }
+
+               public ListViewItem(ListViewSubItem[] subItems, int imageIndex, ListViewGroup group)
+                       : this(subItems, imageIndex)
+               {
+                       this.group = group;
+               }
+
+               public ListViewItem(ListViewSubItem[] subItems, string imageKey, ListViewGroup group)
+                       : this(subItems, imageKey)
+               {
+                       this.group = group;
+               }
+
+               public ListViewItem(string text, int imageIndex, ListViewGroup group)
+                       : this(text, imageIndex)
+               {
+                       this.group = group;
+               }
+
+               public ListViewItem(string text, string imageKey, ListViewGroup group)
+                       : this(text, imageKey)
+               {
+                       this.group = group;
+               }
+
+               public ListViewItem(string[] items, int imageIndex, ListViewGroup group)
+                       : this(items, imageIndex)
+               {
+                       this.group = group;
+               }
+
+               public ListViewItem(string[] items, string imageKey, ListViewGroup group)
+                       : this(items, imageKey)
+               {
+                       this.group = group;
+               }
+
+               public ListViewItem(string[] items, int imageIndex, Color foreColor, Color backColor,
+                               Font font, ListViewGroup group)
+                       : this(items, imageIndex, foreColor, backColor, font)
+               {
+                       this.group = group;
+               }
+
+               public ListViewItem(string[] items, string imageKey, Color foreColor, Color backColor,
+                               Font font, ListViewGroup group)
+                       : this(items, imageKey, foreColor, backColor, font)
+               {
+                       this.group = group;
+               }
+#endif
                #endregion      // Public Constructors
 
                #region Public Instance Properties
@@ -146,17 +243,8 @@ namespace System.Windows.Forms
                                is_checked = value;
 
                                if (owner != null) {
-                                       if (is_checked) {
-                                               if (owner.CheckedItems.Contains (this) == false) {
-                                                       owner.CheckedItems.list.Add (this);
-                                                       owner.CheckedIndices.list.Add (this.Index);
-                                               }
-                                       }
-                                       else {
-                                               owner.CheckedItems.list.Remove (this);
-                                               owner.CheckedIndices.list.Remove (this.Index);
-                                       }
-                                       
+                                       // force re-population of list
+                                       owner.CheckedItems.Reset ();
                                        Layout ();
                                }                       
                                Invalidate ();
@@ -173,6 +261,7 @@ namespace System.Windows.Forms
 
                                is_focused = value; 
 
+                               Invalidate ();
                                if (owner != null)
                                        Layout ();
                                Invalidate ();
@@ -183,19 +272,18 @@ namespace System.Windows.Forms
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                public Font Font {
                        get {
-                               if (sub_items.Count > 0)
-                                       return sub_items[0].Font;
-
-                               if (owner != null)
+                               if (font != null)
+                                       return font;
+                               else if (owner != null)
                                        return owner.Font;
 
                                return ThemeEngine.Current.DefaultFont;
                        }
                        set {   
-                               if (sub_items[0].Font == value)
+                               if (font == value)
                                        return;
 
-                               sub_items[0].Font = value; 
+                               font = value; 
 
                                if (owner != null)
                                        Layout ();
@@ -222,7 +310,12 @@ namespace System.Windows.Forms
                [Editor ("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design,
                         typeof (System.Drawing.Design.UITypeEditor))]
                [Localizable (true)]
+#if NET_2_0
+               [RefreshProperties (RefreshProperties.Repaint)]
+               // [TypeConverter (typeof (NoneExcludedImageIndexConverter))]
+#else
                [TypeConverter (typeof (ImageIndexConverter))]
+#endif
                public int ImageIndex {
                        get { return image_index; }
                        set {
@@ -230,6 +323,9 @@ namespace System.Windows.Forms
                                        throw new ArgumentException ("Invalid ImageIndex. It must be greater than or equal to -1.");
                                
                                image_index = value;
+#if NET_2_0
+                               image_key = String.Empty;
+#endif
 
                                if (owner != null)
                                        Layout ();
@@ -237,6 +333,29 @@ namespace System.Windows.Forms
                        }
                }
 
+#if NET_2_0
+               [DefaultValue ("")]
+               [LocalizableAttribute (true)]
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
+               [Editor ("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design,
+                        typeof (System.Drawing.Design.UITypeEditor))]
+               [RefreshProperties (RefreshProperties.Repaint)]
+               // XXX [TypeConverter (typeof (ImageKeyConverter))
+               public string ImageKey {
+                       get {
+                               return image_key;
+                       }
+                       set {
+                               image_key = value == null ? String.Empty : value;
+                               image_index = -1;
+
+                               if (owner != null)
+                                       Layout ();
+                               Invalidate ();
+                       }
+               }
+#endif
+
                [Browsable (false)]
                public ImageList ImageList {
                        get {
@@ -264,6 +383,20 @@ namespace System.Windows.Forms
                        get { return owner; }
                }
 
+#if NET_2_0
+               [Browsable (false)]
+               [Localizable (true)]
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
+               public string Name {
+                       get {
+                               return name;
+                       }
+                       set {
+                               name = value == null ? String.Empty : value;
+                       }
+               }
+#endif
+
                [Browsable (false)]
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
                public bool Selected {
@@ -272,11 +405,16 @@ namespace System.Windows.Forms
                                if (selected == value)
                                        return;
 
-                               selected = value;
-
                                if (owner != null) {
-                                       owner.UpdateSelection (this);
+                                       if (value && !owner.MultiSelect)
+                                               owner.SelectedItems.Clear ();
+                                       selected = value;
+                                       // force re-population of list
+                                       owner.SelectedItems.Reset ();
                                        Layout ();
+                                       owner.OnSelectedIndexChanged ();
+                               } else {
+                                       selected = value;
                                }
                                Invalidate ();
                        }
@@ -286,7 +424,13 @@ namespace System.Windows.Forms
                [Editor ("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design,
                         typeof (System.Drawing.Design.UITypeEditor))]
                [Localizable (true)]
+#if NET_2_0
+               [RefreshProperties (RefreshProperties.Repaint)]
+               // XXX [RelatedImageListAttribute ("ListView.StateImageList")]
+               // XXX [TypeConverter (typeof (NoneExcludedImageIndexConverter))]
+#else
                [TypeConverter (typeof (ImageIndexConverter))]
+#endif
                public int StateImageIndex {
                        get { return state_image_index; }
                        set {
@@ -298,6 +442,10 @@ namespace System.Windows.Forms
                }
 
                [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
+#if NET_2_0
+               [Editor ("System.Windows.Forms.Design.ListViewSubItemCollectionEditor, " + Consts.AssemblySystem_Design,
+                        typeof (System.Drawing.Design.UITypeEditor))]
+#endif
                public ListViewSubItemCollection SubItems {
                        get { return sub_items; }
                }
@@ -318,7 +466,7 @@ namespace System.Windows.Forms
                                if (this.sub_items.Count > 0)
                                        return this.sub_items [0].Text;
                                else
-                                       return "";
+                                       return string.Empty;
                        }
                        set { 
                                if (sub_items [0].Text == value)
@@ -337,11 +485,43 @@ namespace System.Windows.Forms
                        get { return use_item_style; }
                        set { use_item_style = value; }
                }
+
+#if NET_2_0
+               [LocalizableAttribute(true)]
+               [DefaultValue (null)]
+               public ListViewGroup Group {
+                       get { return this.group; }
+                       set
+                       {
+                               if (this.group != value)
+                               {
+                                       if (value != null)
+                                       {
+                                               value.Items.Add(this);
+
+                                               if (this.group != null)
+                                                       this.group.Items.Remove(this);
+
+                                               this.group = value;
+                                       }
+                                       else
+                                       {
+                                               if(this.group != null)
+                                               this.group.Items.Remove(this);
+                                       }
+                               }
+                       }
+               }
+#endif
+
                #endregion      // Public Instance Properties
 
                #region Public Instance Methods
                public void BeginEdit ()
                {
+                       if (owner != null && owner.LabelEdit) {
+                               owner.item_control.BeginEdit (this);
+                       }
                        // FIXME: TODO
                        // if (owner != null && owner.LabelEdit 
                        //    && owner.Activation == ItemActivation.Standard)
@@ -357,6 +537,7 @@ namespace System.Windows.Forms
                        clone.is_checked = this.is_checked;
                        clone.is_focused = this.is_focused;
                        clone.selected = this.selected;
+                       clone.font = this.font;
                        clone.state_image_index = this.state_image_index;
                        clone.sub_items = new ListViewSubItemCollection (this);
                        
@@ -366,6 +547,9 @@ namespace System.Windows.Forms
                        clone.tag = this.tag;
                        clone.use_item_style = this.use_item_style;
                        clone.owner = null;
+#if NET_2_0
+                       clone.name = name;
+#endif
 
                        return clone;
                }
@@ -401,7 +585,7 @@ namespace System.Windows.Forms
                                rect = bounds;
                                rect.X -= owner.h_marker;
                                rect.Y -= owner.v_marker;
-                               return rect;                            
+                               return rect;
 
                        default:
                                throw new ArgumentException ("Invalid value for portion.");
@@ -452,18 +636,6 @@ namespace System.Windows.Forms
                        }
                }
                
-               Rectangle CheckRect {
-                       get { return this.checkbox_rect; }
-               }
-
-               Rectangle IconRect {
-                       get { return this.icon_rect; }
-               }
-
-               Rectangle LabelRect {
-                       get { return this.label_rect; }
-               }
-
                internal Point Location {
                        set {
                                if (bounds.X == value.X && bounds.Y == value.Y)
@@ -552,6 +724,18 @@ namespace System.Windows.Forms
                        case View.LargeIcon:
                                label_rect = icon_rect = Rectangle.Empty;
 
+                               SizeF sz = owner.DeviceContext.MeasureString (Text, Font);
+                               if ((int) sz.Width > text_size.Width) {
+                                       if (Focused) {
+                                               int text_width = text_size.Width;
+                                               StringFormat format = new StringFormat ();
+                                               format.Alignment = StringAlignment.Center;
+                                               sz = owner.DeviceContext.MeasureString (Text, Font, text_width, format);
+                                               text_size.Height = (int) sz.Height;
+                                       } else
+                                               text_size.Height = 2 * (int) sz.Height;
+                               }
+
                                if (owner.LargeImageList != null) {
                                        icon_rect.Width = owner.LargeImageList.ImageSize.Width;
                                        icon_rect.Height = owner.LargeImageList.ImageSize.Height;
@@ -562,7 +746,6 @@ namespace System.Windows.Forms
                                else
                                        checkbox_rect.Y = icon_rect.Height - checkbox_rect.Height;
 
-
                                if (text_size.Width <= icon_rect.Width) {
                                        icon_rect.X = checkbox_rect.Width + 1;
                                        label_rect.X = icon_rect.X + (icon_rect.Width - text_size.Width) / 2;
@@ -602,6 +785,63 @@ namespace System.Windows.Forms
                                total = Rectangle.Union (item_rect, checkbox_rect);
                                bounds.Size = total.Size;
                                break;
+#if NET_2_0
+                       case View.Tile:
+                               label_rect = icon_rect = Rectangle.Empty;
+
+                               if (owner.LargeImageList != null) {
+                                       icon_rect.Width = owner.LargeImageList.ImageSize.Width;
+                                       icon_rect.Height = owner.LargeImageList.ImageSize.Height;
+                               }
+
+                               int separation = 2;
+                               SizeF tsize = owner.DeviceContext.MeasureString (Text, Font);
+
+                               // Set initial values for subitem's layout
+                               int total_height = (int)Math.Ceiling (tsize.Height);
+                               int max_subitem_width = (int)Math.Ceiling (tsize.Width);
+                               SubItems [0].bounds.Height = total_height;
+                       
+                               int count = Math.Min (owner.Columns.Count, SubItems.Count);
+                               for (int i = 1; i < count; i++) { // Ignore first column and first subitem
+                                       ListViewSubItem sub_item = SubItems [i];
+                                       if (sub_item.Text == null || sub_item.Text.Length == 0)
+                                               continue;
+
+                                       tsize = owner.DeviceContext.MeasureString (sub_item.Text, sub_item.Font);
+                               
+                                       int width = (int)Math.Ceiling (tsize.Width);
+                               
+                                       if (width > max_subitem_width)
+                                               max_subitem_width = width;
+                               
+                                       int height = (int)Math.Ceiling (tsize.Height);
+                                       total_height += height + separation;
+                               
+                                       sub_item.bounds.Height = height;
+                       
+                               }
+
+                               label_rect.X = icon_rect.Right + 4;
+                               label_rect.Y = owner.TileSize.Height / 2 - total_height / 2;
+                               label_rect.Width = max_subitem_width;
+                               label_rect.Height = total_height;
+                       
+                               // Second pass for assigning bounds. This time take first subitem into account.
+                               int current_y = label_rect.Y;
+                               for (int j = 0; j < count; j++) {
+                                       ListViewSubItem sub_item = SubItems [j];
+                                       if (sub_item.Text == null || sub_item.Text.Length == 0)
+                                               continue;
+
+                                       sub_item.SetBounds (label_rect.X, current_y, max_subitem_width, sub_item.bounds.Height);
+                                       current_y += sub_item.Bounds.Height + separation;
+                               }
+                               
+                               item_rect = Rectangle.Union (icon_rect, label_rect);
+                               bounds.Size = item_rect.Size;
+                               break;
+#endif
                        }
                        
                }
@@ -620,7 +860,12 @@ namespace System.Windows.Forms
                        private Font font;
                        private Color fore_color;
                        internal ListViewItem owner;
-                       private string text;
+                       private string text = string.Empty;
+#if NET_2_0
+                       private string name = String.Empty;
+                       private object tag;
+                       internal Rectangle bounds;
+#endif
                        
                        #region Public Constructors
                        public ListViewSubItem ()
@@ -629,8 +874,7 @@ namespace System.Windows.Forms
 
                        public ListViewSubItem (ListViewItem owner, string text)
                                : this (owner, text, ThemeEngine.Current.ColorWindowText,
-                                       ThemeEngine.Current.ColorWindow,
-                                       ThemeEngine.Current.DefaultFont)
+                                       ThemeEngine.Current.ColorWindow, null)
                        {
                        }
 
@@ -638,7 +882,7 @@ namespace System.Windows.Forms
                                                Color backColor, Font font)
                        {
                                this.owner = owner;
-                               this.text = text;
+                               Text = text;
                                this.fore_color = foreColor;
                                this.back_color = backColor;
                                this.font = font;
@@ -654,6 +898,20 @@ namespace System.Windows.Forms
                                    }
                        }
 
+#if NET_2_0
+                       public Rectangle Bounds {
+                               get {
+                                       Rectangle retval = bounds;
+                                       if (owner != null) {
+                                               retval.X += owner.Bounds.X;
+                                               retval.Y += owner.Bounds.Y;
+                                       }
+
+                                       return retval;
+                               }
+                       }
+#endif
+
                        [Localizable (true)]
                        public Font Font {
                                get {
@@ -661,9 +919,11 @@ namespace System.Windows.Forms
                                                return font;
                                        else if (owner != null)
                                                return owner.Font;
-                                       return font;
+                                       return ThemeEngine.Current.DefaultFont;
                                }
                                set { 
+                                       if (font == value)
+                                               return;
                                        font = value; 
                                        Invalidate ();
                                    }
@@ -677,11 +937,43 @@ namespace System.Windows.Forms
                                    }
                        }
 
+#if NET_2_0
+                       [Localizable (true)]
+                       public string Name {
+                               get {
+                                       return name;
+                               }
+                               set {
+                                       name = value == null ? String.Empty : value;
+                               }
+                       }
+
+                       [TypeConverter (typeof (StringConverter))]
+                       [BindableAttribute (true)]
+                       [DefaultValue (null)]
+                       [Localizable (false)]
+                       public object Tag {
+                               get {
+                                       return tag;
+                               }
+                               set {
+                                       tag = value;
+                               }
+                       }
+#endif
+
                        [Localizable (true)]
                        public string Text {
                                get { return text; }
                                set { 
-                                       text = value; 
+                                       if(text == value)
+                                               return;
+
+                                       if(value == null)
+                                               text = string.Empty;
+                                       else
+                                               text = value; 
+
                                        Invalidate ();
                                    }
                        }
@@ -711,6 +1003,13 @@ namespace System.Windows.Forms
 
                                owner.owner.Invalidate ();
                        }
+
+#if NET_2_0
+                       internal void SetBounds (int x, int y, int width, int height)
+                       {
+                               bounds = new Rectangle (x, y, width, height);
+                       }
+#endif
                        #endregion // Private Methods
                }
 
@@ -745,6 +1044,18 @@ namespace System.Windows.Forms
                                }
                        }
 
+#if NET_2_0
+                       public virtual ListViewSubItem this [string key] {
+                               get {
+                                       int idx = IndexOfKey (key);
+                                       if (idx == -1)
+                                               return null;
+
+                                       return (ListViewSubItem) list [idx];
+                               }
+                       }
+#endif
+
                        bool ICollection.IsSynchronized {
                                get { return list.IsSynchronized; }
                        }
@@ -793,24 +1104,39 @@ namespace System.Windows.Forms
 
                        public void AddRange (ListViewSubItem [] items)
                        {
-                               list.Clear ();
-                               foreach (ListViewSubItem item in items)
+                               if (items == null)
+                                       throw new ArgumentNullException ("items");
+
+                               foreach (ListViewSubItem item in items) {
+                                       if (item == null)
+                                               continue;
                                        this.Add (item);
+                               }
                        }
 
                        public void AddRange (string [] items)
                        {
-                               list.Clear ();
-                               foreach (string item in items)
+                               if (items == null)
+                                       throw new ArgumentNullException ("items");
+
+                               foreach (string item in items) {
+                                       if (item == null)
+                                               continue;
                                        this.Add (item);
+                               }
                        }
 
                        public void AddRange (string [] items, Color foreColor,
                                              Color backColor, Font font)
                        {
-                               list.Clear ();
-                               foreach (string item in items)
+                               if (items == null)
+                                       throw new ArgumentNullException ("items");
+
+                               foreach (string item in items) {
+                                       if (item == null)
+                                               continue;
                                        this.Add (item, foreColor, backColor, font);
+                               }
                        }
 
                        public void Clear ()
@@ -823,6 +1149,13 @@ namespace System.Windows.Forms
                                return list.Contains (item);
                        }
 
+#if NET_2_0
+                       public virtual bool ContainsKey (string key)
+                       {
+                               return IndexOfKey (key) != -1;
+                       }
+#endif
+
                        public IEnumerator GetEnumerator ()
                        {
                                return list.GetEnumerator ();
@@ -885,6 +1218,22 @@ namespace System.Windows.Forms
                                return list.IndexOf (subItem);
                        }
 
+#if NET_2_0
+                       public virtual int IndexOfKey (string key)
+                       {
+                               if (key == null || key.Length == 0)
+                                       return -1;
+
+                               for (int i = 0; i < list.Count; i++) {
+                                       ListViewSubItem l = (ListViewSubItem) list [i];
+                                       if (String.Compare (l.Name, key, true) == 0)
+                                               return i;
+                               }
+
+                               return -1;
+                       }
+#endif
+
                        public void Insert (int index, ListViewSubItem item)
                        {
                                item.owner = this.owner;
@@ -896,6 +1245,15 @@ namespace System.Windows.Forms
                                list.Remove (item);
                        }
 
+#if NET_2_0
+                       public virtual void RemoveByKey (string key)
+                       {
+                               int idx = IndexOfKey (key);
+                               if (idx != -1)
+                                       RemoveAt (idx);
+                       }
+#endif
+
                        public void RemoveAt (int index)
                        {
                                list.RemoveAt (index);