* ImageList.cs: When the image stream is set pull all the images
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / CheckedListBox.cs
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:
8 //
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 //
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.
19 //
20 // Copyright (c) 2004-2005 Novell, Inc.
21 //
22 // Authors:
23 //      Jordi Mas i Hernandez, jordi@ximian.com
24 //
25 //
26
27 // NOT COMPLETE
28
29 using System;
30 using System.Drawing;
31 using System.Collections;
32 using System.ComponentModel;
33 using System.Reflection;
34
35 namespace System.Windows.Forms
36 {
37
38         public class CheckedListBox : ListBox
39         {
40                 private CheckedIndexCollection checked_indices;
41                 private CheckedItemCollection checked_items;
42                 private bool check_onclick;
43                 private bool three_dcheckboxes;
44                 
45                 public CheckedListBox ()
46                 {
47                         items = new CheckedListBox.ObjectCollection (this);
48                         checked_indices = new CheckedIndexCollection (this);
49                         checked_items = new CheckedItemCollection (this);
50                         check_onclick = false;
51                         three_dcheckboxes = false;
52                         listbox_info.item_height = FontHeight + 2;
53                 }
54
55                 #region events
56                 [Browsable (false)]
57                 [EditorBrowsable (EditorBrowsableState.Never)]
58                 public new event EventHandler Click;
59                 
60                 [Browsable (false)]
61                 [EditorBrowsable (EditorBrowsableState.Never)]
62                 public new event EventHandler DataSourceChanged;
63                 
64                 [Browsable (false)]
65                 [EditorBrowsable (EditorBrowsableState.Never)]
66                 public new event EventHandler DisplayMemberChanged;
67                 
68                 [Browsable (false)]
69                 [EditorBrowsable (EditorBrowsableState.Never)]
70                 public new event DrawItemEventHandler DrawItem;
71                 public event ItemCheckEventHandler ItemCheck;
72                 
73                 [Browsable (false)]
74                 [EditorBrowsable (EditorBrowsableState.Never)]
75                 public new event MeasureItemEventHandler MeasureItem;
76                 
77                 [Browsable (false)]
78                 [EditorBrowsable (EditorBrowsableState.Never)]
79                 public new event EventHandler ValueMemberChanged;
80                 #endregion Events
81
82                 #region Public Properties
83                 
84                 [Browsable (false)]
85                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]\r
86                 public CheckedListBox.CheckedIndexCollection CheckedIndices {
87                         get {return checked_indices; }
88                 }
89                                 
90                 [Browsable (false)]
91                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]\r
92                 public CheckedListBox.CheckedItemCollection CheckedItems {
93                         get {return checked_items; }
94                 }
95
96                 [DefaultValue (false)]
97                 public bool CheckOnClick {
98                         get { return check_onclick; }
99                         set { check_onclick = value; }
100                 }
101
102                 protected override CreateParams CreateParams {
103                         get { return base.CreateParams;}
104                 }
105                 
106                 [EditorBrowsable (EditorBrowsableState.Never)]
107                 [Browsable (false)]\r
108                 public new object DataSource {
109                         get { return base.DataSource; }
110                         set { DataSource = value; }
111                 }
112
113                 [EditorBrowsable (EditorBrowsableState.Never)]
114                 [Browsable (false)]
115                 public new string DisplayMember {
116                         get { throw new NotImplementedException (); }
117                         set { throw new NotImplementedException (); }
118                 }
119
120                 [Browsable (false)]
121                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
122                 [EditorBrowsable (EditorBrowsableState.Never)]
123                 public override DrawMode DrawMode {
124                         get { return DrawMode.Normal; }
125                         set { /* Not possible */ }
126                 }
127
128                 [Browsable (false)]
129                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
130                 [EditorBrowsable (EditorBrowsableState.Never)]
131                 public override int ItemHeight {
132                         get { return listbox_info.item_height; }
133                         set { /* Not possible */ }
134                 }
135
136                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
137                 [Localizable (true)]
138                 [Editor ("System.Windows.Forms.Design.ListControlStringCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
139                 public new CheckedListBox.ObjectCollection Items {
140                         get { return (CheckedListBox.ObjectCollection) base.Items; }
141                 }
142
143                 public override SelectionMode SelectionMode {
144                         get { return base.SelectionMode; }
145                         set {
146                                 if (value == SelectionMode.MultiSimple || value == SelectionMode.MultiExtended)
147                                         throw new InvalidEnumArgumentException ("Multi selection modes not supported");
148
149                                 base.SelectionMode = value;
150                         }
151                 }
152
153                 [DefaultValue (false)]
154                 public bool ThreeDCheckBoxes {
155                         get { return three_dcheckboxes; }
156                         set {
157                                 if (three_dcheckboxes == value)
158                                         return;
159
160                                 three_dcheckboxes = value;
161                                 Refresh ();
162                         }
163                 }
164
165                 [Browsable (false)]
166                 [EditorBrowsable (EditorBrowsableState.Never)]
167                 public new string ValueMember {
168                         get { return base.ValueMember; }
169                         set { base.ValueMember = value; }                       
170                 }
171                 
172                 #endregion Public Properties
173
174                 #region Public Methods
175
176                 protected override AccessibleObject CreateAccessibilityInstance ()
177                 {
178                         throw new NotImplementedException ();
179                 }
180                 \r
181                 protected override ListBox.ObjectCollection CreateItemCollection ()
182                 {
183                         return new ObjectCollection (this);
184                 }
185
186                 public bool GetItemChecked (int index)
187                 {
188                         return (GetItemCheckState (index) == CheckState.Checked);
189                 }
190                 \r
191                 public CheckState GetItemCheckState (int index)
192                 {
193                         if (index < 0 || index >= Items.Count)
194                                 throw new ArgumentOutOfRangeException ("Index of out range");
195
196                         return (Items.GetListBoxItem (index)).State;
197                 }
198
199                 protected override void OnBackColorChanged (EventArgs e)
200                 {
201                         base.OnBackColorChanged (e);
202                 }
203
204                 protected override void OnClick (EventArgs e)
205                 {
206                         base.OnClick (e);
207                         
208                         if (check_onclick) {
209                                 if (focused_item != -1) {
210                                         SetItemChecked (focused_item, !GetItemChecked (focused_item));
211                                 }
212                         }
213                         
214                         if (Click != null)                      
215                                 Click (this, EventArgs.Empty);
216                 }
217                 \r
218                 protected override void OnDrawItem (DrawItemEventArgs e)
219                 {
220                         ThemeEngine.Current.DrawCheckedListBoxItem (this, e);
221                 }
222
223                 protected override void OnFontChanged (EventArgs e)
224                 {
225                         base.OnFontChanged (e);
226                 }
227
228                 protected override void OnHandleCreated (EventArgs e)
229                 {
230                         base.OnHandleCreated (e);
231                 }
232
233                 protected virtual void OnItemCheck (ItemCheckEventArgs ice)
234                 {
235                         if (ItemCheck != null)
236                                 ItemCheck (this, ice);
237                 }
238
239                 protected override void OnKeyPress (KeyPressEventArgs e)
240                 {
241                         base.OnKeyPress (e);
242                         
243                         if (e.KeyChar == ' ') { // Space should check focused item                              
244                                 if (focused_item != -1) {
245                                         SetItemChecked (focused_item, !GetItemChecked (focused_item));
246                                 }
247                         }
248                 }
249
250                 protected override void OnMeasureItem (MeasureItemEventArgs e)
251                 {
252                         if (MeasureItem != null)
253                                 MeasureItem (this, e);
254                 }
255
256                 protected override void OnSelectedIndexChanged (EventArgs e)
257                 {
258                         base.OnSelectedIndexChanged (e);
259                 }
260
261                 public void SetItemChecked (int index, bool value)
262                 {
263                         SetItemCheckState (index, value ? CheckState.Checked : CheckState.Unchecked);
264                 }
265
266                 public void SetItemCheckState (int index, CheckState value)
267                 {
268                         if (index < 0 || index >= Items.Count)
269                                 throw new ArgumentOutOfRangeException ("Index of out range");
270
271                         if (!Enum.IsDefined (typeof (CheckState), value))
272                                 throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for CheckState", value));
273
274                         CheckState old_value = (Items.GetListBoxItem (index)).State;
275                         
276                         if (old_value == value)
277                                 return;
278                         
279                         (Items.GetListBoxItem (index)).State = value;
280
281                         Rectangle invalidate = GetItemDisplayRectangle (index, LBoxInfo.top_item);
282
283                         switch (value) {
284                                 case CheckState.Checked:
285                                         checked_indices.AddIndex (index);
286                                         checked_items.AddObject (Items[index]);
287                                         break;
288                                 case CheckState.Unchecked:
289                                         checked_indices.RemoveIndex (index);
290                                         checked_items.RemoveObject (Items[index]);
291                                         break;
292                                 case CheckState.Indeterminate:
293                                 default:
294                                         break;
295                         }
296
297                         OnItemCheck (new ItemCheckEventArgs (index, value, old_value));
298
299                         if (ClientRectangle.Contains (invalidate))
300                                 Invalidate (invalidate);
301                 }
302
303                 protected override void WmReflectCommand (ref Message m)
304                 {
305                         base.WmReflectCommand (ref m);
306                 }
307
308                 protected override void WndProc (ref Message m)
309                 {
310                         base.WndProc (ref m);
311                 }
312
313                 #endregion Public Methods
314
315                 #region Private Methods
316
317                 internal override void OnMouseDownLB (object sender, MouseEventArgs e)
318                 {
319                         Rectangle hit_rect, item_rect;
320                         CheckState value =  CheckState.Checked;
321                         bool set_value = false;
322                         int index = IndexFromPointDisplayRectangle (e.X, e.Y);
323
324                         if (index == -1)
325                                 return;
326                         
327                         /* CheckBox hit */
328                         hit_rect = item_rect = GetItemDisplayRectangle (index, LBoxInfo.top_item); // Full item rect
329                         hit_rect.X += ThemeEngine.Current.CheckedListBoxCheckRectangle().X;
330                         hit_rect.Y += ThemeEngine.Current.CheckedListBoxCheckRectangle().Y;
331                         hit_rect.Width = ThemeEngine.Current.CheckedListBoxCheckRectangle().Width;
332                         hit_rect.Height = ThemeEngine.Current.CheckedListBoxCheckRectangle().Height;
333                         
334                         if ((Items.GetListBoxItem (index)).State == CheckState.Checked)
335                                         value = CheckState.Unchecked;
336
337                         if (hit_rect.Contains (e.X, e.Y) == true)  {                            
338                                 set_value = true;
339
340                         } else {
341                                 if (item_rect.Contains (e.X, e.Y) == true) {
342                                         if (!check_onclick) {
343                                                 if ((Items.GetListBoxItem (index)).Selected == true)
344                                                         set_value = true;
345                                         }
346                                 }
347                         }
348
349                         if (set_value)
350                                 SetItemCheckState (index, value);
351                         
352                         base.OnMouseDownLB (sender, e);
353                 }
354
355                 internal override void UpdateItemInfo (UpdateOperation operation, int first, int last)
356                 {
357                         base.UpdateItemInfo (operation, first, last);
358                         CheckedItems.ReCreate ();
359                         CheckedIndices.ReCreate ();
360                 }
361
362                 #endregion Private Methods
363
364                 public class ObjectCollection : ListBox.ObjectCollection
365                 {               
366                         public ObjectCollection (CheckedListBox owner) : base (owner)
367                         {
368                                 
369                         }
370
371                         public int Add (object item,  bool isChecked)
372                         {
373                                 if (isChecked)
374                                         return Add (item, CheckState.Checked);
375                                 
376                                 return Add (item, CheckState.Unchecked);
377                                         
378                         }
379                         \r
380                         public int Add (object item, CheckState check)
381                         {
382                                 int cnt = object_items.Count;
383                                 ListBox.ListBoxItem box_item = new ListBox.ListBoxItem (cnt);
384                                 box_item.State = check;
385                                 object_items.Add (item);
386                                 listbox_items.Add (box_item);
387                                 return cnt;
388                         }
389                 }
390
391                 /*
392                         CheckedListBox.CheckedIndexCollection
393                 */
394                 public class CheckedIndexCollection : IList, ICollection, IEnumerable
395                 {
396                         private CheckedListBox owner;
397                         private ArrayList indices = new ArrayList ();
398
399                         internal CheckedIndexCollection (CheckedListBox owner)
400                         {
401                                 this.owner = owner;
402                         }
403
404                         #region Public Properties
405                         public virtual int Count {
406                                 get { return indices.Count; }
407                         }
408
409                         public virtual bool IsReadOnly {
410                                 get { return true;}
411                         }
412
413                         bool ICollection.IsSynchronized {
414                                 get { return false; }
415                         }
416
417                         bool IList.IsFixedSize{
418                                 get { return true; }
419                         }
420
421                         object ICollection.SyncRoot {
422                                 get { return this; }
423                         }
424
425                         [Browsable (false)]
426                         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
427                         public int this[int index] {
428                                 get {
429                                         if (index < 0 || index >= Count)
430                                                 throw new ArgumentOutOfRangeException ("Index of out range");
431
432                                         return (int) indices[index];
433                                 }
434                         }
435                         #endregion Public Properties
436
437                         public bool Contains (int index)
438                         {
439                                 return indices.Contains (index);
440                         }
441
442
443                         public virtual void CopyTo (Array dest, int index)
444                         {
445                                 indices.CopyTo (dest, index);
446                         }
447
448                         public virtual IEnumerator GetEnumerator ()
449                         {
450                                 return indices.GetEnumerator ();
451                         }
452
453                         int IList.Add (object value)
454                         {
455                                 throw new NotSupportedException ();
456                         }
457
458                         void IList.Clear ()
459                         {
460                                 throw new NotSupportedException ();
461                         }
462
463                         bool IList.Contains (object index)
464                         {
465                                 return Contains ((int)index);
466                         }
467
468                         int IList.IndexOf (object index)
469                         {
470                                 return IndexOf ((int) index);
471                         }
472
473                         void IList.Insert (int index, object value)
474                         {
475                                 throw new NotSupportedException ();
476                         }
477
478                         void IList.Remove (object value)
479                         {
480                                 throw new NotSupportedException ();
481                         }
482
483                         void IList.RemoveAt (int index)
484                         {
485                                 throw new NotSupportedException ();
486                         }
487
488                         object IList.this[int index]{
489                                 get {return indices[index]; }
490                                 set {throw new NotImplementedException (); }
491                         }
492
493                         public int IndexOf (int index)
494                         {
495                                 return indices.IndexOf (index);
496                         }
497
498                         #region Private Methods
499
500                         internal void AddIndex (int index)
501                         {
502                                 indices.Add (index);
503                         }
504
505                         internal void ClearIndices ()
506                         {
507                                 indices.Clear ();
508                         }
509
510                         internal void RemoveIndex (int index)
511                         {
512                                 indices.Remove (index);
513                         }
514
515                         internal void ReCreate ()
516                         {
517                                 indices.Clear ();
518
519                                 for (int i = 0; i < owner.Items.Count; i++) {
520                                         ListBox.ListBoxItem item = owner.Items.GetListBoxItem (i);
521
522                                         if (item.State == CheckState.Checked)
523                                                 indices.Add (item.Index);
524                                 }
525                         }
526
527                         #endregion Private Methods
528                 }
529
530                 /*
531                         CheckedItemCollection
532                 */
533                 public class CheckedItemCollection : IList, ICollection, IEnumerable
534                 {
535                         private CheckedListBox owner;
536                         private ArrayList object_items = new ArrayList ();
537
538                         internal CheckedItemCollection (CheckedListBox owner)
539                         {
540                                 this.owner = owner;
541                         }
542
543                         #region Public Properties
544                         public virtual int Count {
545                                 get { return object_items.Count; }
546                         }
547
548                         public virtual bool IsReadOnly {
549                                 get { return true; }
550                         }
551
552                         [Browsable (false)]
553                         [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
554                         public virtual object this [int index] {
555                                 get {
556                                         if (index < 0 || index >= Count)
557                                                 throw new ArgumentOutOfRangeException ("Index of out range");
558
559                                         return object_items[index];
560                                 }
561                                 set {throw new NotSupportedException ();}
562                         }
563
564                         bool ICollection.IsSynchronized {
565                                 get { return true; }
566                         }
567
568                         object ICollection.SyncRoot {
569                                 get { return this; }
570                         }
571
572                         bool IList.IsFixedSize {
573                                 get { return true; }
574                         }
575
576                         object IList.this[int index] {
577                                 get { return object_items[index]; }
578                                 set { throw new NotSupportedException (); }
579                         }
580
581                         #endregion Public Properties
582
583                         #region Public Methods
584                         public virtual bool Contains (object selectedObject)
585                         {
586                                 return object_items.Contains (selectedObject);
587                         }
588
589                         public virtual void CopyTo (Array dest, int index)
590                         {
591                                 object_items.CopyTo (dest, index);
592                         }
593
594                         int IList.Add (object value)
595                         {
596                                 throw new NotSupportedException ();
597                         }
598
599                         void IList.Clear ()
600                         {
601                                 throw new NotSupportedException ();
602                         }
603
604                         bool IList.Contains (object selectedIndex)
605                         {
606                                 throw new NotImplementedException ();
607                         }
608                                 \r
609                         void IList.Insert (int index, object value)
610                         {
611                                 throw new NotSupportedException ();
612                         }
613
614                         void IList.Remove (object value)
615                         {
616                                 throw new NotSupportedException ();
617                         }
618
619                         void IList.RemoveAt (int index)
620                         {
621                                 throw new NotSupportedException ();
622                         }
623         \r
624                         public int IndexOf (object item)
625                         {
626                                 return object_items.IndexOf (item);
627                         }
628
629                         public virtual IEnumerator GetEnumerator ()
630                         {
631                                 return object_items.GetEnumerator ();
632                         }
633
634                         #endregion Public Methods
635
636                         #region Private Methods
637                         internal void AddObject (object obj)
638                         {
639                                 object_items.Add (obj);
640                         }
641
642                         internal void ClearObjects ()
643                         {
644                                 object_items.Clear ();
645                         }
646
647                         internal void ReCreate ()
648                         {
649                                 object_items.Clear ();
650
651                                 for (int i = 0; i < owner.Items.Count; i++) {
652                                         ListBox.ListBoxItem item = owner.Items.GetListBoxItem (i);
653
654                                         if (item.State == CheckState.Checked)
655                                                 object_items.Add (owner.Items[item.Index]);
656                                 }
657                         }
658
659                         internal void RemoveObject (object obj)
660                         {
661                                 object_items.Remove (obj);
662                         }
663                         #endregion Private Methods
664                 }
665         }
666 }
667