/mcs/class/Managed.Windows.Forms/System.Windows.Forms/CheckedListBox.cs

https://bitbucket.org/danipen/mono · C# · 654 lines · 507 code · 120 blank · 27 comment · 42 complexity · 9185c8a5b4bc63f79aa467577f2dccfd MD5 · raw file

  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-2006 Novell, Inc.
  21. //
  22. // Authors:
  23. // Jordi Mas i Hernandez, jordi@ximian.com
  24. // Mike Kestner <mkestner@novell.com>
  25. //
  26. //
  27. using System;
  28. using System.Drawing;
  29. using System.Collections;
  30. using System.ComponentModel;
  31. using System.Reflection;
  32. using System.Runtime.InteropServices;
  33. namespace System.Windows.Forms
  34. {
  35. [ClassInterface (ClassInterfaceType.AutoDispatch)]
  36. [ComVisible (true)]
  37. [LookupBindingPropertiesAttribute ()]
  38. public class CheckedListBox : ListBox
  39. {
  40. private CheckedIndexCollection checked_indices;
  41. private CheckedItemCollection checked_items;
  42. private Hashtable check_states = new Hashtable ();
  43. private bool check_onclick = false;
  44. private bool three_dcheckboxes = false;
  45. public CheckedListBox ()
  46. {
  47. checked_indices = new CheckedIndexCollection (this);
  48. checked_items = new CheckedItemCollection (this);
  49. SetStyle (ControlStyles.ResizeRedraw, true);
  50. }
  51. #region events
  52. static object ItemCheckEvent = new object ();
  53. [Browsable (true)]
  54. [EditorBrowsable (EditorBrowsableState.Always)]
  55. public new event EventHandler Click {
  56. add { base.Click += value; }
  57. remove { base.Click -= value; }
  58. }
  59. [Browsable (false)]
  60. [EditorBrowsable (EditorBrowsableState.Never)]
  61. public new event EventHandler DataSourceChanged {
  62. add { base.DataSourceChanged += value; }
  63. remove { base.DataSourceChanged -= value; }
  64. }
  65. [Browsable (false)]
  66. [EditorBrowsable (EditorBrowsableState.Never)]
  67. public new event EventHandler DisplayMemberChanged {
  68. add { base.DisplayMemberChanged += value; }
  69. remove { base.DisplayMemberChanged -= value; }
  70. }
  71. [Browsable (false)]
  72. [EditorBrowsable (EditorBrowsableState.Never)]
  73. public new event DrawItemEventHandler DrawItem {
  74. add { base.DrawItem += value; }
  75. remove { base.DrawItem -= value; }
  76. }
  77. [Browsable (false)]
  78. [EditorBrowsable (EditorBrowsableState.Never)]
  79. public new event MeasureItemEventHandler MeasureItem {
  80. add { base.MeasureItem += value; }
  81. remove { base.MeasureItem -= value; }
  82. }
  83. [Browsable (false)]
  84. [EditorBrowsable (EditorBrowsableState.Never)]
  85. public new event EventHandler ValueMemberChanged {
  86. add { base.ValueMemberChanged += value; }
  87. remove { base.ValueMemberChanged -= value; }
  88. }
  89. public event ItemCheckEventHandler ItemCheck {
  90. add { Events.AddHandler (ItemCheckEvent, value); }
  91. remove { Events.RemoveHandler (ItemCheckEvent, value); }
  92. }
  93. [Browsable (true)]
  94. [EditorBrowsable (EditorBrowsableState.Always)]
  95. public new event MouseEventHandler MouseClick {
  96. add { base.MouseClick += value; }
  97. remove { base.MouseClick -= value; }
  98. }
  99. #endregion Events
  100. #region Public Properties
  101. [Browsable (false)]
  102. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  103. public CheckedListBox.CheckedIndexCollection CheckedIndices {
  104. get {return checked_indices; }
  105. }
  106. [Browsable (false)]
  107. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  108. public CheckedListBox.CheckedItemCollection CheckedItems {
  109. get {return checked_items; }
  110. }
  111. [DefaultValue (false)]
  112. public bool CheckOnClick {
  113. get { return check_onclick; }
  114. set { check_onclick = value; }
  115. }
  116. protected override CreateParams CreateParams {
  117. get { return base.CreateParams;}
  118. }
  119. [EditorBrowsable (EditorBrowsableState.Never)]
  120. [Browsable (false)]
  121. public new object DataSource {
  122. get { return base.DataSource; }
  123. // FIXME: docs say you can't use a DataSource with this subclass
  124. set { base.DataSource = value; }
  125. }
  126. [EditorBrowsable (EditorBrowsableState.Never)]
  127. [Browsable (false)]
  128. public new string DisplayMember {
  129. get { return base.DisplayMember; }
  130. set { base.DisplayMember = value; }
  131. }
  132. [Browsable (false)]
  133. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  134. [EditorBrowsable (EditorBrowsableState.Never)]
  135. public override DrawMode DrawMode {
  136. get { return DrawMode.Normal; }
  137. set { /* Not an exception, but has no effect. */ }
  138. }
  139. [Browsable (false)]
  140. [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
  141. [EditorBrowsable (EditorBrowsableState.Never)]
  142. public override int ItemHeight {
  143. get { return base.ItemHeight; }
  144. set { /* Not an exception, but has no effect. */ }
  145. }
  146. [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
  147. [Localizable (true)]
  148. [Editor ("System.Windows.Forms.Design.ListControlStringCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
  149. public new CheckedListBox.ObjectCollection Items {
  150. get { return (CheckedListBox.ObjectCollection) base.Items; }
  151. }
  152. public override SelectionMode SelectionMode {
  153. get { return base.SelectionMode; }
  154. set {
  155. if (!Enum.IsDefined (typeof (SelectionMode), value))
  156. throw new InvalidEnumArgumentException ("value", (int) value, typeof (SelectionMode));
  157. if (value == SelectionMode.MultiSimple || value == SelectionMode.MultiExtended)
  158. throw new ArgumentException ("Multi selection not supported on CheckedListBox");
  159. base.SelectionMode = value;
  160. }
  161. }
  162. [DefaultValue (false)]
  163. public bool ThreeDCheckBoxes {
  164. get { return three_dcheckboxes; }
  165. set {
  166. if (three_dcheckboxes == value)
  167. return;
  168. three_dcheckboxes = value;
  169. Refresh ();
  170. }
  171. }
  172. [Browsable (false)]
  173. [EditorBrowsable (EditorBrowsableState.Never)]
  174. public new string ValueMember {
  175. get { return base.ValueMember; }
  176. set { base.ValueMember = value; }
  177. }
  178. [Browsable (false)]
  179. [EditorBrowsable (EditorBrowsableState.Never)]
  180. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  181. public new Padding Padding {
  182. get { return base.Padding; }
  183. set { base.Padding = value; }
  184. }
  185. #endregion Public Properties
  186. #region Public Methods
  187. protected override AccessibleObject CreateAccessibilityInstance ()
  188. {
  189. return base.CreateAccessibilityInstance ();
  190. }
  191. protected override ListBox.ObjectCollection CreateItemCollection ()
  192. {
  193. return new ObjectCollection (this);
  194. }
  195. public bool GetItemChecked (int index)
  196. {
  197. return check_states.Contains (Items [index]);
  198. }
  199. public CheckState GetItemCheckState (int index)
  200. {
  201. if (index < 0 || index >= Items.Count)
  202. throw new ArgumentOutOfRangeException ("Index of out range");
  203. object o = Items [index];
  204. if (check_states.Contains (o))
  205. return (CheckState) check_states [o];
  206. else
  207. return CheckState.Unchecked;
  208. }
  209. protected override void OnBackColorChanged (EventArgs e)
  210. {
  211. base.OnBackColorChanged (e);
  212. }
  213. protected override void OnClick (EventArgs e)
  214. {
  215. base.OnClick (e);
  216. }
  217. protected override void OnDrawItem (DrawItemEventArgs e)
  218. {
  219. if (check_states.Contains (Items [e.Index])) {
  220. DrawItemState state = e.State | DrawItemState.Checked;
  221. if (((CheckState) check_states [Items [e.Index]]) == CheckState.Indeterminate)
  222. state |= DrawItemState.Inactive;
  223. e = new DrawItemEventArgs (e.Graphics, e.Font, e.Bounds, e.Index, state, e.ForeColor, e.BackColor);
  224. }
  225. ThemeEngine.Current.DrawCheckedListBoxItem (this, e);
  226. }
  227. protected override void OnFontChanged (EventArgs e)
  228. {
  229. base.OnFontChanged (e);
  230. }
  231. protected override void OnHandleCreated (EventArgs e)
  232. {
  233. base.OnHandleCreated (e);
  234. }
  235. protected virtual void OnItemCheck (ItemCheckEventArgs ice)
  236. {
  237. ItemCheckEventHandler eh = (ItemCheckEventHandler)(Events [ItemCheckEvent]);
  238. if (eh != null)
  239. eh (this, ice);
  240. }
  241. protected override void OnKeyPress (KeyPressEventArgs e)
  242. {
  243. base.OnKeyPress (e);
  244. if (e.KeyChar == ' ' && FocusedItem != -1)
  245. SetItemChecked (FocusedItem, !GetItemChecked (FocusedItem));
  246. }
  247. protected override void OnMeasureItem (MeasureItemEventArgs e)
  248. {
  249. base.OnMeasureItem (e);
  250. }
  251. protected override void OnSelectedIndexChanged (EventArgs e)
  252. {
  253. base.OnSelectedIndexChanged (e);
  254. }
  255. protected override void RefreshItems ()
  256. {
  257. base.RefreshItems ();
  258. }
  259. public void SetItemChecked (int index, bool value)
  260. {
  261. SetItemCheckState (index, value ? CheckState.Checked : CheckState.Unchecked);
  262. }
  263. public void SetItemCheckState (int index, CheckState value)
  264. {
  265. if (index < 0 || index >= Items.Count)
  266. throw new ArgumentOutOfRangeException ("Index of out range");
  267. if (!Enum.IsDefined (typeof (CheckState), value))
  268. throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for CheckState", value));
  269. CheckState old_value = GetItemCheckState (index);
  270. if (old_value == value)
  271. return;
  272. ItemCheckEventArgs icea = new ItemCheckEventArgs (index, value, old_value);
  273. OnItemCheck (icea);
  274. switch (icea.NewValue) {
  275. case CheckState.Checked:
  276. case CheckState.Indeterminate:
  277. check_states[Items[index]] = icea.NewValue;
  278. break;
  279. case CheckState.Unchecked:
  280. check_states.Remove (Items[index]);
  281. break;
  282. default:
  283. break;
  284. }
  285. UpdateCollections ();
  286. InvalidateCheckbox (index);
  287. }
  288. protected override void WmReflectCommand (ref Message m)
  289. {
  290. base.WmReflectCommand (ref m);
  291. }
  292. protected override void WndProc (ref Message m)
  293. {
  294. base.WndProc (ref m);
  295. }
  296. #endregion Public Methods
  297. #region Private Methods
  298. int last_clicked_index = -1;
  299. internal override void OnItemClick (int index)
  300. {
  301. if ((CheckOnClick || last_clicked_index == index) && index > -1) {
  302. if (GetItemChecked (index))
  303. SetItemCheckState (index, CheckState.Unchecked);
  304. else
  305. SetItemCheckState (index, CheckState.Checked);
  306. }
  307. last_clicked_index = index;
  308. base.OnItemClick (index);
  309. }
  310. internal override void CollectionChanged ()
  311. {
  312. base.CollectionChanged ();
  313. UpdateCollections ();
  314. }
  315. private void InvalidateCheckbox (int index)
  316. {
  317. Rectangle area = GetItemDisplayRectangle (index, TopIndex);
  318. area.X += 2;
  319. area.Y += (area.Height - 11) / 2;
  320. area.Width = 11;
  321. area.Height = 11;
  322. Invalidate (area);
  323. }
  324. private void UpdateCollections ()
  325. {
  326. CheckedItems.Refresh ();
  327. CheckedIndices.Refresh ();
  328. }
  329. #endregion Private Methods
  330. public new class ObjectCollection : ListBox.ObjectCollection
  331. {
  332. private CheckedListBox owner;
  333. public ObjectCollection (CheckedListBox owner) : base (owner)
  334. {
  335. this.owner = owner;
  336. }
  337. public int Add (object item, bool isChecked)
  338. {
  339. return Add (item, isChecked ? CheckState.Checked : CheckState.Unchecked);
  340. }
  341. public int Add (object item, CheckState check)
  342. {
  343. int idx = Add (item);
  344. ItemCheckEventArgs icea = new ItemCheckEventArgs (idx, check, CheckState.Unchecked);
  345. if (check == CheckState.Checked)
  346. owner.OnItemCheck (icea);
  347. if (icea.NewValue != CheckState.Unchecked)
  348. owner.check_states[item] = icea.NewValue;
  349. owner.UpdateCollections ();
  350. return idx;
  351. }
  352. }
  353. public class CheckedIndexCollection : IList, ICollection, IEnumerable
  354. {
  355. private CheckedListBox owner;
  356. private ArrayList indices = new ArrayList ();
  357. internal CheckedIndexCollection (CheckedListBox owner)
  358. {
  359. this.owner = owner;
  360. }
  361. #region Public Properties
  362. public int Count {
  363. get { return indices.Count; }
  364. }
  365. public bool IsReadOnly {
  366. get { return true;}
  367. }
  368. bool ICollection.IsSynchronized {
  369. get { return false; }
  370. }
  371. bool IList.IsFixedSize{
  372. get { return true; }
  373. }
  374. object ICollection.SyncRoot {
  375. get { return this; }
  376. }
  377. [Browsable (false)]
  378. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  379. public int this[int index] {
  380. get {
  381. if (index < 0 || index >= Count)
  382. throw new ArgumentOutOfRangeException ("Index of out range");
  383. return (int) indices[index];
  384. }
  385. }
  386. #endregion Public Properties
  387. public bool Contains (int index)
  388. {
  389. return indices.Contains (index);
  390. }
  391. public void CopyTo (Array dest, int index)
  392. {
  393. indices.CopyTo (dest, index);
  394. }
  395. public IEnumerator GetEnumerator ()
  396. {
  397. return indices.GetEnumerator ();
  398. }
  399. int IList.Add (object value)
  400. {
  401. throw new NotSupportedException ();
  402. }
  403. void IList.Clear ()
  404. {
  405. throw new NotSupportedException ();
  406. }
  407. bool IList.Contains (object index)
  408. {
  409. return Contains ((int)index);
  410. }
  411. int IList.IndexOf (object index)
  412. {
  413. return IndexOf ((int) index);
  414. }
  415. void IList.Insert (int index, object value)
  416. {
  417. throw new NotSupportedException ();
  418. }
  419. void IList.Remove (object value)
  420. {
  421. throw new NotSupportedException ();
  422. }
  423. void IList.RemoveAt (int index)
  424. {
  425. throw new NotSupportedException ();
  426. }
  427. object IList.this[int index]{
  428. get {return indices[index]; }
  429. set {throw new NotImplementedException (); }
  430. }
  431. public int IndexOf (int index)
  432. {
  433. return indices.IndexOf (index);
  434. }
  435. #region Private Methods
  436. internal void Refresh ()
  437. {
  438. indices.Clear ();
  439. for (int i = 0; i < owner.Items.Count; i++)
  440. if (owner.check_states.Contains (owner.Items [i]))
  441. indices.Add (i);
  442. }
  443. #endregion Private Methods
  444. }
  445. public class CheckedItemCollection : IList, ICollection, IEnumerable
  446. {
  447. private CheckedListBox owner;
  448. private ArrayList list = new ArrayList ();
  449. internal CheckedItemCollection (CheckedListBox owner)
  450. {
  451. this.owner = owner;
  452. }
  453. #region Public Properties
  454. public int Count {
  455. get { return list.Count; }
  456. }
  457. public bool IsReadOnly {
  458. get { return true; }
  459. }
  460. [Browsable (false)]
  461. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
  462. public object this [int index] {
  463. get {
  464. if (index < 0 || index >= Count)
  465. throw new ArgumentOutOfRangeException ("Index of out range");
  466. return list[index];
  467. }
  468. set {throw new NotSupportedException ();}
  469. }
  470. bool ICollection.IsSynchronized {
  471. get { return true; }
  472. }
  473. object ICollection.SyncRoot {
  474. get { return this; }
  475. }
  476. bool IList.IsFixedSize {
  477. get { return true; }
  478. }
  479. #endregion Public Properties
  480. #region Public Methods
  481. public bool Contains (object item)
  482. {
  483. return list.Contains (item);
  484. }
  485. public void CopyTo (Array dest, int index)
  486. {
  487. list.CopyTo (dest, index);
  488. }
  489. int IList.Add (object value)
  490. {
  491. throw new NotSupportedException ();
  492. }
  493. void IList.Clear ()
  494. {
  495. throw new NotSupportedException ();
  496. }
  497. void IList.Insert (int index, object value)
  498. {
  499. throw new NotSupportedException ();
  500. }
  501. void IList.Remove (object value)
  502. {
  503. throw new NotSupportedException ();
  504. }
  505. void IList.RemoveAt (int index)
  506. {
  507. throw new NotSupportedException ();
  508. }
  509. public int IndexOf (object item)
  510. {
  511. return list.IndexOf (item);
  512. }
  513. public IEnumerator GetEnumerator ()
  514. {
  515. return list.GetEnumerator ();
  516. }
  517. #endregion Public Methods
  518. #region Private Methods
  519. internal void Refresh ()
  520. {
  521. list.Clear ();
  522. for (int i = 0; i < owner.Items.Count; i++)
  523. if (owner.check_states.Contains (owner.Items [i]))
  524. list.Add (owner.Items[i]);
  525. }
  526. #endregion Private Methods
  527. }
  528. [DefaultValue (false)]
  529. public bool UseCompatibleTextRendering {
  530. get { return use_compatible_text_rendering; }
  531. set { use_compatible_text_rendering = value; }
  532. }
  533. }
  534. }