using System; using System.Drawing; using Gwen.ControlInternal; namespace Gwen.Control { /// /// ComboBox control. /// public class ComboBox : Button { private readonly Menu m_Menu; private readonly Base m_Button; private MenuItem m_SelectedItem; /// /// Invoked when the selected item has changed. /// public event GwenEventHandler ItemSelected; /// /// Indicates whether the combo menu is open. /// public bool IsOpen { get { return m_Menu != null && !m_Menu.IsHidden; } } /// /// Initializes a new instance of the class. /// /// Parent control. public ComboBox(Base parent) : base(parent) { SetSize(100, 20); m_Menu = new Menu(this); m_Menu.IsHidden = true; m_Menu.IconMarginDisabled = true; m_Menu.IsTabable = false; DownArrow arrow = new DownArrow(this); m_Button = arrow; Alignment = Pos.Left | Pos.CenterV; Text = String.Empty; Margin = new Margin(3, 0, 0, 0); IsTabable = true; KeyboardInputEnabled = true; } /// /// Selected item. /// /// Not just String property, because items also have internal names. public Label SelectedItem { get { return m_SelectedItem; } } internal override bool IsMenuComponent { get { return true; } } /// /// Adds a new item. /// /// Item label (displayed). /// Item name. /// Newly created control. public virtual MenuItem AddItem(String label, String name = "") { MenuItem item = m_Menu.AddItem(label, String.Empty); item.Name = name; item.Selected += OnItemSelected; if (m_SelectedItem == null) OnItemSelected(item); return item; } /// /// Renders the control using specified skin. /// /// Skin to use. protected override void Render(Skin.Base skin) { skin.DrawComboBox(this, IsDepressed, IsOpen); } /// /// Internal Pressed implementation. /// protected override void OnClicked() { if (IsOpen) { GetCanvas().CloseMenus(); return; } bool wasMenuHidden = m_Menu.IsHidden; GetCanvas().CloseMenus(); if (wasMenuHidden) { Open(); } } /// /// Removes all items. /// public virtual void DeleteAll() { if (m_Menu != null) m_Menu.DeleteAll(); } /// /// Internal handler for item selected event. /// /// Event source. protected virtual void OnItemSelected(Base control) { //Convert selected to a menu item MenuItem item = control as MenuItem; if (null == item) return; m_SelectedItem = item; Text = m_SelectedItem.Text; m_Menu.IsHidden = true; if (ItemSelected != null) ItemSelected.Invoke(this); Focus(); Invalidate(); } /// /// Lays out the control's interior according to alignment, padding, dock etc. /// /// Skin to use. protected override void Layout(Skin.Base skin) { m_Button.Position(Pos.Right|Pos.CenterV, 4, 0); base.Layout(skin); } /// /// Handler for losing keyboard focus. /// protected override void OnLostKeyboardFocus() { TextColor = Color.Black; } /// /// Handler for gaining keyboard focus. /// protected override void OnKeyboardFocus() { //Until we add the blue highlighting again TextColor = Color.Black; } /// /// Opens the combo. /// public virtual void Open() { if (null == m_Menu) return; m_Menu.Parent = GetCanvas(); m_Menu.IsHidden = false; m_Menu.BringToFront(); Point p = LocalPosToCanvas(Point.Empty); m_Menu.SetBounds(new Rectangle(p.X, p.Y + Height, Width, m_Menu.Height)); } /// /// Closes the combo. /// public virtual void Close() { if (m_Menu == null) return; m_Menu.Hide(); } /// /// Handler for Down Arrow keyboard event. /// /// Indicates whether the key was pressed or released. /// /// True if handled. /// protected override bool OnKeyDown(bool down) { if (down) { var it = m_Menu.Children.FindIndex(x => x == m_SelectedItem); if (it + 1 < m_Menu.Children.Count) OnItemSelected(m_Menu.Children[it + 1]); } return true; } /// /// Handler for Up Arrow keyboard event. /// /// Indicates whether the key was pressed or released. /// /// True if handled. /// protected override bool OnKeyUp(bool down) { if (down) { var it = m_Menu.Children.FindLastIndex(x => x == m_SelectedItem); if (it - 1 >= 0) OnItemSelected(m_Menu.Children[it - 1]); } return true; } /// /// Renders the focus overlay. /// /// Skin to use. protected override void RenderFocus(Skin.Base skin) { } } }