a575963da9
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
655 lines
16 KiB
C#
655 lines
16 KiB
C#
// Permission is hereby granted, free of charge, to any person obtaining
|
|
// a copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
|
// permit persons to whom the Software is furnished to do so, subject to
|
|
// the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be
|
|
// included in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
//
|
|
// Copyright (c) 2004-2006 Novell, Inc.
|
|
//
|
|
// Authors:
|
|
// Jordi Mas i Hernandez, jordi@ximian.com
|
|
// Mike Kestner <mkestner@novell.com>
|
|
//
|
|
//
|
|
|
|
using System;
|
|
using System.Drawing;
|
|
using System.Collections;
|
|
using System.ComponentModel;
|
|
using System.Reflection;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace System.Windows.Forms
|
|
{
|
|
[ClassInterface (ClassInterfaceType.AutoDispatch)]
|
|
[ComVisible (true)]
|
|
[LookupBindingPropertiesAttribute ()]
|
|
public class CheckedListBox : ListBox
|
|
{
|
|
private CheckedIndexCollection checked_indices;
|
|
private CheckedItemCollection checked_items;
|
|
private Hashtable check_states = new Hashtable ();
|
|
private bool check_onclick = false;
|
|
private bool three_dcheckboxes = false;
|
|
|
|
public CheckedListBox ()
|
|
{
|
|
checked_indices = new CheckedIndexCollection (this);
|
|
checked_items = new CheckedItemCollection (this);
|
|
SetStyle (ControlStyles.ResizeRedraw, true);
|
|
}
|
|
|
|
#region events
|
|
static object ItemCheckEvent = new object ();
|
|
|
|
[Browsable (true)]
|
|
[EditorBrowsable (EditorBrowsableState.Always)]
|
|
public new event EventHandler Click {
|
|
add { base.Click += value; }
|
|
remove { base.Click -= value; }
|
|
}
|
|
|
|
[Browsable (false)]
|
|
[EditorBrowsable (EditorBrowsableState.Never)]
|
|
public new event EventHandler DataSourceChanged {
|
|
add { base.DataSourceChanged += value; }
|
|
remove { base.DataSourceChanged -= value; }
|
|
}
|
|
|
|
[Browsable (false)]
|
|
[EditorBrowsable (EditorBrowsableState.Never)]
|
|
public new event EventHandler DisplayMemberChanged {
|
|
add { base.DisplayMemberChanged += value; }
|
|
remove { base.DisplayMemberChanged -= value; }
|
|
}
|
|
|
|
[Browsable (false)]
|
|
[EditorBrowsable (EditorBrowsableState.Never)]
|
|
public new event DrawItemEventHandler DrawItem {
|
|
add { base.DrawItem += value; }
|
|
remove { base.DrawItem -= value; }
|
|
}
|
|
|
|
[Browsable (false)]
|
|
[EditorBrowsable (EditorBrowsableState.Never)]
|
|
public new event MeasureItemEventHandler MeasureItem {
|
|
add { base.MeasureItem += value; }
|
|
remove { base.MeasureItem -= value; }
|
|
}
|
|
|
|
[Browsable (false)]
|
|
[EditorBrowsable (EditorBrowsableState.Never)]
|
|
public new event EventHandler ValueMemberChanged {
|
|
add { base.ValueMemberChanged += value; }
|
|
remove { base.ValueMemberChanged -= value; }
|
|
}
|
|
|
|
public event ItemCheckEventHandler ItemCheck {
|
|
add { Events.AddHandler (ItemCheckEvent, value); }
|
|
remove { Events.RemoveHandler (ItemCheckEvent, value); }
|
|
}
|
|
|
|
[Browsable (true)]
|
|
[EditorBrowsable (EditorBrowsableState.Always)]
|
|
public new event MouseEventHandler MouseClick {
|
|
add { base.MouseClick += value; }
|
|
remove { base.MouseClick -= value; }
|
|
}
|
|
#endregion Events
|
|
|
|
#region Public Properties
|
|
|
|
[Browsable (false)]
|
|
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
|
|
public CheckedListBox.CheckedIndexCollection CheckedIndices {
|
|
get {return checked_indices; }
|
|
}
|
|
|
|
[Browsable (false)]
|
|
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
|
|
public CheckedListBox.CheckedItemCollection CheckedItems {
|
|
get {return checked_items; }
|
|
}
|
|
|
|
[DefaultValue (false)]
|
|
public bool CheckOnClick {
|
|
get { return check_onclick; }
|
|
set { check_onclick = value; }
|
|
}
|
|
|
|
protected override CreateParams CreateParams {
|
|
get { return base.CreateParams;}
|
|
}
|
|
|
|
[EditorBrowsable (EditorBrowsableState.Never)]
|
|
[Browsable (false)]
|
|
public new object DataSource {
|
|
get { return base.DataSource; }
|
|
// FIXME: docs say you can't use a DataSource with this subclass
|
|
set { base.DataSource = value; }
|
|
}
|
|
|
|
[EditorBrowsable (EditorBrowsableState.Never)]
|
|
[Browsable (false)]
|
|
public new string DisplayMember {
|
|
get { return base.DisplayMember; }
|
|
set { base.DisplayMember = value; }
|
|
}
|
|
|
|
[Browsable (false)]
|
|
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
|
|
[EditorBrowsable (EditorBrowsableState.Never)]
|
|
public override DrawMode DrawMode {
|
|
get { return DrawMode.Normal; }
|
|
set { /* Not an exception, but has no effect. */ }
|
|
}
|
|
|
|
[Browsable (false)]
|
|
[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
|
|
[EditorBrowsable (EditorBrowsableState.Never)]
|
|
public override int ItemHeight {
|
|
get { return base.ItemHeight; }
|
|
set { /* Not an exception, but has no effect. */ }
|
|
}
|
|
|
|
[DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
|
|
[Localizable (true)]
|
|
[Editor ("System.Windows.Forms.Design.ListControlStringCollectionEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
|
|
public new CheckedListBox.ObjectCollection Items {
|
|
get { return (CheckedListBox.ObjectCollection) base.Items; }
|
|
}
|
|
|
|
public override SelectionMode SelectionMode {
|
|
get { return base.SelectionMode; }
|
|
set {
|
|
if (!Enum.IsDefined (typeof (SelectionMode), value))
|
|
throw new InvalidEnumArgumentException ("value", (int) value, typeof (SelectionMode));
|
|
|
|
if (value == SelectionMode.MultiSimple || value == SelectionMode.MultiExtended)
|
|
throw new ArgumentException ("Multi selection not supported on CheckedListBox");
|
|
|
|
base.SelectionMode = value;
|
|
}
|
|
}
|
|
|
|
[DefaultValue (false)]
|
|
public bool ThreeDCheckBoxes {
|
|
get { return three_dcheckboxes; }
|
|
set {
|
|
if (three_dcheckboxes == value)
|
|
return;
|
|
|
|
three_dcheckboxes = value;
|
|
Refresh ();
|
|
}
|
|
}
|
|
|
|
[Browsable (false)]
|
|
[EditorBrowsable (EditorBrowsableState.Never)]
|
|
public new string ValueMember {
|
|
get { return base.ValueMember; }
|
|
set { base.ValueMember = value; }
|
|
}
|
|
|
|
[Browsable (false)]
|
|
[EditorBrowsable (EditorBrowsableState.Never)]
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
public new Padding Padding {
|
|
get { return base.Padding; }
|
|
set { base.Padding = value; }
|
|
}
|
|
#endregion Public Properties
|
|
|
|
#region Public Methods
|
|
|
|
protected override AccessibleObject CreateAccessibilityInstance ()
|
|
{
|
|
return base.CreateAccessibilityInstance ();
|
|
}
|
|
|
|
protected override ListBox.ObjectCollection CreateItemCollection ()
|
|
{
|
|
return new ObjectCollection (this);
|
|
}
|
|
|
|
public bool GetItemChecked (int index)
|
|
{
|
|
return check_states.Contains (Items [index]);
|
|
}
|
|
|
|
public CheckState GetItemCheckState (int index)
|
|
{
|
|
if (index < 0 || index >= Items.Count)
|
|
throw new ArgumentOutOfRangeException ("Index of out range");
|
|
|
|
object o = Items [index];
|
|
if (check_states.Contains (o))
|
|
return (CheckState) check_states [o];
|
|
else
|
|
return CheckState.Unchecked;
|
|
}
|
|
|
|
protected override void OnBackColorChanged (EventArgs e)
|
|
{
|
|
base.OnBackColorChanged (e);
|
|
}
|
|
|
|
protected override void OnClick (EventArgs e)
|
|
{
|
|
base.OnClick (e);
|
|
}
|
|
|
|
protected override void OnDrawItem (DrawItemEventArgs e)
|
|
{
|
|
if (check_states.Contains (Items [e.Index])) {
|
|
DrawItemState state = e.State | DrawItemState.Checked;
|
|
if (((CheckState) check_states [Items [e.Index]]) == CheckState.Indeterminate)
|
|
state |= DrawItemState.Inactive;
|
|
e = new DrawItemEventArgs (e.Graphics, e.Font, e.Bounds, e.Index, state, e.ForeColor, e.BackColor);
|
|
}
|
|
ThemeEngine.Current.DrawCheckedListBoxItem (this, e);
|
|
}
|
|
|
|
protected override void OnFontChanged (EventArgs e)
|
|
{
|
|
base.OnFontChanged (e);
|
|
}
|
|
|
|
protected override void OnHandleCreated (EventArgs e)
|
|
{
|
|
base.OnHandleCreated (e);
|
|
}
|
|
|
|
protected virtual void OnItemCheck (ItemCheckEventArgs ice)
|
|
{
|
|
ItemCheckEventHandler eh = (ItemCheckEventHandler)(Events [ItemCheckEvent]);
|
|
if (eh != null)
|
|
eh (this, ice);
|
|
}
|
|
|
|
protected override void OnKeyPress (KeyPressEventArgs e)
|
|
{
|
|
base.OnKeyPress (e);
|
|
|
|
if (e.KeyChar == ' ' && FocusedItem != -1)
|
|
SetItemChecked (FocusedItem, !GetItemChecked (FocusedItem));
|
|
}
|
|
|
|
protected override void OnMeasureItem (MeasureItemEventArgs e)
|
|
{
|
|
base.OnMeasureItem (e);
|
|
}
|
|
|
|
protected override void OnSelectedIndexChanged (EventArgs e)
|
|
{
|
|
base.OnSelectedIndexChanged (e);
|
|
}
|
|
|
|
protected override void RefreshItems ()
|
|
{
|
|
base.RefreshItems ();
|
|
}
|
|
|
|
public void SetItemChecked (int index, bool value)
|
|
{
|
|
SetItemCheckState (index, value ? CheckState.Checked : CheckState.Unchecked);
|
|
}
|
|
|
|
public void SetItemCheckState (int index, CheckState value)
|
|
{
|
|
if (index < 0 || index >= Items.Count)
|
|
throw new ArgumentOutOfRangeException ("Index of out range");
|
|
|
|
if (!Enum.IsDefined (typeof (CheckState), value))
|
|
throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for CheckState", value));
|
|
|
|
CheckState old_value = GetItemCheckState (index);
|
|
|
|
if (old_value == value)
|
|
return;
|
|
|
|
ItemCheckEventArgs icea = new ItemCheckEventArgs (index, value, old_value);
|
|
OnItemCheck (icea);
|
|
|
|
switch (icea.NewValue) {
|
|
case CheckState.Checked:
|
|
case CheckState.Indeterminate:
|
|
check_states[Items[index]] = icea.NewValue;
|
|
break;
|
|
case CheckState.Unchecked:
|
|
check_states.Remove (Items[index]);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
UpdateCollections ();
|
|
|
|
InvalidateCheckbox (index);
|
|
}
|
|
|
|
protected override void WmReflectCommand (ref Message m)
|
|
{
|
|
base.WmReflectCommand (ref m);
|
|
}
|
|
|
|
protected override void WndProc (ref Message m)
|
|
{
|
|
base.WndProc (ref m);
|
|
}
|
|
|
|
#endregion Public Methods
|
|
|
|
#region Private Methods
|
|
|
|
int last_clicked_index = -1;
|
|
|
|
internal override void OnItemClick (int index)
|
|
{
|
|
if ((CheckOnClick || last_clicked_index == index) && index > -1) {
|
|
if (GetItemChecked (index))
|
|
SetItemCheckState (index, CheckState.Unchecked);
|
|
else
|
|
SetItemCheckState (index, CheckState.Checked);
|
|
}
|
|
|
|
last_clicked_index = index;
|
|
base.OnItemClick (index);
|
|
}
|
|
|
|
internal override void CollectionChanged ()
|
|
{
|
|
base.CollectionChanged ();
|
|
UpdateCollections ();
|
|
}
|
|
|
|
private void InvalidateCheckbox (int index)
|
|
{
|
|
Rectangle area = GetItemDisplayRectangle (index, TopIndex);
|
|
area.X += 2;
|
|
area.Y += (area.Height - 11) / 2;
|
|
area.Width = 11;
|
|
area.Height = 11;
|
|
Invalidate (area);
|
|
}
|
|
|
|
private void UpdateCollections ()
|
|
{
|
|
CheckedItems.Refresh ();
|
|
CheckedIndices.Refresh ();
|
|
}
|
|
|
|
#endregion Private Methods
|
|
|
|
public new class ObjectCollection : ListBox.ObjectCollection
|
|
{
|
|
private CheckedListBox owner;
|
|
|
|
public ObjectCollection (CheckedListBox owner) : base (owner)
|
|
{
|
|
this.owner = owner;
|
|
}
|
|
|
|
public int Add (object item, bool isChecked)
|
|
{
|
|
return Add (item, isChecked ? CheckState.Checked : CheckState.Unchecked);
|
|
}
|
|
|
|
public int Add (object item, CheckState check)
|
|
{
|
|
int idx = Add (item);
|
|
|
|
ItemCheckEventArgs icea = new ItemCheckEventArgs (idx, check, CheckState.Unchecked);
|
|
|
|
if (check == CheckState.Checked)
|
|
owner.OnItemCheck (icea);
|
|
|
|
if (icea.NewValue != CheckState.Unchecked)
|
|
owner.check_states[item] = icea.NewValue;
|
|
|
|
owner.UpdateCollections ();
|
|
return idx;
|
|
}
|
|
}
|
|
|
|
public class CheckedIndexCollection : IList, ICollection, IEnumerable
|
|
{
|
|
private CheckedListBox owner;
|
|
private ArrayList indices = new ArrayList ();
|
|
|
|
internal CheckedIndexCollection (CheckedListBox owner)
|
|
{
|
|
this.owner = owner;
|
|
}
|
|
|
|
#region Public Properties
|
|
public int Count {
|
|
get { return indices.Count; }
|
|
}
|
|
|
|
public bool IsReadOnly {
|
|
get { return true;}
|
|
}
|
|
|
|
bool ICollection.IsSynchronized {
|
|
get { return false; }
|
|
}
|
|
|
|
bool IList.IsFixedSize{
|
|
get { return true; }
|
|
}
|
|
|
|
object ICollection.SyncRoot {
|
|
get { return this; }
|
|
}
|
|
|
|
[Browsable (false)]
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
public int this[int index] {
|
|
get {
|
|
if (index < 0 || index >= Count)
|
|
throw new ArgumentOutOfRangeException ("Index of out range");
|
|
|
|
return (int) indices[index];
|
|
}
|
|
}
|
|
#endregion Public Properties
|
|
|
|
public bool Contains (int index)
|
|
{
|
|
return indices.Contains (index);
|
|
}
|
|
|
|
|
|
public void CopyTo (Array dest, int index)
|
|
{
|
|
indices.CopyTo (dest, index);
|
|
}
|
|
|
|
public IEnumerator GetEnumerator ()
|
|
{
|
|
return indices.GetEnumerator ();
|
|
}
|
|
|
|
int IList.Add (object value)
|
|
{
|
|
throw new NotSupportedException ();
|
|
}
|
|
|
|
void IList.Clear ()
|
|
{
|
|
throw new NotSupportedException ();
|
|
}
|
|
|
|
bool IList.Contains (object index)
|
|
{
|
|
return Contains ((int)index);
|
|
}
|
|
|
|
int IList.IndexOf (object index)
|
|
{
|
|
return IndexOf ((int) index);
|
|
}
|
|
|
|
void IList.Insert (int index, object value)
|
|
{
|
|
throw new NotSupportedException ();
|
|
}
|
|
|
|
void IList.Remove (object value)
|
|
{
|
|
throw new NotSupportedException ();
|
|
}
|
|
|
|
void IList.RemoveAt (int index)
|
|
{
|
|
throw new NotSupportedException ();
|
|
}
|
|
|
|
object IList.this[int index]{
|
|
get {return indices[index]; }
|
|
set {throw new NotImplementedException (); }
|
|
}
|
|
|
|
public int IndexOf (int index)
|
|
{
|
|
return indices.IndexOf (index);
|
|
}
|
|
|
|
#region Private Methods
|
|
internal void Refresh ()
|
|
{
|
|
indices.Clear ();
|
|
for (int i = 0; i < owner.Items.Count; i++)
|
|
if (owner.check_states.Contains (owner.Items [i]))
|
|
indices.Add (i);
|
|
}
|
|
#endregion Private Methods
|
|
|
|
}
|
|
|
|
public class CheckedItemCollection : IList, ICollection, IEnumerable
|
|
{
|
|
private CheckedListBox owner;
|
|
private ArrayList list = new ArrayList ();
|
|
|
|
internal CheckedItemCollection (CheckedListBox owner)
|
|
{
|
|
this.owner = owner;
|
|
}
|
|
|
|
#region Public Properties
|
|
public int Count {
|
|
get { return list.Count; }
|
|
}
|
|
|
|
public bool IsReadOnly {
|
|
get { return true; }
|
|
}
|
|
|
|
[Browsable (false)]
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
public object this [int index] {
|
|
get {
|
|
if (index < 0 || index >= Count)
|
|
throw new ArgumentOutOfRangeException ("Index of out range");
|
|
|
|
return list[index];
|
|
}
|
|
set {throw new NotSupportedException ();}
|
|
}
|
|
|
|
bool ICollection.IsSynchronized {
|
|
get { return true; }
|
|
}
|
|
|
|
object ICollection.SyncRoot {
|
|
get { return this; }
|
|
}
|
|
|
|
bool IList.IsFixedSize {
|
|
get { return true; }
|
|
}
|
|
|
|
#endregion Public Properties
|
|
|
|
#region Public Methods
|
|
public bool Contains (object item)
|
|
{
|
|
return list.Contains (item);
|
|
}
|
|
|
|
public void CopyTo (Array dest, int index)
|
|
{
|
|
list.CopyTo (dest, index);
|
|
}
|
|
|
|
int IList.Add (object value)
|
|
{
|
|
throw new NotSupportedException ();
|
|
}
|
|
|
|
void IList.Clear ()
|
|
{
|
|
throw new NotSupportedException ();
|
|
}
|
|
|
|
void IList.Insert (int index, object value)
|
|
{
|
|
throw new NotSupportedException ();
|
|
}
|
|
|
|
void IList.Remove (object value)
|
|
{
|
|
throw new NotSupportedException ();
|
|
}
|
|
|
|
void IList.RemoveAt (int index)
|
|
{
|
|
throw new NotSupportedException ();
|
|
}
|
|
|
|
public int IndexOf (object item)
|
|
{
|
|
return list.IndexOf (item);
|
|
}
|
|
|
|
public IEnumerator GetEnumerator ()
|
|
{
|
|
return list.GetEnumerator ();
|
|
}
|
|
|
|
#endregion Public Methods
|
|
|
|
#region Private Methods
|
|
internal void Refresh ()
|
|
{
|
|
list.Clear ();
|
|
for (int i = 0; i < owner.Items.Count; i++)
|
|
if (owner.check_states.Contains (owner.Items [i]))
|
|
list.Add (owner.Items[i]);
|
|
}
|
|
#endregion Private Methods
|
|
}
|
|
[DefaultValue (false)]
|
|
public bool UseCompatibleTextRendering {
|
|
get { return use_compatible_text_rendering; }
|
|
set { use_compatible_text_rendering = value; }
|
|
}
|
|
}
|
|
}
|
|
|