From 391c67b1a94895e4909fb4680f13023337b7d277 Mon Sep 17 00:00:00 2001 From: xxSeys1 Date: Sun, 23 Mar 2025 14:09:59 +0100 Subject: [PATCH] add visibility options for the tab close button --- Source/Editor/GUI/Docking/DockPanelProxy.cs | 61 +++++++++++++++------ Source/Editor/Options/InterfaceOptions.cs | 26 +++++++++ 2 files changed, 70 insertions(+), 17 deletions(-) diff --git a/Source/Editor/GUI/Docking/DockPanelProxy.cs b/Source/Editor/GUI/Docking/DockPanelProxy.cs index ef6c2cb1a..983497c59 100644 --- a/Source/Editor/GUI/Docking/DockPanelProxy.cs +++ b/Source/Editor/GUI/Docking/DockPanelProxy.cs @@ -14,6 +14,7 @@ namespace FlaxEditor.GUI.Docking public class DockPanelProxy : ContainerControl { private DockPanel _panel; + private InterfaceOptions.TabCloseButtonVisibility closeButtonVisibility; private double _dragEnterTime = -1; private float _tabHeight = Editor.Instance.Options.Options.Interface.TabHeight; private bool _useMinimumTabWidth = Editor.Instance.Options.Options.Interface.UseMinimumTabWidth; @@ -74,6 +75,14 @@ namespace FlaxEditor.GUI.Docking _panel = panel; AnchorPreset = AnchorPresets.StretchAll; Offsets = Margin.Zero; + + Editor.Instance.Options.OptionsChanged += OnEditorOptionsChanged; + OnEditorOptionsChanged(Editor.Instance.Options.Options); + } + + private void OnEditorOptionsChanged(EditorOptions options) + { + closeButtonVisibility = options.Interface.ShowTabCloseButton; } private DockWindow GetTabAtPos(Float2 position, out bool closeButton) @@ -87,8 +96,8 @@ namespace FlaxEditor.GUI.Docking var crossRect = new Rectangle(Width - DockPanel.DefaultButtonsSize - DockPanel.DefaultButtonsMargin, (HeaderRectangle.Height - DockPanel.DefaultButtonsSize) / 2, DockPanel.DefaultButtonsSize, DockPanel.DefaultButtonsSize); if (HeaderRectangle.Contains(position)) { - closeButton = crossRect.Contains(position); result = _panel.GetTab(0); + closeButton = crossRect.Contains(position) && IsCloseButtonVisible(result, closeButtonVisibility); } } else @@ -97,9 +106,7 @@ namespace FlaxEditor.GUI.Docking for (int i = 0; i < tabsCount; i++) { var tab = _panel.GetTab(i); - var titleSize = tab.TitleSize; - var iconWidth = tab.Icon.IsValid ? DockPanel.DefaultButtonsSize + DockPanel.DefaultLeftTextMargin : 0; - var width = titleSize.X + DockPanel.DefaultButtonsSize + 2 * DockPanel.DefaultButtonsMargin + DockPanel.DefaultLeftTextMargin + DockPanel.DefaultRightTextMargin + iconWidth; + float width = CalculateTabWidth(tab, closeButtonVisibility); if (_useMinimumTabWidth && width < _minimumTabWidth) width = _minimumTabWidth; @@ -109,7 +116,7 @@ namespace FlaxEditor.GUI.Docking if (isMouseOver) { var crossRect = new Rectangle(x + width - DockPanel.DefaultButtonsSize - DockPanel.DefaultButtonsMargin, (HeaderRectangle.Height - DockPanel.DefaultButtonsSize) / 2, DockPanel.DefaultButtonsSize, DockPanel.DefaultButtonsSize); - closeButton = crossRect.Contains(position); + closeButton = crossRect.Contains(position) && IsCloseButtonVisible(tab, closeButtonVisibility); result = tab; break; } @@ -120,6 +127,24 @@ namespace FlaxEditor.GUI.Docking return result; } + private bool IsCloseButtonVisible(DockWindow win, InterfaceOptions.TabCloseButtonVisibility visibilityMode) + { + return visibilityMode != InterfaceOptions.TabCloseButtonVisibility.Never && + (visibilityMode == InterfaceOptions.TabCloseButtonVisibility.Always || + (visibilityMode == InterfaceOptions.TabCloseButtonVisibility.SelectedTab && _panel.SelectedTab == win)); + } + + private float CalculateTabWidth(DockWindow win, InterfaceOptions.TabCloseButtonVisibility visibilityMode) + { + var iconWidth = win.Icon.IsValid ? DockPanel.DefaultButtonsSize + DockPanel.DefaultLeftTextMargin : 0; + var width = win.TitleSize.X + DockPanel.DefaultLeftTextMargin + DockPanel.DefaultRightTextMargin + iconWidth; + + if (IsCloseButtonVisible(win, visibilityMode)) + width += 2 * DockPanel.DefaultButtonsMargin + DockPanel.DefaultButtonsSize; + + return width; + } + private void GetTabRect(DockWindow win, out Rectangle bounds) { FlaxEngine.Assertions.Assert.IsTrue(_panel.ContainsTab(win)); @@ -137,7 +162,7 @@ namespace FlaxEditor.GUI.Docking { var tab = _panel.GetTab(i); var titleSize = tab.TitleSize; - float width = titleSize.X + DockPanel.DefaultButtonsSize + 2 * DockPanel.DefaultButtonsMargin + DockPanel.DefaultLeftTextMargin + DockPanel.DefaultRightTextMargin; + float width = CalculateTabWidth(tab, closeButtonVisibility); if (tab == win) { bounds = new Rectangle(x, 0, width, HeaderRectangle.Height); @@ -234,12 +259,15 @@ namespace FlaxEditor.GUI.Docking TextAlignment.Near, TextAlignment.Center); - // Draw cross - var crossRect = new Rectangle(Width - DockPanel.DefaultButtonsSize - DockPanel.DefaultButtonsMargin, (HeaderRectangle.Height - DockPanel.DefaultButtonsSize) / 2, DockPanel.DefaultButtonsSize, DockPanel.DefaultButtonsSize); - bool isMouseOverCross = isMouseOver && crossRect.Contains(MousePosition); - if (isMouseOverCross) - Render2D.FillRectangle(crossRect, (containsFocus ? style.BackgroundSelected : style.LightBackground) * 1.3f); - Render2D.DrawSprite(style.Cross, crossRect, isMouseOverCross ? style.Foreground : style.ForegroundGrey); + if (IsCloseButtonVisible(tab, closeButtonVisibility)) + { + // Draw cross + var crossRect = new Rectangle(Width - DockPanel.DefaultButtonsSize - DockPanel.DefaultButtonsMargin, (HeaderRectangle.Height - DockPanel.DefaultButtonsSize) / 2, DockPanel.DefaultButtonsSize, DockPanel.DefaultButtonsSize); + bool isMouseOverCross = isMouseOver && crossRect.Contains(MousePosition); + if (isMouseOverCross) + Render2D.FillRectangle(crossRect, (containsFocus ? style.BackgroundSelected : style.LightBackground) * 1.3f); + Render2D.DrawSprite(style.Cross, crossRect, isMouseOverCross ? style.Foreground : style.ForegroundGrey); + } } else { @@ -253,10 +281,9 @@ namespace FlaxEditor.GUI.Docking // Cache data var tab = _panel.GetTab(i); var tabColor = Color.Black; - var titleSize = tab.TitleSize; var iconWidth = tab.Icon.IsValid ? DockPanel.DefaultButtonsSize + DockPanel.DefaultLeftTextMargin : 0; - - var width = titleSize.X + DockPanel.DefaultButtonsSize + 2 * DockPanel.DefaultButtonsMargin + DockPanel.DefaultLeftTextMargin + DockPanel.DefaultRightTextMargin + iconWidth; + + float width = CalculateTabWidth(tab, closeButtonVisibility); if (_useMinimumTabWidth && width < _minimumTabWidth) width = _minimumTabWidth; @@ -303,7 +330,7 @@ namespace FlaxEditor.GUI.Docking TextAlignment.Center); // Draw cross - if (isSelected || isMouseOver) + if (IsCloseButtonVisible(tab, closeButtonVisibility)) { var crossRect = new Rectangle(x + width - DockPanel.DefaultButtonsSize - DockPanel.DefaultButtonsMargin, (HeaderRectangle.Height - DockPanel.DefaultButtonsSize) / 2, DockPanel.DefaultButtonsSize, DockPanel.DefaultButtonsSize); bool isMouseOverCross = isMouseOver && crossRect.Contains(MousePosition); @@ -312,7 +339,7 @@ namespace FlaxEditor.GUI.Docking Render2D.DrawSprite(style.Cross, crossRect, isMouseOverCross ? style.Foreground : style.ForegroundGrey); } - // Move + // Set the start position for the next tab x += width; } diff --git a/Source/Editor/Options/InterfaceOptions.cs b/Source/Editor/Options/InterfaceOptions.cs index 1e58b2a23..06679f24b 100644 --- a/Source/Editor/Options/InterfaceOptions.cs +++ b/Source/Editor/Options/InterfaceOptions.cs @@ -76,6 +76,25 @@ namespace FlaxEditor.Options DockBottom = DockState.DockBottom } + /// + /// Options for the visibility status of the tab close button. + /// + public enum TabCloseButtonVisibility + { + /// + /// Never show the close button. + /// + Never, + /// + /// Show the close button on tabs that are currently selected. + /// + SelectedTab, + /// + /// Show the close button on all tabs that can be closed. + /// + Always + } + /// /// Options for the action taken by the play button. /// @@ -295,6 +314,13 @@ namespace FlaxEditor.Options [EditorDisplay("Tabs & Windows", "New Window Location"), EditorOrder(150), Tooltip("Define the opening method for new windows, open in a new tab by default.")] public DockStateProxy NewWindowLocation { get; set; } = DockStateProxy.Float; + /// + /// Gets or sets a value indicating when the tab close button should be visible. + /// + [DefaultValue(TabCloseButtonVisibility.SelectedTab)] + [EditorDisplay("Tabs & Windows"), EditorOrder(151)] + public TabCloseButtonVisibility ShowTabCloseButton { get; set; } = TabCloseButtonVisibility.SelectedTab; + /// /// Gets or sets the timestamps prefix mode for output log messages. ///