282 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			282 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System;
 | |
| using System.Collections.Generic;
 | |
| using System.Text;
 | |
| using System.ComponentModel;
 | |
| using System.Drawing.Design;
 | |
| using System.Windows.Forms;
 | |
| using System.Windows.Forms.Design;
 | |
| 
 | |
| namespace DevComponents.DotNetBar.Design
 | |
| {
 | |
|     // UITypeEditor for flag enums
 | |
|     public class FlagEnumUIEditor : UITypeEditor
 | |
|     {
 | |
|         // The checklistbox
 | |
|         private FlagCheckedListBox flagEnumCB;
 | |
| 
 | |
|         public FlagEnumUIEditor()
 | |
|         {
 | |
|             flagEnumCB = new FlagCheckedListBox();
 | |
|             flagEnumCB.BorderStyle = BorderStyle.None;
 | |
|         }
 | |
| 
 | |
|         public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
 | |
|         {
 | |
|             if (context != null
 | |
|                 && context.Instance != null
 | |
|                 && provider != null)
 | |
|             {
 | |
| 
 | |
|                 IWindowsFormsEditorService edSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
 | |
| 
 | |
|                 if (edSvc != null)
 | |
|                 {
 | |
| 
 | |
|                     Enum e = (Enum)Convert.ChangeType(value, context.PropertyDescriptor.PropertyType);
 | |
|                     flagEnumCB.EnumValue = e;
 | |
|                     edSvc.DropDownControl(flagEnumCB);
 | |
|                     return flagEnumCB.EnumValue;
 | |
| 
 | |
|                 }
 | |
|             }
 | |
|             return null;
 | |
|         }
 | |
| 
 | |
|         public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
 | |
|         {
 | |
|             return UITypeEditorEditStyle.DropDown;
 | |
|         }
 | |
| 
 | |
| 
 | |
|     }
 | |
| 
 | |
|     #region FlagCheckedListBox
 | |
|     internal class FlagCheckedListBox : CheckedListBox
 | |
|     {
 | |
|         private System.ComponentModel.Container components = null;
 | |
| 
 | |
|         public FlagCheckedListBox()
 | |
|         {
 | |
|             // This call is required by the Windows.Forms Form Designer.
 | |
|             InitializeComponent();
 | |
| 
 | |
|             // TODO: Add any initialization after the InitForm call
 | |
| 
 | |
|         }
 | |
| 
 | |
|         protected override void Dispose(bool disposing)
 | |
|         {
 | |
|             if (disposing)
 | |
|             {
 | |
|                 if (components != null)
 | |
|                     components.Dispose();
 | |
|             }
 | |
|             base.Dispose(disposing);
 | |
|         }
 | |
| 
 | |
|         #region Component Designer generated code
 | |
|         private void InitializeComponent()
 | |
|         {
 | |
|             // 
 | |
|             // FlaggedCheckedListBox
 | |
|             // 
 | |
|             this.CheckOnClick = true;
 | |
| 
 | |
|         }
 | |
|         #endregion
 | |
| 
 | |
|         // Adds an integer value and its associated description
 | |
|         public FlagCheckedListBoxItem Add(int v, string c)
 | |
|         {
 | |
|             FlagCheckedListBoxItem item = new FlagCheckedListBoxItem(v, c);
 | |
|             Items.Add(item);
 | |
|             return item;
 | |
|         }
 | |
| 
 | |
|         public FlagCheckedListBoxItem Add(FlagCheckedListBoxItem item)
 | |
|         {
 | |
|             Items.Add(item);
 | |
|             return item;
 | |
|         }
 | |
| 
 | |
|         protected override void OnItemCheck(ItemCheckEventArgs e)
 | |
|         {
 | |
|             base.OnItemCheck(e);
 | |
| 
 | |
|             if (isUpdatingCheckStates)
 | |
|                 return;
 | |
| 
 | |
|             // Get the checked/unchecked item
 | |
|             FlagCheckedListBoxItem item = Items[e.Index] as FlagCheckedListBoxItem;
 | |
|             // Update other items
 | |
|             UpdateCheckedItems(item, e.NewValue);
 | |
|         }
 | |
| 
 | |
|         // Checks/Unchecks items depending on the give bitvalue
 | |
|         protected void UpdateCheckedItems(int value)
 | |
|         {
 | |
| 
 | |
|             isUpdatingCheckStates = true;
 | |
| 
 | |
|             // Iterate over all items
 | |
|             for (int i = 0; i < Items.Count; i++)
 | |
|             {
 | |
|                 FlagCheckedListBoxItem item = Items[i] as FlagCheckedListBoxItem;
 | |
| 
 | |
|                 if (item.value == 0)
 | |
|                 {
 | |
|                     SetItemChecked(i, value == 0);
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
| 
 | |
|                     // If the bit for the current item is on in the bitvalue, check it
 | |
|                     if ((item.value & value) == item.value && item.value != 0)
 | |
|                         SetItemChecked(i, true);
 | |
|                     // Otherwise uncheck it
 | |
|                     else
 | |
|                         SetItemChecked(i, false);
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             isUpdatingCheckStates = false;
 | |
| 
 | |
|         }
 | |
| 
 | |
|         // Updates items in the checklistbox
 | |
|         // composite = The item that was checked/unchecked
 | |
|         // cs = The check state of that item
 | |
|         protected void UpdateCheckedItems(FlagCheckedListBoxItem composite, CheckState cs)
 | |
|         {
 | |
| 
 | |
|             // If the value of the item is 0, call directly.
 | |
|             if (composite.value == 0)
 | |
|                 UpdateCheckedItems(0);
 | |
| 
 | |
| 
 | |
|             // Get the total value of all checked items
 | |
|             int sum = 0;
 | |
|             for (int i = 0; i < Items.Count; i++)
 | |
|             {
 | |
|                 FlagCheckedListBoxItem item = Items[i] as FlagCheckedListBoxItem;
 | |
| 
 | |
|                 // If item is checked, add its value to the sum.
 | |
|                 if (GetItemChecked(i))
 | |
|                     sum |= item.value;
 | |
|             }
 | |
| 
 | |
|             // If the item has been unchecked, remove its bits from the sum
 | |
|             if (cs == CheckState.Unchecked)
 | |
|                 sum = sum & (~composite.value);
 | |
|             // If the item has been checked, combine its bits with the sum
 | |
|             else
 | |
|                 sum |= composite.value;
 | |
| 
 | |
|             // Update all items in the checklistbox based on the final bit value
 | |
|             UpdateCheckedItems(sum);
 | |
| 
 | |
|         }
 | |
| 
 | |
|         private bool isUpdatingCheckStates = false;
 | |
| 
 | |
|         // Gets the current bit value corresponding to all checked items
 | |
|         public int GetCurrentValue()
 | |
|         {
 | |
|             int sum = 0;
 | |
| 
 | |
|             for (int i = 0; i < Items.Count; i++)
 | |
|             {
 | |
|                 FlagCheckedListBoxItem item = Items[i] as FlagCheckedListBoxItem;
 | |
| 
 | |
|                 if (GetItemChecked(i))
 | |
|                     sum |= item.value;
 | |
|             }
 | |
| 
 | |
|             return sum;
 | |
|         }
 | |
| 
 | |
|         Type enumType;
 | |
|         Enum enumValue;
 | |
| 
 | |
|         // Adds items to the checklistbox based on the members of the enum
 | |
|         private void FillEnumMembers()
 | |
|         {
 | |
|             foreach (string name in Enum.GetNames(enumType))
 | |
|             {
 | |
|                 object val = Enum.Parse(enumType, name);
 | |
|                 int intVal = (int)Convert.ChangeType(val, typeof(int));
 | |
| 
 | |
|                 Add(intVal, name);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         // Checks/unchecks items based on the current value of the enum variable
 | |
|         private void ApplyEnumValue()
 | |
|         {
 | |
|             int intVal = (int)Convert.ChangeType(enumValue, typeof(int));
 | |
|             UpdateCheckedItems(intVal);
 | |
| 
 | |
|         }
 | |
| 
 | |
|         [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
 | |
|         public Enum EnumValue
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 object e = Enum.ToObject(enumType, GetCurrentValue());
 | |
|                 return (Enum)e;
 | |
|             }
 | |
|             set
 | |
|             {
 | |
| 
 | |
|                 Items.Clear();
 | |
|                 enumValue = value; // Store the current enum value
 | |
|                 enumType = value.GetType(); // Store enum type
 | |
|                 FillEnumMembers(); // Add items for enum members
 | |
|                 ApplyEnumValue(); // Check/uncheck items depending on enum value
 | |
| 
 | |
|             }
 | |
|         }
 | |
| 
 | |
| 
 | |
|     }
 | |
| 
 | |
|     // Represents an item in the checklistbox
 | |
|     public class FlagCheckedListBoxItem
 | |
|     {
 | |
|         public FlagCheckedListBoxItem(int v, string c)
 | |
|         {
 | |
|             value = v;
 | |
|             caption = c;
 | |
|         }
 | |
| 
 | |
|         public override string ToString()
 | |
|         {
 | |
|             return caption;
 | |
|         }
 | |
| 
 | |
|         // Returns true if the value corresponds to a single bit being set
 | |
|         public bool IsFlag
 | |
|         {
 | |
|             get
 | |
|             {
 | |
|                 return ((value & (value - 1)) == 0);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         // Returns true if this value is a member of the composite bit value
 | |
|         public bool IsMemberFlag(FlagCheckedListBoxItem composite)
 | |
|         {
 | |
|             return (IsFlag && ((value & composite.value) == value));
 | |
|         }
 | |
| 
 | |
|         public int value;
 | |
|         public string caption;
 | |
|     }
 | |
|     #endregion
 | |
| 
 | |
|     
 | |
| 
 | |
|     
 | |
| }
 |