From 5ae2196a01812201c7a99a9e274beffec5d030db Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Wed, 7 Aug 2024 22:44:38 +0200 Subject: [PATCH] Add support for customizing `Dropdown` popup visuals --- Source/Engine/UI/GUI/Common/Dropdown.cs | 176 ++++++++++++++---------- 1 file changed, 107 insertions(+), 69 deletions(-) diff --git a/Source/Engine/UI/GUI/Common/Dropdown.cs b/Source/Engine/UI/GUI/Common/Dropdown.cs index e1dc1fb24..e23bca199 100644 --- a/Source/Engine/UI/GUI/Common/Dropdown.cs +++ b/Source/Engine/UI/GUI/Common/Dropdown.cs @@ -27,7 +27,7 @@ namespace FlaxEngine.GUI /// /// The selected control. Used to scroll to the control on popup creation. /// - public ContainerControl SelectedControl = null; + public Control SelectedControl = null; /// /// The main panel used to hold the items. @@ -460,37 +460,22 @@ namespace FlaxEngine.GUI /// protected virtual DropdownRoot CreatePopup() { - // TODO: support using templates for the items collection container panel + // Create popup + var popup = CreatePopupRoot(); + if (popup == null) + throw new NullReferenceException("Missing popup."); + if (popup.MainPanel == null) + throw new NullReferenceException("Missing popup MainPanel."); + CreatePopupBackground(popup); - var popup = new DropdownRoot(); - - // TODO: support item templates - - var panel = new Panel - { - AnchorPreset = AnchorPresets.StretchAll, - BackgroundColor = BackgroundColor, - ScrollBars = ScrollBars.Vertical, - AutoFocus = true, - Parent = popup, - }; - popup.MainPanel = panel; - - var container = new VerticalPanel + // Create items container + var itemContainer = new VerticalPanel { AnchorPreset = AnchorPresets.StretchAll, BackgroundColor = Color.Transparent, IsScrollable = true, AutoSize = true, - Parent = panel, - }; - var border = new Border - { - BorderColor = BorderColorHighlighted, - Width = 4.0f, - AnchorPreset = AnchorPresets.StretchAll, - Offsets = Margin.Zero, - Parent = popup, + Parent = popup.MainPanel, }; var itemsHeight = 20.0f; @@ -513,69 +498,122 @@ namespace FlaxEngine.GUI */ var itemsWidth = Width; - var height = container.Margin.Height; + var height = itemContainer.Margin.Height; for (int i = 0; i < _items.Count; i++) { - var item = new ContainerControl - { - AutoFocus = false, - Height = itemsHeight, - Width = itemsWidth, - Parent = container, - }; - - var label = new DropdownLabel - { - AutoFocus = true, - X = itemsMargin, - Size = new Float2(itemsWidth - itemsMargin, itemsHeight), - Font = Font, - TextColor = Color.White * 0.9f, - TextColorHighlighted = Color.White, - HorizontalAlignment = HorizontalAlignment, - VerticalAlignment = VerticalAlignment, - Text = _items[i], - Parent = item, - Tag = i, - }; - label.ItemClicked += c => - { - OnItemClicked((int)c.Tag); - DestroyPopup(); - }; + var item = CreatePopupItem(i, new Float2(itemsWidth, itemsHeight), itemsMargin); + item.Parent = itemContainer; height += itemsHeight; if (i != 0) - height += container.Spacing; - + height += itemContainer.Spacing; if (_selectedIndex == i) - { - var icon = new Image - { - Brush = CheckedImage, - Size = new Float2(itemsMargin, itemsHeight), - Margin = new Margin(4.0f, 6.0f, 4.0f, 4.0f), - //AnchorPreset = AnchorPresets.VerticalStretchLeft, - Parent = item, - }; popup.SelectedControl = item; - } } if (ShowAllItems || _items.Count < ShowMaxItemsCount) { popup.Size = new Float2(itemsWidth, height); - panel.Size = popup.Size; + popup.MainPanel.Size = popup.Size; } else { - popup.Size = new Float2(itemsWidth, (itemsHeight + container.Spacing) * ShowMaxItemsCount); - panel.Size = popup.Size; + popup.Size = new Float2(itemsWidth, (itemsHeight + itemContainer.Spacing) * ShowMaxItemsCount); + popup.MainPanel.Size = popup.Size; } return popup; } + /// + /// Creates the popup root. Called by default implementation of and allows to customize popup base. + /// + /// Custom popup root control. + protected virtual DropdownRoot CreatePopupRoot() + { + var popup = new DropdownRoot(); + + var panel = new Panel + { + AnchorPreset = AnchorPresets.StretchAll, + BackgroundColor = BackgroundColor, + ScrollBars = ScrollBars.Vertical, + AutoFocus = true, + Parent = popup, + }; + popup.MainPanel = panel; + + return popup; + } + + /// + /// Creates the popup background. Called by default implementation of and allows to customize popup background by adding controls to it. + /// + /// The popup control where background controls can be added. + protected virtual void CreatePopupBackground(DropdownRoot popup) + { + // Default background outline + var border = new Border + { + BorderColor = BorderColorHighlighted, + Width = 4.0f, + AnchorPreset = AnchorPresets.StretchAll, + Offsets = Margin.Zero, + Parent = popup, + }; + } + + /// + /// Creates the popup item. Called by default implementation of and allows to customize popup item. + /// + /// The item index. + /// The item control size + /// The item control left-side margin + /// Custom popup item control. + protected virtual Control CreatePopupItem(int i, Float2 size, float margin) + { + // Default item with label + var item = new ContainerControl + { + AutoFocus = false, + Size = size, + }; + var label = new DropdownLabel + { + AutoFocus = true, + X = margin, + Size = new Float2(size.X - margin, size.Y), + Font = Font, + TextColor = Color.White * 0.9f, + TextColorHighlighted = Color.White, + HorizontalAlignment = HorizontalAlignment, + VerticalAlignment = VerticalAlignment, + Text = _items[i], + Parent = item, + Tag = i, + }; + label.ItemClicked += c => + { + OnItemClicked((int)c.Tag); + DestroyPopup(); + }; + + if (_selectedIndex == i) + { + // Add icon to the selected item + var icon = new Image + { + Brush = CheckedImage, + Size = new Float2(margin, size.Y), + Margin = new Margin(4.0f, 6.0f, 4.0f, 4.0f), + //AnchorPreset = AnchorPresets.VerticalStretchLeft, + Parent = item, + }; + } + + return item; + } + /// /// Called when popup menu gets shown. ///