using System; using System.Collections.Specialized; using System.Collections.Generic; using System.Linq; using System.Text; using MatterHackers.VectorMath; using MatterHackers.MatterControl; using MatterHackers.Agg.VertexSource; namespace MatterHackers.Agg.UI { public class DropDownMenu : Menu { public event EventHandler SelectionChanged; TextWidget mainControlText; public bool MenuAsWideAsItems { get; set; } int borderWidth = 1; public int BorderWidth { get { return borderWidth; } set { borderWidth = value; } } RGBA_Bytes borderColor; public RGBA_Bytes BorderColor { get { return borderColor; } set { borderColor = value; } } RGBA_Bytes arrowColor; public RGBA_Bytes ArrowColor { get { return arrowColor; } set { arrowColor = value; } } RGBA_Bytes normalColor; public RGBA_Bytes NormalColor { get { return normalColor; } set { normalColor = value; } } RGBA_Bytes hoverColor; public RGBA_Bytes HoverColor { get { return hoverColor; } set { hoverColor = value; } } RGBA_Bytes textColor = RGBA_Bytes.Black; public RGBA_Bytes TextColor { get { return textColor; } set { textColor = value; //mainControlText.TextColor = TextColor; } } int selectedIndex = -1; public int SelectedIndex { get { return selectedIndex; } set { selectedIndex = value; OnSelectionChanged(null); Invalidate(); } } public String SelectedValue { get { return GetValue(SelectedIndex); } } public string GetValue(int itemIndex) { return MenuItems[SelectedIndex].Value; } public DropDownMenu(GuiWidget topMenuWidget, Direction direction = Direction.Down) : base(direction) { } public DropDownMenu(string topMenuText, Direction direction = Direction.Down, double pointSize = 12) : base(direction) { MenuAsWideAsItems = true; SetDisplayAttributes(); MenuItems.CollectionChanged += new NotifyCollectionChangedEventHandler(MenuItems_CollectionChanged); mainControlText = new TextWidget(topMenuText, pointSize: pointSize); mainControlText.TextColor = this.TextColor; mainControlText.AutoExpandBoundsToText = true; mainControlText.VAnchor = UI.VAnchor.ParentCenter; mainControlText.HAnchor = UI.HAnchor.ParentLeft; AddChild(mainControlText); HAnchor = HAnchor.FitToChildren; VAnchor = VAnchor.FitToChildren; MouseEnter += new EventHandler(DropDownList_MouseEnter); MouseLeave += new EventHandler(DropDownList_MouseLeave); NormalColor = normalColor; HoverColor = hoverColor; BackgroundColor = normalColor; BorderColor = normalColor; //IE Don't show arrow unless color is set explicitly ArrowColor = new RGBA_Bytes(255, 255, 255, 0); } void DropDownList_MouseLeave(object sender, EventArgs e) { if (!this.IsOpen) { BackgroundColor = NormalColor; ArrowColor = new RGBA_Bytes(255, 255, 255, 0); } } void DropDownList_MouseEnter(object sender, EventArgs e) { BackgroundColor = HoverColor; ArrowColor = TextColor; } void OnSelectionChanged(EventArgs e) { if (SelectionChanged != null) { SelectionChanged(this, e); } } void MenuItems_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { Vector2 minSize = new Vector2(LocalBounds.Width, LocalBounds.Height); string startText = mainControlText.Text; foreach (MenuItem item in MenuItems) { mainControlText.Text = item.Text; minSize.x = Math.Max(minSize.x, LocalBounds.Width); minSize.y = Math.Max(minSize.y, LocalBounds.Height); } mainControlText.Text = startText; if (MenuAsWideAsItems) { this.MinimumSize = minSize; } foreach (MenuItem item in e.NewItems) { item.MinimumSize = minSize; // remove it if it is there so we don't have two. It is ok to remove a delagate that is not present. item.Selected -= new EventHandler(item_Selected); item.Selected += new EventHandler(item_Selected); } } void item_Selected(object sender, EventArgs e) { int newSelectedIndex = 0; foreach (MenuItem item in MenuItems) { if (item == sender) { break; } newSelectedIndex++; } SelectedIndex = newSelectedIndex; BackgroundColor = NormalColor; } private void SetDisplayAttributes() { this.TextColor = RGBA_Bytes.White; this.NormalColor = ActiveTheme.Instance.PrimaryBackgroundColor; this.HoverColor = RGBA_Bytes.Gray; this.MenuItemsBorderWidth = 1; this.MenuItemsBackgroundColor = RGBA_Bytes.White; this.MenuItemsBorderColor = RGBA_Bytes.Gray; this.MenuItemsPadding = new BorderDouble(10, 10, 10, 10); } public override void OnDraw(Graphics2D graphics2D) { base.OnDraw(graphics2D); this.DrawBorder(graphics2D); this.DrawDirectionalArrow(graphics2D); } private void DrawDirectionalArrow(Graphics2D graphics2D) { PathStorage littleArrow = new PathStorage(); if (this.MenuDirection == Direction.Down) { littleArrow.MoveTo(-4, 0); littleArrow.LineTo(4, 0); littleArrow.LineTo(0, -5); } else if (this.MenuDirection == Direction.Up) { littleArrow.MoveTo(-4, -5); littleArrow.LineTo(4, -5); littleArrow.LineTo(0, 0); } else { throw new NotImplementedException("Pulldown direction has not been implemented"); } graphics2D.Render(littleArrow, LocalBounds.Right - 10, LocalBounds.Bottom + Height - 4, arrowColor); } private void DrawBorder(Graphics2D graphics2D) { RectangleDouble Bounds = LocalBounds; RoundedRect borderRect = new RoundedRect(this.LocalBounds, 0); Stroke strokeRect = new Stroke(borderRect, borderWidth); graphics2D.Render(strokeRect, borderColor); } public void AddItem(string name, string value = null, double pointSize = 12) { if (value == null) { value = name; } mainControlText.Margin = MenuItemsPadding; GuiWidget normalTextWithMargin = new GuiWidget(); normalTextWithMargin.HAnchor = UI.HAnchor.ParentLeft; normalTextWithMargin.BackgroundColor = MenuItemsBackgroundColor; TextWidget normal = new TextWidget(name, pointSize: pointSize); normal.Margin = MenuItemsPadding; normal.TextColor = MenuItemsTextColor; normalTextWithMargin.AddChild(normal); normalTextWithMargin.HAnchor = HAnchor.FitToChildren; normalTextWithMargin.VAnchor = VAnchor.FitToChildren; GuiWidget hoverTextWithMargin = new GuiWidget(); hoverTextWithMargin.HAnchor = UI.HAnchor.ParentLeft; hoverTextWithMargin.BackgroundColor = MenuItemsBackgroundHoverColor; TextWidget hover = new TextWidget(name, pointSize: pointSize); hover.Margin = MenuItemsPadding; hover.TextColor = mainControlText.TextColor; hoverTextWithMargin.AddChild(hover); hoverTextWithMargin.HAnchor = HAnchor.FitToChildren; hoverTextWithMargin.VAnchor = VAnchor.FitToChildren; MenuItem menuItem = new MenuItem(new MenuItemStatesView(normalTextWithMargin, hoverTextWithMargin), value); menuItem.Text = name; MenuItems.Add(menuItem); } } }