External/Aga.Controls/Tree/NodeControls/NodeComboBox.cs
author sl
Thu, 01 Jan 2015 23:35:49 +0100
changeset 405 5715aefd2bcc
permissions -rw-r--r--
SharpDisplay: Migrating to new robust client scheme.
     1 using System;
     2 using System.Collections.Generic;
     3 using System.Text;
     4 using System.Drawing;
     5 using System.Windows.Forms;
     6 using System.Reflection;
     7 using System.ComponentModel;
     8 using System.Drawing.Design;
     9 
    10 namespace Aga.Controls.Tree.NodeControls
    11 {
    12 	public class NodeComboBox : BaseTextControl
    13 	{
    14 		#region Properties
    15 
    16 		private int _editorWidth = 100;
    17 		[DefaultValue(100)]
    18 		public int EditorWidth
    19 		{
    20 			get { return _editorWidth; }
    21 			set { _editorWidth = value; }
    22 		}
    23 
    24 		private int _editorHeight = 100;
    25 		[DefaultValue(100)]
    26 		public int EditorHeight
    27 		{
    28 			get { return _editorHeight; }
    29 			set { _editorHeight = value; }
    30 		}
    31 
    32 		private List<object> _dropDownItems;
    33 		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1002:DoNotExposeGenericLists")]
    34 		[Editor(typeof(StringCollectionEditor), typeof(UITypeEditor)), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    35 		public List<object> DropDownItems
    36 		{
    37 			get { return _dropDownItems; }
    38 		}
    39 
    40 		#endregion
    41 
    42 		public event EventHandler<EditEventArgs> CreatingEditor;
    43 
    44 		public NodeComboBox()
    45 		{
    46 			_dropDownItems = new List<object>();
    47 		}
    48 
    49 		protected override Size CalculateEditorSize(EditorContext context)
    50 		{
    51 			if (Parent.UseColumns)
    52 			{
    53 				if (context.Editor is CheckedListBox)
    54 					return new Size(context.Bounds.Size.Width, EditorHeight);
    55 				else
    56 					return context.Bounds.Size;
    57 			}
    58 			else
    59 			{
    60 				if (context.Editor is CheckedListBox)
    61 					return new Size(EditorWidth, EditorHeight);
    62 				else
    63 					return new Size(EditorWidth, context.Bounds.Height);
    64 			}
    65 		}
    66 
    67 		protected override Control CreateEditor(TreeNodeAdv node)
    68 		{
    69 			Control c;
    70 			object value = GetValue(node);
    71 			if (IsCheckedListBoxRequired(node))
    72 				c = CreateCheckedListBox(node);
    73 			else
    74 				c = CreateCombo(node);
    75 			OnCreatingEditor(new EditEventArgs(node, c));
    76 			return c;
    77 		}
    78 
    79 		protected override void DisposeEditor(Control editor)
    80 		{
    81 		}
    82 
    83 		protected virtual void OnCreatingEditor(EditEventArgs args)
    84 		{
    85 			if (CreatingEditor != null)
    86 				CreatingEditor(this, args);
    87 		}
    88 
    89 		protected virtual bool IsCheckedListBoxRequired(TreeNodeAdv node)
    90 		{
    91 			object value = GetValue(node);
    92 			if (value != null)
    93 			{
    94 				Type t = value.GetType();
    95 				object[] arr = t.GetCustomAttributes(typeof(FlagsAttribute), false);
    96 				return (t.IsEnum && arr.Length == 1);
    97 			}
    98 			return false;
    99 		}
   100 
   101 		private Control CreateCombo(TreeNodeAdv node)
   102 		{
   103 			ComboBox comboBox = new ComboBox();
   104 			if (DropDownItems != null)
   105 				comboBox.Items.AddRange(DropDownItems.ToArray());
   106 			comboBox.SelectedItem = GetValue(node);
   107 			comboBox.DropDownStyle = ComboBoxStyle.DropDownList;
   108 			comboBox.DropDownClosed += new EventHandler(EditorDropDownClosed);
   109 			SetEditControlProperties(comboBox, node);
   110 			return comboBox;
   111 		}
   112 
   113 		private Control CreateCheckedListBox(TreeNodeAdv node)
   114 		{
   115 			CheckedListBox listBox = new CheckedListBox();
   116 			listBox.CheckOnClick = true;
   117 
   118 			object value = GetValue(node);
   119 			Type enumType = GetEnumType(node);
   120 			foreach (object obj in Enum.GetValues(enumType))
   121 			{
   122 				object[] attributes = enumType.GetField(obj.ToString()).GetCustomAttributes(typeof(BrowsableAttribute), false);
   123 				if (attributes.Length == 0 || ((BrowsableAttribute)attributes[0]).Browsable)
   124 					listBox.Items.Add(obj, IsContain(value, obj));
   125 			}
   126 
   127 			SetEditControlProperties(listBox, node);
   128 			if (CreatingEditor != null)
   129 				CreatingEditor(this, new EditEventArgs(node, listBox));
   130 			return listBox;
   131 		}
   132 
   133 		protected virtual Type GetEnumType(TreeNodeAdv node)
   134 		{
   135 			object value = GetValue(node);
   136 			return value.GetType();
   137 		}
   138 
   139 		private bool IsContain(object value, object enumElement)
   140 		{
   141 			if (value == null || enumElement == null)
   142 				return false;
   143 			if (value.GetType().IsEnum)
   144 			{
   145 				int i1 = (int)value;
   146 				int i2 = (int)enumElement;
   147 				return (i1 & i2) == i2;
   148 			}
   149 			else
   150 			{
   151 				var arr = value as object[];
   152 				foreach (object obj in arr)
   153 					if ((int)obj == (int)enumElement)
   154 						return true;
   155 				return false;
   156 			}
   157 		}
   158 
   159 		protected override string FormatLabel(object obj)
   160 		{
   161 			var arr = obj as object[];
   162 			if (arr != null)
   163 			{
   164 				StringBuilder sb = new StringBuilder();
   165 				foreach (object t in arr)
   166 				{
   167 					if (sb.Length > 0)
   168 						sb.Append(", ");
   169 					sb.Append(t);
   170 				}
   171 				return sb.ToString();
   172 			}
   173 			else
   174 				return base.FormatLabel(obj);
   175 		}
   176 
   177 		void EditorDropDownClosed(object sender, EventArgs e)
   178 		{
   179 			EndEdit(true);
   180 		}
   181 
   182 		public override void UpdateEditor(Control control)
   183 		{
   184 			if (control is ComboBox)
   185 				(control as ComboBox).DroppedDown = true;
   186 		}
   187 
   188 		protected override void DoApplyChanges(TreeNodeAdv node, Control editor)
   189 		{
   190 			var combo = editor as ComboBox;
   191 			if (combo != null)
   192 			{
   193 				if (combo.DropDownStyle == ComboBoxStyle.DropDown)
   194 					SetValue(node, combo.Text);
   195 				else
   196 					SetValue(node, combo.SelectedItem);
   197 			}
   198 			else
   199 			{
   200 				var listBox = editor as CheckedListBox;
   201 				Type type = GetEnumType(node);
   202 				if (IsFlags(type))
   203 				{
   204 					int res = 0;
   205 					foreach (object obj in listBox.CheckedItems)
   206 						res |= (int)obj;
   207 					object val = Enum.ToObject(type, res);
   208 					SetValue(node, val);
   209 				}
   210 				else
   211 				{
   212 					List<object> list = new List<object>();
   213 					foreach (object obj in listBox.CheckedItems)
   214 						list.Add(obj);
   215 					SetValue(node, list.ToArray());
   216 				}
   217 			}
   218 		}
   219 
   220 		private bool IsFlags(Type type)
   221 		{
   222 			object[] atr = type.GetCustomAttributes(typeof(FlagsAttribute), false);
   223 			return atr.Length == 1;
   224 		}
   225 
   226 		public override void MouseUp(TreeNodeAdvMouseEventArgs args)
   227 		{
   228 			if (args.Node != null && args.Node.IsSelected) //Workaround of specific ComboBox control behavior
   229 				base.MouseUp(args);
   230 		}
   231 	}
   232 }