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