Refactor Editor Tab controls system to allows customizing the tab header controls
This commit is contained in:
@@ -77,5 +77,14 @@ namespace FlaxEditor.GUI.Tabs
|
||||
{
|
||||
Deselected?.Invoke(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Factory method for tabs header control (UI for the tabs strip to represent this tab).
|
||||
/// </summary>
|
||||
/// <returns>The tab header control.</returns>
|
||||
public virtual Tabs.TabHeader CreateHeader()
|
||||
{
|
||||
return new Tabs.TabHeader((Tabs)Parent, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,11 +24,6 @@ namespace FlaxEditor.GUI.Tabs
|
||||
/// </summary>
|
||||
protected Tabs Tabs;
|
||||
|
||||
/// <summary>
|
||||
/// The index of the tab.
|
||||
/// </summary>
|
||||
protected int Index;
|
||||
|
||||
/// <summary>
|
||||
/// The tab.
|
||||
/// </summary>
|
||||
@@ -38,21 +33,22 @@ namespace FlaxEditor.GUI.Tabs
|
||||
/// Initializes a new instance of the <see cref="TabHeader"/> class.
|
||||
/// </summary>
|
||||
/// <param name="tabs">The tabs.</param>
|
||||
/// <param name="index">The tab index.</param>
|
||||
/// <param name="tab">The tab.</param>
|
||||
public TabHeader(Tabs tabs, int index, Tab tab)
|
||||
public TabHeader(Tabs tabs, Tab tab)
|
||||
: base(Float2.Zero, tabs._tabsSize)
|
||||
{
|
||||
Tabs = tabs;
|
||||
Index = index;
|
||||
Tab = tab;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool OnMouseUp(Float2 location, MouseButton button)
|
||||
{
|
||||
Tabs.SelectedTabIndex = Index;
|
||||
Tabs.Focus();
|
||||
if (EnabledInHierarchy && Tab.Enabled)
|
||||
{
|
||||
Tabs.SelectedTab = Tab;
|
||||
Tabs.Focus();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -61,19 +57,20 @@ namespace FlaxEditor.GUI.Tabs
|
||||
{
|
||||
base.Draw();
|
||||
|
||||
// Cache data
|
||||
var style = Style.Current;
|
||||
var enabled = EnabledInHierarchy && Tab.EnabledInHierarchy;
|
||||
var tabRect = new Rectangle(Float2.Zero, Size);
|
||||
bool isTabSelected = Tabs._selectedIndex == Index;
|
||||
bool isMouseOverTab = IsMouseOver;
|
||||
var textOffset = Tabs._orientation == Orientation.Horizontal ? 0 : 8;
|
||||
|
||||
// Draw bar
|
||||
if (isTabSelected)
|
||||
if (Tabs.SelectedTab == Tab)
|
||||
{
|
||||
var color = style.BackgroundSelected;
|
||||
if (!enabled)
|
||||
color *= 0.6f;
|
||||
if (Tabs._orientation == Orientation.Horizontal)
|
||||
{
|
||||
Render2D.FillRectangle(tabRect, style.BackgroundSelected);
|
||||
Render2D.FillRectangle(tabRect, color);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -84,10 +81,10 @@ namespace FlaxEditor.GUI.Tabs
|
||||
fillRect.Size.X -= lefEdgeWidth;
|
||||
fillRect.Location.X += lefEdgeWidth;
|
||||
Render2D.FillRectangle(fillRect, style.Background);
|
||||
Render2D.FillRectangle(leftEdgeRect, style.BackgroundSelected);
|
||||
Render2D.FillRectangle(leftEdgeRect, color);
|
||||
}
|
||||
}
|
||||
else if (isMouseOverTab)
|
||||
else if (IsMouseOver && enabled)
|
||||
{
|
||||
Render2D.FillRectangle(tabRect, style.BackgroundHighlighted);
|
||||
}
|
||||
@@ -131,20 +128,15 @@ namespace FlaxEditor.GUI.Tabs
|
||||
{
|
||||
base.PerformLayoutBeforeChildren();
|
||||
|
||||
// Cache data
|
||||
var tabsSize = Tabs._tabsSize;
|
||||
var clientSize = GetClientArea();
|
||||
tabsSize = Float2.Min(tabsSize, clientSize.Size);
|
||||
var tabRect = new Rectangle(Float2.Zero, tabsSize);
|
||||
var tabStripOffset = Tabs._orientation == Orientation.Horizontal ? new Float2(tabsSize.X, 0) : new Float2(0, tabsSize.Y);
|
||||
|
||||
// Arrange tab header controls
|
||||
var pos = Float2.Zero;
|
||||
var sizeMask = Tabs._orientation == Orientation.Horizontal ? Float2.UnitX : Float2.UnitY;
|
||||
for (int i = 0; i < Children.Count; i++)
|
||||
{
|
||||
if (Children[i] is TabHeader tabHeader)
|
||||
{
|
||||
tabHeader.Bounds = tabRect;
|
||||
tabRect.Offset(tabStripOffset);
|
||||
tabHeader.Location = pos;
|
||||
pos += tabHeader.Size * sizeMask;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -160,6 +152,11 @@ namespace FlaxEditor.GUI.Tabs
|
||||
/// </summary>
|
||||
protected Float2 _tabsSize;
|
||||
|
||||
/// <summary>
|
||||
/// Automatic tab size based on the fill axis.
|
||||
/// </summary>
|
||||
protected bool _autoTabsSizeAuto;
|
||||
|
||||
/// <summary>
|
||||
/// The orientation.
|
||||
/// </summary>
|
||||
@@ -174,15 +171,31 @@ namespace FlaxEditor.GUI.Tabs
|
||||
set
|
||||
{
|
||||
_tabsSize = value;
|
||||
for (int i = 0; i < TabsPanel.ChildrenCount; i++)
|
||||
if (!_autoTabsSizeAuto)
|
||||
{
|
||||
if (TabsPanel.Children[i] is TabHeader tabHeader)
|
||||
tabHeader.Size = value;
|
||||
for (int i = 0; i < TabsPanel.ChildrenCount; i++)
|
||||
{
|
||||
if (TabsPanel.Children[i] is TabHeader tabHeader)
|
||||
tabHeader.Size = value;
|
||||
}
|
||||
}
|
||||
PerformLayout();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enables automatic tabs size to fill the space.
|
||||
/// </summary>
|
||||
public bool AutoTabsSize
|
||||
{
|
||||
get => _autoTabsSizeAuto;
|
||||
set
|
||||
{
|
||||
_autoTabsSizeAuto = value;
|
||||
PerformLayout();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the orientation.
|
||||
/// </summary>
|
||||
@@ -339,14 +352,10 @@ namespace FlaxEditor.GUI.Tabs
|
||||
|
||||
// Update tabs headers
|
||||
TabsPanel.DisposeChildren();
|
||||
int index = 0;
|
||||
for (int i = 0; i < Children.Count; i++)
|
||||
{
|
||||
if (Children[i] is Tab tab)
|
||||
{
|
||||
var tabHeader = new TabHeader(this, index++, tab);
|
||||
TabsPanel.AddChild(tabHeader);
|
||||
}
|
||||
TabsPanel.AddChild(tab.CreateHeader());
|
||||
}
|
||||
|
||||
TabsPanel.IsLayoutLocked = wasLocked;
|
||||
@@ -371,23 +380,46 @@ namespace FlaxEditor.GUI.Tabs
|
||||
/// <inheritdoc />
|
||||
protected override void PerformLayoutBeforeChildren()
|
||||
{
|
||||
var tabsSize = _tabsSize;
|
||||
if (_autoTabsSizeAuto)
|
||||
{
|
||||
// Horizontal is default for Toolbox so tabs go to the right
|
||||
int tabsCount = 0;
|
||||
for (int i = 0; i < TabsPanel.ChildrenCount; i++)
|
||||
{
|
||||
if (TabsPanel.Children[i] is TabHeader)
|
||||
tabsCount++;
|
||||
}
|
||||
if (tabsCount == 0)
|
||||
tabsCount = 1;
|
||||
if (_orientation == Orientation.Horizontal)
|
||||
tabsSize.X = Width / tabsCount;
|
||||
else
|
||||
tabsSize.Y = Height / tabsCount;
|
||||
for (int i = 0; i < TabsPanel.ChildrenCount; i++)
|
||||
{
|
||||
if (TabsPanel.Children[i] is TabHeader tabHeader)
|
||||
tabHeader.Size = tabsSize;
|
||||
}
|
||||
}
|
||||
|
||||
// Fit the tabs panel
|
||||
TabsPanel.Size = _orientation == Orientation.Horizontal ? new Float2(Width, _tabsSize.Y) : new Float2(_tabsSize.X, Height);
|
||||
TabsPanel.Size = _orientation == Orientation.Horizontal
|
||||
? new Float2(Width, tabsSize.Y)
|
||||
: new Float2(tabsSize.X, Height);
|
||||
|
||||
// Hide all pages except selected one
|
||||
var clientArea = _orientation == Orientation.Horizontal
|
||||
? new Rectangle(0, _tabsSize.Y, Width, Height - _tabsSize.Y)
|
||||
: new Rectangle(_tabsSize.X, 0, Width - _tabsSize.X, Height);
|
||||
for (int i = 0; i < Children.Count; i++)
|
||||
{
|
||||
if (Children[i] is Tab tab)
|
||||
{
|
||||
// Check if is selected or not
|
||||
if (i - 1 == _selectedIndex)
|
||||
{
|
||||
// Show and fit size
|
||||
tab.Visible = true;
|
||||
tab.Bounds = clientArea;
|
||||
tab.Bounds = _orientation == Orientation.Horizontal
|
||||
? new Rectangle(0, tabsSize.Y, Width, Height - tabsSize.Y)
|
||||
: new Rectangle(tabsSize.X, 0, Width - tabsSize.X, Height);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user