moel@345: using System; moel@345: using System.Collections.Generic; moel@345: using System.Text; moel@345: using System.Drawing; moel@345: using System.Windows.Forms; moel@345: using System.Reflection; moel@345: using System.ComponentModel; moel@345: using System.Drawing.Design; moel@345: moel@345: namespace Aga.Controls.Tree.NodeControls moel@345: { moel@345: public class NodeComboBox : BaseTextControl moel@345: { moel@345: #region Properties moel@345: moel@345: private int _editorWidth = 100; moel@345: [DefaultValue(100)] moel@345: public int EditorWidth moel@345: { moel@345: get { return _editorWidth; } moel@345: set { _editorWidth = value; } moel@345: } moel@345: moel@345: private int _editorHeight = 100; moel@345: [DefaultValue(100)] moel@345: public int EditorHeight moel@345: { moel@345: get { return _editorHeight; } moel@345: set { _editorHeight = value; } moel@345: } moel@345: moel@345: private List _dropDownItems; moel@345: [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1002:DoNotExposeGenericLists")] moel@345: [Editor(typeof(StringCollectionEditor), typeof(UITypeEditor)), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] moel@345: public List DropDownItems moel@345: { moel@345: get { return _dropDownItems; } moel@345: } moel@345: moel@345: #endregion moel@345: moel@345: public event EventHandler CreatingEditor; moel@345: moel@345: public NodeComboBox() moel@345: { moel@345: _dropDownItems = new List(); moel@345: } moel@345: moel@345: protected override Size CalculateEditorSize(EditorContext context) moel@345: { moel@345: if (Parent.UseColumns) moel@345: { moel@345: if (context.Editor is CheckedListBox) moel@345: return new Size(context.Bounds.Size.Width, EditorHeight); moel@345: else moel@345: return context.Bounds.Size; moel@345: } moel@345: else moel@345: { moel@345: if (context.Editor is CheckedListBox) moel@345: return new Size(EditorWidth, EditorHeight); moel@345: else moel@345: return new Size(EditorWidth, context.Bounds.Height); moel@345: } moel@345: } moel@345: moel@345: protected override Control CreateEditor(TreeNodeAdv node) moel@345: { moel@345: Control c; moel@345: object value = GetValue(node); moel@345: if (IsCheckedListBoxRequired(node)) moel@345: c = CreateCheckedListBox(node); moel@345: else moel@345: c = CreateCombo(node); moel@345: OnCreatingEditor(new EditEventArgs(node, c)); moel@345: return c; moel@345: } moel@345: moel@345: protected override void DisposeEditor(Control editor) moel@345: { moel@345: } moel@345: moel@345: protected virtual void OnCreatingEditor(EditEventArgs args) moel@345: { moel@345: if (CreatingEditor != null) moel@345: CreatingEditor(this, args); moel@345: } moel@345: moel@345: protected virtual bool IsCheckedListBoxRequired(TreeNodeAdv node) moel@345: { moel@345: object value = GetValue(node); moel@345: if (value != null) moel@345: { moel@345: Type t = value.GetType(); moel@345: object[] arr = t.GetCustomAttributes(typeof(FlagsAttribute), false); moel@345: return (t.IsEnum && arr.Length == 1); moel@345: } moel@345: return false; moel@345: } moel@345: moel@345: private Control CreateCombo(TreeNodeAdv node) moel@345: { moel@345: ComboBox comboBox = new ComboBox(); moel@345: if (DropDownItems != null) moel@345: comboBox.Items.AddRange(DropDownItems.ToArray()); moel@345: comboBox.SelectedItem = GetValue(node); moel@345: comboBox.DropDownStyle = ComboBoxStyle.DropDownList; moel@345: comboBox.DropDownClosed += new EventHandler(EditorDropDownClosed); moel@345: SetEditControlProperties(comboBox, node); moel@345: return comboBox; moel@345: } moel@345: moel@345: private Control CreateCheckedListBox(TreeNodeAdv node) moel@345: { moel@345: CheckedListBox listBox = new CheckedListBox(); moel@345: listBox.CheckOnClick = true; moel@345: moel@345: object value = GetValue(node); moel@345: Type enumType = GetEnumType(node); moel@345: foreach (object obj in Enum.GetValues(enumType)) moel@345: { moel@345: object[] attributes = enumType.GetField(obj.ToString()).GetCustomAttributes(typeof(BrowsableAttribute), false); moel@345: if (attributes.Length == 0 || ((BrowsableAttribute)attributes[0]).Browsable) moel@345: listBox.Items.Add(obj, IsContain(value, obj)); moel@345: } moel@345: moel@345: SetEditControlProperties(listBox, node); moel@345: if (CreatingEditor != null) moel@345: CreatingEditor(this, new EditEventArgs(node, listBox)); moel@345: return listBox; moel@345: } moel@345: moel@345: protected virtual Type GetEnumType(TreeNodeAdv node) moel@345: { moel@345: object value = GetValue(node); moel@345: return value.GetType(); moel@345: } moel@345: moel@345: private bool IsContain(object value, object enumElement) moel@345: { moel@345: if (value == null || enumElement == null) moel@345: return false; moel@345: if (value.GetType().IsEnum) moel@345: { moel@345: int i1 = (int)value; moel@345: int i2 = (int)enumElement; moel@345: return (i1 & i2) == i2; moel@345: } moel@345: else moel@345: { moel@345: var arr = value as object[]; moel@345: foreach (object obj in arr) moel@345: if ((int)obj == (int)enumElement) moel@345: return true; moel@345: return false; moel@345: } moel@345: } moel@345: moel@345: protected override string FormatLabel(object obj) moel@345: { moel@345: var arr = obj as object[]; moel@345: if (arr != null) moel@345: { moel@345: StringBuilder sb = new StringBuilder(); moel@345: foreach (object t in arr) moel@345: { moel@345: if (sb.Length > 0) moel@345: sb.Append(", "); moel@345: sb.Append(t); moel@345: } moel@345: return sb.ToString(); moel@345: } moel@345: else moel@345: return base.FormatLabel(obj); moel@345: } moel@345: moel@345: void EditorDropDownClosed(object sender, EventArgs e) moel@345: { moel@345: EndEdit(true); moel@345: } moel@345: moel@345: public override void UpdateEditor(Control control) moel@345: { moel@345: if (control is ComboBox) moel@345: (control as ComboBox).DroppedDown = true; moel@345: } moel@345: moel@345: protected override void DoApplyChanges(TreeNodeAdv node, Control editor) moel@345: { moel@345: var combo = editor as ComboBox; moel@345: if (combo != null) moel@345: { moel@345: if (combo.DropDownStyle == ComboBoxStyle.DropDown) moel@345: SetValue(node, combo.Text); moel@345: else moel@345: SetValue(node, combo.SelectedItem); moel@345: } moel@345: else moel@345: { moel@345: var listBox = editor as CheckedListBox; moel@345: Type type = GetEnumType(node); moel@345: if (IsFlags(type)) moel@345: { moel@345: int res = 0; moel@345: foreach (object obj in listBox.CheckedItems) moel@345: res |= (int)obj; moel@345: object val = Enum.ToObject(type, res); moel@345: SetValue(node, val); moel@345: } moel@345: else moel@345: { moel@345: List list = new List(); moel@345: foreach (object obj in listBox.CheckedItems) moel@345: list.Add(obj); moel@345: SetValue(node, list.ToArray()); moel@345: } moel@345: } moel@345: } moel@345: moel@345: private bool IsFlags(Type type) moel@345: { moel@345: object[] atr = type.GetCustomAttributes(typeof(FlagsAttribute), false); moel@345: return atr.Length == 1; moel@345: } moel@345: moel@345: public override void MouseUp(TreeNodeAdvMouseEventArgs args) moel@345: { moel@345: if (args.Node != null && args.Node.IsSelected) //Workaround of specific ComboBox control behavior moel@345: base.MouseUp(args); moel@345: } moel@345: } moel@345: }