diff --git a/Terminal.Gui/Views/TabView/Tab.cs b/Terminal.Gui/Views/TabView/Tab.cs
index 52fb0bdf9d..8451b74136 100644
--- a/Terminal.Gui/Views/TabView/Tab.cs
+++ b/Terminal.Gui/Views/TabView/Tab.cs
@@ -22,6 +22,7 @@ public string DisplayText
set
{
_displayText = value;
+ DisplayTextChanged?.Invoke (this, EventArgs.Empty);
SetNeedsLayout ();
}
}
@@ -29,4 +30,9 @@ public string DisplayText
/// The control to display when the tab is selected.
///
public View? View { get; set; }
+
+ ///
+ /// Raised when changed.
+ ///
+ public event EventHandler? DisplayTextChanged;
}
diff --git a/Terminal.Gui/Views/TabView/TabRow.cs b/Terminal.Gui/Views/TabView/TabRow.cs
index 2ca80a69ae..d1a72b4322 100644
--- a/Terminal.Gui/Views/TabView/TabRow.cs
+++ b/Terminal.Gui/Views/TabView/TabRow.cs
@@ -4,8 +4,8 @@ namespace Terminal.Gui;
internal class TabRow : View
{
private readonly TabView _host;
- private readonly View _leftScrollIndicator;
- private readonly View _rightScrollIndicator;
+ private readonly View _leftUpScrollIndicator;
+ private readonly View _rightDownScrollIndicator;
public TabRow (TabView host)
{
@@ -13,40 +13,48 @@ public TabRow (TabView host)
Id = "tabRow";
CanFocus = true;
+
+ // Because TabRow has focusable subviews, it must be a TabGroup
TabStop = TabBehavior.TabGroup;
Width = Dim.Fill ();
- _rightScrollIndicator = new View
+ _rightDownScrollIndicator = new ()
{
- Id = "rightScrollIndicator",
+ Id = "rightDownScrollIndicator",
Width = 1,
Height = 1,
- Visible = false,
- Text = Glyphs.RightArrow.ToString ()
+ Visible = false
};
- _rightScrollIndicator.MouseClick += _host.Tab_MouseClick!;
+ _rightDownScrollIndicator.MouseClick += _host.Tab_MouseClick!;
- _leftScrollIndicator = new View
+ _leftUpScrollIndicator = new ()
{
- Id = "leftScrollIndicator",
+ Id = "leftUpScrollIndicator",
Width = 1,
Height = 1,
- Visible = false,
- Text = Glyphs.LeftArrow.ToString ()
+ Visible = false
};
- _leftScrollIndicator.MouseClick += _host.Tab_MouseClick!;
+ _leftUpScrollIndicator.MouseClick += _host.Tab_MouseClick!;
+
+ Add (_rightDownScrollIndicator, _leftUpScrollIndicator);
+ }
+
+ ///
+ public override void EndInit ()
+ {
+ _host._tabLocations = _host.CalculateViewport (Viewport);
- Add (_rightScrollIndicator, _leftScrollIndicator);
+ base.EndInit ();
}
protected override bool OnMouseEvent (MouseEventArgs me)
{
View? parent = me.View is Adornment adornment ? adornment.Parent : me.View;
- Tab? hit = parent as Tab;
+ var hit = parent as Tab;
if (me.IsSingleClicked)
{
- _host.OnTabClicked (new TabMouseEventArgs (hit!, me));
+ _host.OnTabClicked (new (hit!, me));
// user canceled click
if (me.Handled)
@@ -74,11 +82,11 @@ protected override bool OnMouseEvent (MouseEventArgs me)
{
var scrollIndicatorHit = 0;
- if (me.View is { Id: "rightScrollIndicator" } || me.Flags.HasFlag (MouseFlags.WheeledDown) || me.Flags.HasFlag (MouseFlags.WheeledRight))
+ if (me.View is { Id: "rightDownScrollIndicator" } || me.Flags.HasFlag (MouseFlags.WheeledDown) || me.Flags.HasFlag (MouseFlags.WheeledRight))
{
scrollIndicatorHit = 1;
}
- else if (me.View is { Id: "leftScrollIndicator" } || me.Flags.HasFlag (MouseFlags.WheeledUp) || me.Flags.HasFlag (MouseFlags.WheeledLeft))
+ else if (me.View is { Id: "leftUpScrollIndicator" } || me.Flags.HasFlag (MouseFlags.WheeledUp) || me.Flags.HasFlag (MouseFlags.WheeledLeft))
{
scrollIndicatorHit = -1;
}
@@ -101,7 +109,7 @@ protected override bool OnMouseEvent (MouseEventArgs me)
return false;
}
- ///
+ ///
protected override void OnHasFocusChanged (bool newHasFocus, View? previousFocusedView, View? focusedView)
{
if (_host.SelectedTab is { HasFocus: false, CanFocus: true } && focusedView == this)
@@ -117,16 +125,23 @@ protected override void OnHasFocusChanged (bool newHasFocus, View? previousFocus
///
protected override void OnSubviewLayout (LayoutEventArgs args)
{
- _host._tabLocations = _host.CalculateViewport (Viewport).ToArray ();
+ if (_host._tabLocations is null)
+ {
+ return;
+ }
- RenderTabLine ();
+ if (_host is { SelectedTab: { }, _tabLocations: { } } && !_host._tabLocations!.Contains (_host.SelectedTab))
+ {
+ _host.SelectedTab = _host._tabLocations [0];
+ Application.Invoke (() => _host.SetNeedsLayout ());
+ }
RenderUnderline ();
base.OnSubviewLayout (args);
}
- ///
+ ///
protected override bool OnRenderingLineCanvas ()
{
RenderTabLineCanvas ();
@@ -149,7 +164,6 @@ private void RenderTabLineCanvas ()
{
View tab = tabLocations [i];
Rectangle vts = tab.ViewportToScreen (tab.Viewport);
- int selectedOffset = _host.Style.ShowTopLine && tabLocations [i] == _host.SelectedTab ? 0 : 1;
if (tabLocations [i] == _host.SelectedTab)
{
@@ -157,595 +171,1272 @@ private void RenderTabLineCanvas ()
if (i == 0 && _host.TabScrollOffset == 0)
{
- if (_host.Style.TabsOnBottom)
- {
- // Upper left vertical line
- lc.AddLine (
- new Point (vts.X - 1, vts.Y - 1),
- -1,
- Orientation.Vertical,
- tab.BorderStyle
- );
- }
- else
+ switch (_host.Style.TabsSide)
{
- // Lower left vertical line
- lc.AddLine (
- new Point (vts.X - 1, vts.Bottom - selectedOffset),
- -1,
- Orientation.Vertical,
- tab.BorderStyle
- );
+ case TabSide.Top:
+ // Lower left vertical line
+ lc.AddLine (
+ new (vts.X - 1, vts.Bottom),
+ -1,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ break;
+ case TabSide.Bottom:
+ // Upper left vertical line
+ lc.AddLine (
+ new (vts.X - 1, vts.Y - 1),
+ -1,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ break;
+ case TabSide.Left:
+ // Upper horizontal line
+ lc.AddLine (
+ new (vts.Right, vts.Y - 1),
+ -1,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+
+ break;
+ case TabSide.Right:
+ // Upper horizontal line
+ lc.AddLine (
+ new (vts.X - 1, vts.Y - 1),
+ -1,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+
+ break;
+ default:
+ throw new ArgumentOutOfRangeException ();
}
}
else if (i > 0 && i <= tabLocations.Length - 1)
{
- if (_host.Style.TabsOnBottom)
- {
- // URCorner
- lc.AddLine (
- new Point (vts.X - 1, vts.Y - 1),
- 1,
- Orientation.Vertical,
- tab.BorderStyle
- );
-
- lc.AddLine (
- new Point (vts.X - 1, vts.Y - 1),
- -1,
- Orientation.Horizontal,
- tab.BorderStyle
- );
- }
- else
- {
- // LRCorner
- lc.AddLine (
- new Point (vts.X - 1, vts.Bottom - selectedOffset),
- -1,
- Orientation.Vertical,
- tab.BorderStyle
- );
-
- lc.AddLine (
- new Point (vts.X - 1, vts.Bottom - selectedOffset),
- -1,
- Orientation.Horizontal,
- tab.BorderStyle
- );
- }
-
- if (_host.Style.ShowTopLine)
+ switch (_host.Style.TabsSide)
{
- if (_host.Style.TabsOnBottom)
- {
- // Lower left tee
+ case TabSide.Top:
+ // LRCorner
lc.AddLine (
- new Point (vts.X - 1, vts.Bottom),
+ new (vts.X - 1, vts.Bottom),
-1,
Orientation.Vertical,
tab.BorderStyle
);
lc.AddLine (
- new Point (vts.X - 1, vts.Bottom),
- 0,
+ new (vts.X - 1, vts.Bottom),
+ -1,
Orientation.Horizontal,
tab.BorderStyle
);
- }
- else
- {
- // Upper left tee
+
+ break;
+ case TabSide.Bottom:
+ // URCorner
lc.AddLine (
- new Point (vts.X - 1, vts.Y - 1),
+ new (vts.X - 1, vts.Y - 1),
1,
Orientation.Vertical,
tab.BorderStyle
);
lc.AddLine (
- new Point (vts.X - 1, vts.Y - 1),
- 0,
+ new (vts.X - 1, vts.Y - 1),
+ -1,
Orientation.Horizontal,
tab.BorderStyle
);
+
+ break;
+ case TabSide.Left:
+ if (Frame.Bottom > tab.Frame.Bottom)
+ {
+ // LRCorner
+ lc.AddLine (
+ new (vts.Right, vts.Bottom),
+ 1,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.Right, vts.Bottom),
+ -1,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+ }
+
+ break;
+ case TabSide.Right:
+ if (Frame.Bottom > tab.Frame.Bottom)
+ {
+ // LRCorner
+ lc.AddLine (
+ new (vts.X - 1, vts.Bottom),
+ 1,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.X - 1, vts.Bottom),
+ 1,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+ }
+
+ break;
+ default:
+ throw new ArgumentOutOfRangeException ();
+ }
+
+ if (_host.Style.ShowInitialLine)
+ {
+ switch (_host.Style.TabsSide)
+ {
+ case TabSide.Top:
+ // Upper left tee
+ lc.AddLine (
+ new (vts.X - 1, vts.Y - 1),
+ 1,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.X - 1, vts.Y - 1),
+ 0,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+
+ break;
+ case TabSide.Bottom:
+ // Lower left tee
+ lc.AddLine (
+ new (vts.X - 1, vts.Bottom),
+ -1,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.X - 1, vts.Bottom),
+ 0,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+
+ break;
+ case TabSide.Left:
+ // Upper left tee
+ lc.AddLine (
+ new (vts.X - 1, vts.Y - 1),
+ 0,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.X - 1, vts.Y - 1),
+ 1,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+
+ break;
+ case TabSide.Right:
+ // Upper left tee
+ lc.AddLine (
+ new (vts.Right, vts.Y - 1),
+ 0,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.Right, vts.Y - 1),
+ -1,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+
+ break;
+ default:
+ throw new ArgumentOutOfRangeException ();
}
}
}
if (i < tabLocations.Length - 1)
{
- if (_host.Style.ShowTopLine)
+ if (_host.Style.ShowInitialLine)
{
- if (_host.Style.TabsOnBottom)
+ switch (_host.Style.TabsSide)
{
- // Lower right tee
+ case TabSide.Top:
+ // Upper right tee
+ lc.AddLine (
+ new (vts.Right, vts.Y - 1),
+ 1,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.Right, vts.Y - 1),
+ 0,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+
+ break;
+ case TabSide.Bottom:
+ // Lower right tee
+ lc.AddLine (
+ new (vts.Right, vts.Bottom),
+ -1,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.Right, vts.Bottom),
+ 0,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+
+ break;
+ case TabSide.Left:
+ // Upper right tee
+ lc.AddLine (
+ new (vts.X - 1, vts.Bottom),
+ 0,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.X - 1, vts.Bottom),
+ 1,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+
+ break;
+ case TabSide.Right:
+ // Upper right tee
+ lc.AddLine (
+ new (vts.Right, vts.Bottom),
+ 0,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.Right, vts.Bottom),
+ -1,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+
+ break;
+ default:
+ throw new ArgumentOutOfRangeException ();
+ }
+ }
+ }
+
+ switch (_host.Style.TabsSide)
+ {
+ case TabSide.Top:
+ //LRCorner
+ lc.AddLine (
+ new (vts.Right, vts.Bottom),
+ -1,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.Right, vts.Bottom),
+ 1,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+
+ break;
+ case TabSide.Bottom:
+ //URCorner
+ lc.AddLine (
+ new (vts.Right, vts.Y - 1),
+ 1,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.Right, vts.Y - 1),
+ 1,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+
+ break;
+ case TabSide.Left:
+ if (Frame.Bottom > tab.Frame.Bottom)
+ {
+ //LRCorner
lc.AddLine (
- new Point (vts.Right, vts.Bottom),
- -1,
+ new (vts.Right, vts.Bottom),
+ 1,
Orientation.Vertical,
tab.BorderStyle
);
lc.AddLine (
- new Point (vts.Right, vts.Bottom),
- 0,
+ new (vts.Right, vts.Bottom),
+ -1,
Orientation.Horizontal,
tab.BorderStyle
);
}
- else
+
+ break;
+ case TabSide.Right:
+ if (Frame.Bottom > tab.Frame.Bottom)
{
- // Upper right tee
+ //LRCorner
lc.AddLine (
- new Point (vts.Right, vts.Y - 1),
+ new (vts.X - 1, vts.Bottom),
1,
Orientation.Vertical,
tab.BorderStyle
);
lc.AddLine (
- new Point (vts.Right, vts.Y - 1),
- 0,
+ new (vts.X - 1, vts.Bottom),
+ 1,
Orientation.Horizontal,
tab.BorderStyle
);
}
- }
- }
- if (_host.Style.TabsOnBottom)
- {
- //URCorner
- lc.AddLine (
- new Point (vts.Right, vts.Y - 1),
- 1,
- Orientation.Vertical,
- tab.BorderStyle
- );
-
- lc.AddLine (
- new Point (vts.Right, vts.Y - 1),
- 1,
- Orientation.Horizontal,
- tab.BorderStyle
- );
- }
- else
- {
- //LLCorner
- lc.AddLine (
- new Point (vts.Right, vts.Bottom - selectedOffset),
- -1,
- Orientation.Vertical,
- tab.BorderStyle
- );
-
- lc.AddLine (
- new Point (vts.Right, vts.Bottom - selectedOffset),
- 1,
- Orientation.Horizontal,
- tab.BorderStyle
- );
+ break;
+ default:
+ throw new ArgumentOutOfRangeException ();
}
}
else if (selectedTab == -1)
{
if (i == 0 && string.IsNullOrEmpty (tab.Text))
{
- if (_host.Style.TabsOnBottom)
+ switch (_host.Style.TabsSide)
{
- if (_host.Style.ShowTopLine)
- {
+ case TabSide.Top:
+ if (_host.Style.ShowInitialLine)
+ {
+ // ULCorner
+ lc.AddLine (
+ new (vts.X - 1, vts.Y - 1),
+ 1,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.X - 1, vts.Y - 1),
+ 1,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+ }
+
// LLCorner
lc.AddLine (
- new Point (vts.X - 1, vts.Bottom),
+ new (vts.X - 1, vts.Bottom),
-1,
Orientation.Vertical,
tab.BorderStyle
);
lc.AddLine (
- new Point (vts.X - 1, vts.Bottom),
+ new (vts.X - 1, vts.Bottom),
1,
Orientation.Horizontal,
tab.BorderStyle
);
- }
- // ULCorner
- lc.AddLine (
- new Point (vts.X - 1, vts.Y - 1),
- 1,
- Orientation.Vertical,
- tab.BorderStyle
- );
+ break;
+ case TabSide.Bottom:
+ if (_host.Style.ShowInitialLine)
+ {
+ // LLCorner
+ lc.AddLine (
+ new (vts.X - 1, vts.Bottom),
+ -1,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.X - 1, vts.Bottom),
+ 1,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+ }
- lc.AddLine (
- new Point (vts.X - 1, vts.Y - 1),
- 1,
- Orientation.Horizontal,
- tab.BorderStyle
- );
- }
- else
- {
- if (_host.Style.ShowTopLine)
- {
// ULCorner
lc.AddLine (
- new Point (vts.X - 1, vts.Y - 1),
+ new (vts.X - 1, vts.Y - 1),
1,
Orientation.Vertical,
tab.BorderStyle
);
lc.AddLine (
- new Point (vts.X - 1, vts.Y - 1),
+ new (vts.X - 1, vts.Y - 1),
1,
Orientation.Horizontal,
tab.BorderStyle
);
- }
- // LLCorner
- lc.AddLine (
- new Point (vts.X - 1, vts.Bottom),
- -1,
- Orientation.Vertical,
- tab.BorderStyle
- );
+ break;
+ case TabSide.Left:
+ if (_host.Style.ShowInitialLine)
+ {
+ // ULCorner
+ lc.AddLine (
+ new (vts.X - 1, vts.Y - 1),
+ 1,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.X - 1, vts.Y - 1),
+ 1,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+ }
- lc.AddLine (
- new Point (vts.X - 1, vts.Bottom),
- 1,
- Orientation.Horizontal,
- tab.BorderStyle
- );
+ // LLCorner
+ lc.AddLine (
+ new (vts.X - 1, vts.Bottom),
+ -1,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.X - 1, vts.Bottom),
+ 1,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+
+ break;
+ case TabSide.Right:
+ break;
+ default:
+ throw new ArgumentOutOfRangeException ();
}
}
else if (i > 0)
{
- if (_host.Style.ShowTopLine || _host.Style.TabsOnBottom)
+ switch (_host.Style.TabsSide)
{
- // Upper left tee
- lc.AddLine (
- new Point (vts.X - 1, vts.Y - 1),
- 1,
- Orientation.Vertical,
- tab.BorderStyle
- );
-
- lc.AddLine (
- new Point (vts.X - 1, vts.Y - 1),
- 0,
- Orientation.Horizontal,
- tab.BorderStyle
- );
- }
+ case TabSide.Top:
+ case TabSide.Bottom:
+ if (_host.Style.ShowInitialLine || _host.Style.TabsSide == TabSide.Bottom)
+ {
+ // Upper left tee
+ lc.AddLine (
+ new (vts.X - 1, vts.Y - 1),
+ 1,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.X - 1, vts.Y - 1),
+ 0,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+ }
- // Lower left tee
- lc.AddLine (
- new Point (vts.X - 1, vts.Bottom),
- -1,
- Orientation.Vertical,
- tab.BorderStyle
- );
-
- lc.AddLine (
- new Point (vts.X - 1, vts.Bottom),
- 0,
- Orientation.Horizontal,
- tab.BorderStyle
- );
- }
- }
- else if (i < tabLocations.Length - 1)
- {
- if (_host.Style.ShowTopLine)
- {
- // Upper right tee
- lc.AddLine (
- new Point (vts.Right, vts.Y - 1),
- 1,
- Orientation.Vertical,
- tab.BorderStyle
- );
-
- lc.AddLine (
- new Point (vts.Right, vts.Y - 1),
- 0,
- Orientation.Horizontal,
- tab.BorderStyle
- );
- }
+ // Lower left tee
+ lc.AddLine (
+ new (vts.X - 1, vts.Bottom),
+ -1,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
- if (_host.Style.ShowTopLine || !_host.Style.TabsOnBottom)
- {
- // Lower right tee
- lc.AddLine (
- new Point (vts.Right, vts.Bottom),
- -1,
- Orientation.Vertical,
- tab.BorderStyle
- );
-
- lc.AddLine (
- new Point (vts.Right, vts.Bottom),
- 0,
- Orientation.Horizontal,
- tab.BorderStyle
- );
- }
- else
- {
- // Upper right tee
- lc.AddLine (
- new Point (vts.Right, vts.Y - 1),
- 1,
- Orientation.Vertical,
- tab.BorderStyle
- );
-
- lc.AddLine (
- new Point (vts.Right, vts.Y - 1),
- 0,
- Orientation.Horizontal,
- tab.BorderStyle
- );
- }
- }
+ lc.AddLine (
+ new (vts.X - 1, vts.Bottom),
+ 0,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
- if (i == 0 && i != selectedTab && _host is { TabScrollOffset: 0, Style.ShowBorder: true })
- {
- if (_host.Style.TabsOnBottom)
- {
- // Upper left vertical line
- lc.AddLine (
- new Point (vts.X - 1, vts.Y - 1),
- 0,
- Orientation.Vertical,
- tab.BorderStyle
- );
-
- lc.AddLine (
- new Point (vts.X - 1, vts.Y - 1),
- 1,
- Orientation.Horizontal,
- tab.BorderStyle
- );
- }
- else
- {
- // Lower left vertical line
- lc.AddLine (
- new Point (vts.X - 1, vts.Bottom),
- 0,
- Orientation.Vertical,
- tab.BorderStyle
- );
-
- lc.AddLine (
- new Point (vts.X - 1, vts.Bottom),
- 1,
- Orientation.Horizontal,
- tab.BorderStyle
- );
- }
- }
+ break;
+ case TabSide.Left:
+ if (_host.Style.ShowInitialLine || _host.Style.TabsSide == TabSide.Right)
+ {
+ // Upper left tee
+ lc.AddLine (
+ new (vts.X - 1, vts.Y - 1),
+ 0,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.X - 1, vts.Y - 1),
+ 1,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+ }
- if (i == tabLocations.Length - 1 && i != selectedTab)
- {
- if (_host.Style.TabsOnBottom)
- {
- // Upper right tee
- lc.AddLine (
- new Point (vts.Right, vts.Y - 1),
- 1,
- Orientation.Vertical,
- tab.BorderStyle
- );
-
- lc.AddLine (
- new Point (vts.Right, vts.Y - 1),
- 0,
- Orientation.Horizontal,
- tab.BorderStyle
- );
- }
- else
- {
- // Lower right tee
- lc.AddLine (
- new Point (vts.Right, vts.Bottom),
- -1,
- Orientation.Vertical,
- tab.BorderStyle
- );
-
- lc.AddLine (
- new Point (vts.Right, vts.Bottom),
- 0,
- Orientation.Horizontal,
- tab.BorderStyle
- );
- }
- }
+ // Lower left tee
+ lc.AddLine (
+ new (vts.Right, vts.Y - 1),
+ 0,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
- if (i == tabLocations.Length - 1)
- {
- var arrowOffset = 1;
+ lc.AddLine (
+ new (vts.Right, vts.Y - 1),
+ -1,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
- int lastSelectedTab = !_host.Style.ShowTopLine && i == selectedTab ? 1 :
- _host.Style.TabsOnBottom ? 1 : 0;
- Rectangle tabsBarVts = ViewportToScreen (Viewport);
- int lineLength = tabsBarVts.Right - vts.Right;
+ break;
+ case TabSide.Right:
+ if (_host.Style.ShowInitialLine || _host.Style.TabsSide == TabSide.Right)
+ {
+ // Upper left tee
+ lc.AddLine (
+ new (vts.Right, vts.Y - 1),
+ 0,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.Right, vts.Y - 1),
+ -1,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+ }
- // Right horizontal line
- if (ShouldDrawRightScrollIndicator ())
- {
- if (lineLength - arrowOffset > 0)
- {
- if (_host.Style.TabsOnBottom)
- {
+ // Lower left tee
lc.AddLine (
- new Point (vts.Right, vts.Y - lastSelectedTab),
- lineLength - arrowOffset,
- Orientation.Horizontal,
+ new (vts.X - 1, vts.Y - 1),
+ 0,
+ Orientation.Vertical,
tab.BorderStyle
);
- }
- else
- {
+
lc.AddLine (
- new Point (
- vts.Right,
- vts.Bottom - lastSelectedTab
- ),
- lineLength - arrowOffset,
+ new (vts.X - 1, vts.Y - 1),
+ 1,
Orientation.Horizontal,
tab.BorderStyle
);
- }
+
+ break;
+ default:
+ throw new ArgumentOutOfRangeException ();
}
}
- else
+ }
+ else if (i < tabLocations.Length - 1)
+ {
+ if (_host.Style.ShowInitialLine)
{
- // Right corner
- if (_host.Style.TabsOnBottom)
+ switch (_host.Style.TabsSide)
{
- lc.AddLine (
- new Point (vts.Right, vts.Y - lastSelectedTab),
- lineLength,
- Orientation.Horizontal,
- tab.BorderStyle
- );
+ case TabSide.Top:
+ case TabSide.Bottom:
+ // Upper right tee
+ lc.AddLine (
+ new (vts.Right, vts.Y - 1),
+ 1,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.Right, vts.Y - 1),
+ 0,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+
+ break;
+ case TabSide.Left:
+ // Upper right tee
+ lc.AddLine (
+ new (vts.X - 1, vts.Bottom),
+ 0,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.X - 1, vts.Bottom),
+ 1,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+
+ break;
+ case TabSide.Right:
+ // Upper right tee
+ lc.AddLine (
+ new (vts.X - 1, vts.Bottom),
+ 0,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.X - 1, vts.Bottom),
+ 1,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+
+ break;
+ default:
+ throw new ArgumentOutOfRangeException ();
}
- else
+ }
+
+ if (_host.Style.ShowInitialLine)
+ {
+ switch (_host.Style.TabsSide)
{
- lc.AddLine (
- new Point (vts.Right, vts.Bottom - lastSelectedTab),
- lineLength,
- Orientation.Horizontal,
- tab.BorderStyle
- );
- }
+ case TabSide.Top:
+ case TabSide.Bottom:
+ // Lower right tee
+ lc.AddLine (
+ new (vts.Right, vts.Bottom),
+ -1,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
- if (_host.Style.ShowBorder)
+ lc.AddLine (
+ new (vts.Right, vts.Bottom),
+ 0,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+
+ break;
+ case TabSide.Left:
+ // Lower right tee
+ lc.AddLine (
+ new (vts.Right, vts.Bottom),
+ 0,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.Right, vts.Bottom),
+ -1,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+
+ break;
+ case TabSide.Right:
+ // Lower right tee
+ lc.AddLine (
+ new (vts.Right, vts.Bottom),
+ 0,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.Right, vts.Bottom),
+ -1,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+
+ break;
+ default:
+ throw new ArgumentOutOfRangeException ();
+ }
+ }
+ else
+ {
+ switch (_host.Style.TabsSide)
{
- if (_host.Style.TabsOnBottom)
- {
- // More LRCorner
+ case TabSide.Top:
+ // Lower right tee
lc.AddLine (
- new Point (
- tabsBarVts.Right - 1,
- vts.Y - lastSelectedTab
- ),
+ new (vts.Right, vts.Bottom),
-1,
Orientation.Vertical,
tab.BorderStyle
);
- }
- else
- {
- // More URCorner
+
lc.AddLine (
- new Point (
- tabsBarVts.Right - 1,
- vts.Bottom - lastSelectedTab
- ),
+ new (vts.Right, vts.Bottom),
+ 0,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+
+ break;
+ case TabSide.Bottom:
+ // Upper right tee
+ lc.AddLine (
+ new (vts.Right, vts.Y - 1),
1,
Orientation.Vertical,
tab.BorderStyle
);
- }
+
+ lc.AddLine (
+ new (vts.Right, vts.Y - 1),
+ 0,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+
+ break;
+ case TabSide.Left:
+ // Lower right tee
+ lc.AddLine (
+ new (vts.Right, vts.Bottom),
+ 0,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.Right, vts.Bottom),
+ -1,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+
+ break;
+ case TabSide.Right:
+ // Lower right tee
+ lc.AddLine (
+ new (vts.X - 1, vts.Bottom),
+ 0,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.X - 1, vts.Bottom),
+ 1,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+
+ break;
+ default:
+ throw new ArgumentOutOfRangeException ();
}
}
}
- }
- _host.LineCanvas.Merge (lc);
- }
+ if (i == 0 && i != selectedTab && _host is { TabScrollOffset: 0, Style.ShowBorder: true })
+ {
+ switch (_host.Style.TabsSide)
+ {
+ case TabSide.Top:
+ // Lower left vertical line
+ lc.AddLine (
+ new (vts.X - 1, vts.Bottom),
+ 0,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
- private int GetUnderlineYPosition ()
- {
- if (_host.Style.TabsOnBottom)
- {
- return 0;
- }
+ lc.AddLine (
+ new (vts.X - 1, vts.Bottom),
+ 1,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
- return _host.Style.ShowTopLine ? 2 : 1;
- }
+ break;
+ case TabSide.Bottom:
+ // Upper left vertical line
+ lc.AddLine (
+ new (vts.X - 1, vts.Y - 1),
+ 0,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
- /// Renders the line with the tab names in it.
- private void RenderTabLine ()
- {
- if (_host._tabLocations is null)
- {
- return;
- }
+ lc.AddLine (
+ new (vts.X - 1, vts.Y - 1),
+ 1,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
- View? selected = null;
- int topLine = _host.Style.ShowTopLine ? 1 : 0;
+ break;
+ case TabSide.Left:
+ // Upper horizontal line
+ lc.AddLine (
+ new (vts.Right, vts.Y - 1),
+ 1,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
- foreach (Tab toRender in _host._tabLocations)
- {
- Tab tab = toRender;
+ lc.AddLine (
+ new (vts.Right, vts.Y - 1),
+ 0,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
- if (toRender == _host.SelectedTab)
- {
- selected = tab;
+ break;
+ case TabSide.Right:
+ // Upper horizontal line
+ lc.AddLine (
+ new (vts.X - 1, vts.Y - 1),
+ 1,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
- if (_host.Style.TabsOnBottom)
- {
- tab.Border!.Thickness = new (1, 0, 1, topLine);
- tab.Margin!.Thickness = new (0, 1, 0, 0);
- }
- else
- {
- tab.Border!.Thickness = new (1, topLine, 1, 0);
- tab.Margin!.Thickness = new (0, 0, 0, topLine);
+ lc.AddLine (
+ new (vts.X - 1, vts.Y - 1),
+ 0,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+
+ break;
+ default:
+ throw new ArgumentOutOfRangeException ();
}
}
- else if (selected is null)
+
+ if (i == tabLocations.Length - 1 && i != selectedTab)
{
- if (_host.Style.TabsOnBottom)
+ switch (_host.Style.TabsSide)
{
- tab.Border!.Thickness = new (1, 1, 1, topLine);
- tab.Margin!.Thickness = new (0, 0, 0, 0);
- }
- else
- {
- tab.Border!.Thickness = new (1, topLine, 1, 1);
- tab.Margin!.Thickness = new (0, 0, 0, 0);
+ case TabSide.Top:
+ // Lower right tee
+ lc.AddLine (
+ new (vts.Right, vts.Bottom),
+ -1,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.Right, vts.Bottom),
+ 0,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+
+ break;
+ case TabSide.Bottom:
+ // Upper right tee
+ lc.AddLine (
+ new (vts.Right, vts.Y - 1),
+ 1,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.Right, vts.Y - 1),
+ 0,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+
+ break;
+ case TabSide.Left:
+ if (Frame.Bottom > tab.Frame.Bottom)
+ {
+ // Lower right tee
+ lc.AddLine (
+ new (vts.Right, vts.Bottom),
+ 0,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.Right, vts.Bottom),
+ -1,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+ }
+
+ break;
+ case TabSide.Right:
+ if (Frame.Bottom > tab.Frame.Bottom)
+ {
+ // Lower right tee
+ lc.AddLine (
+ new (vts.X - 1, vts.Bottom),
+ 0,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.X - 1, vts.Bottom),
+ 1,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+ }
+
+ break;
+ default:
+ throw new ArgumentOutOfRangeException ();
}
}
- else
+
+ if (i == tabLocations.Length - 1)
{
- if (_host.Style.TabsOnBottom)
+ var arrowOffset = 1;
+
+ Rectangle tabsBarVts = ViewportToScreen (Viewport);
+ int lineLength;
+
+ switch (_host.Style.TabsSide)
{
- tab.Border!.Thickness = new (1, 1, 1, topLine);
- tab.Margin!.Thickness = new (0, 0, 0, 0);
+ case TabSide.Top:
+ case TabSide.Bottom:
+ lineLength = tabsBarVts.Right - vts.Right;
+
+ break;
+ case TabSide.Left:
+ case TabSide.Right:
+ lineLength = tabsBarVts.Bottom - vts.Bottom;
+
+ break;
+ default:
+ throw new ArgumentOutOfRangeException ();
+ }
+
+ // Right horizontal/vertical line
+ if (ShouldDrawRightDownScrollIndicator ())
+ {
+ if (lineLength - arrowOffset > 0)
+ {
+ switch (_host.Style.TabsSide)
+ {
+ case TabSide.Top:
+ lc.AddLine (
+ new (
+ vts.Right,
+ vts.Bottom
+ ),
+ lineLength - arrowOffset,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+
+ break;
+ case TabSide.Bottom:
+ lc.AddLine (
+
+ new (vts.Right, vts.Y - 1),
+ lineLength - arrowOffset,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+
+ break;
+ case TabSide.Left:
+ lc.AddLine (
+ new (
+ vts.Right,
+ vts.Bottom
+ ),
+ lineLength - arrowOffset,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ break;
+ case TabSide.Right:
+ lc.AddLine (
+ new (
+ vts.X - 1,
+ vts.Bottom
+ ),
+ lineLength - arrowOffset,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ break;
+ default:
+ throw new ArgumentOutOfRangeException ();
+ }
+ }
}
else
{
- tab.Border!.Thickness = new (1, topLine, 1, 1);
- tab.Margin!.Thickness = new (0, 0, 0, 0);
+ // Right corner
+ switch (_host.Style.TabsSide)
+ {
+ case TabSide.Top:
+ lc.AddLine (
+ new (vts.Right, vts.Bottom),
+ lineLength,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+
+ break;
+ case TabSide.Bottom:
+ lc.AddLine (
+
+ new (vts.Right, vts.Y - 1),
+ lineLength,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+
+ break;
+ case TabSide.Left:
+ if (i == selectedTab)
+ {
+ if (Frame.Bottom == tab.Frame.Bottom)
+ {
+ // Lower right horizontal line
+ lc.AddLine (
+ new (vts.Right, vts.Bottom),
+ 0,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+ }
+ else
+ {
+ lc.AddLine (
+ new (vts.Right, vts.Bottom),
+ lineLength,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+ }
+ }
+ else
+ {
+ if (Frame.Bottom == tab.Frame.Bottom)
+ {
+ lc.AddLine (
+ new (vts.Right, vts.Bottom),
+ -1,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.Right, vts.Bottom),
+ 0,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+
+ }
+ else
+ {
+ lc.AddLine (
+ new (vts.Right, vts.Bottom),
+ lineLength,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.Right, tabsBarVts.Bottom),
+ 1,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+ }
+ }
+
+ break;
+ case TabSide.Right:
+ if (i == selectedTab)
+ {
+ if (Frame.Bottom == tab.Frame.Bottom)
+ {
+ // Lower right horizontal line
+ lc.AddLine (
+ new (vts.X - 1, vts.Bottom),
+ 0,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+ }
+ else
+ {
+ lc.AddLine (
+ new (vts.X - 1, vts.Bottom),
+ lineLength,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+ }
+ }
+ else
+ {
+ if (Frame.Bottom == tab.Frame.Bottom)
+ {
+ lc.AddLine (
+ new (vts.X - 1, vts.Bottom),
+ -1,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.X - 1, vts.Bottom),
+ 0,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+
+ }
+ else
+ {
+ lc.AddLine (
+ new (vts.X - 1, vts.Bottom),
+ lineLength,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ lc.AddLine (
+ new (vts.X - 1, tabsBarVts.Bottom),
+ 1,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+ }
+ }
+
+ break;
+ default:
+ throw new ArgumentOutOfRangeException ();
+ }
+
+ if (_host.Style.ShowBorder)
+ {
+ switch (_host.Style.TabsSide)
+ {
+ case TabSide.Top:
+ // More URCorner
+ lc.AddLine (
+ new (
+ tabsBarVts.Right - 1,
+ vts.Bottom
+ ),
+ 1,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ break;
+ case TabSide.Bottom:
+ // More LRCorner
+ lc.AddLine (
+ new (
+ tabsBarVts.Right - 1,
+ vts.Y - 1
+ ),
+ -1,
+ Orientation.Vertical,
+ tab.BorderStyle
+ );
+
+ break;
+ case TabSide.Left:
+ if (Frame.Bottom > tab.Frame.Bottom)
+ {
+ // More URCorner
+ lc.AddLine (
+ new (
+ vts.Right,
+ tabsBarVts.Bottom - 1
+ ),
+ 1,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+ }
+
+ break;
+ case TabSide.Right:
+ if (Frame.Bottom > tab.Frame.Bottom)
+ {
+ // More URCorner
+ lc.AddLine (
+ new (
+ vts.X - 1,
+ tabsBarVts.Bottom - 1
+ ),
+ -1,
+ Orientation.Horizontal,
+ tab.BorderStyle
+ );
+ }
+
+ break;
+ default:
+ throw new ArgumentOutOfRangeException ();
+ }
+ }
}
}
-
- // Ensures updating TextFormatter constrains
- tab.TextFormatter.ConstrainToWidth = tab.GetContentSize ().Width;
- tab.TextFormatter.ConstrainToHeight = tab.GetContentSize ().Height;
}
+
+ LineCanvas.Merge (lc);
}
/// Renders the line of the tab that adjoins the content of the tab.
private void RenderUnderline ()
{
- int y = GetUnderlineYPosition ();
-
Tab? selected = _host._tabLocations?.FirstOrDefault (t => t == _host.SelectedTab);
if (selected is null)
@@ -753,42 +1444,99 @@ private void RenderUnderline ()
return;
}
- // draw scroll indicators
+ // Set the correct glyphs for scroll indicators
+ switch (_host.Style.TabsSide)
+ {
+ case TabSide.Top:
+ case TabSide.Bottom:
+ _rightDownScrollIndicator.Text = Glyphs.RightArrow.ToString ();
+ _leftUpScrollIndicator.Text = Glyphs.LeftArrow.ToString ();
+
+ break;
+ case TabSide.Left:
+ case TabSide.Right:
+ _rightDownScrollIndicator.Text = Glyphs.DownArrow.ToString ();
+ _leftUpScrollIndicator.Text = Glyphs.UpArrow.ToString ();
+
+ break;
+ default:
+ throw new ArgumentOutOfRangeException ();
+ }
+
+ // position scroll indicators
// if there are more tabs to the left not visible
if (_host.TabScrollOffset > 0)
{
- _leftScrollIndicator.X = 0;
- _leftScrollIndicator.Y = y;
+ switch (_host.Style.TabsSide)
+ {
+ case TabSide.Top:
+ _leftUpScrollIndicator.X = 0;
+ _leftUpScrollIndicator.Y = Pos.AnchorEnd (1);
+
+ break;
+ case TabSide.Bottom:
+ case TabSide.Right:
+ _leftUpScrollIndicator.X = 0;
+ _leftUpScrollIndicator.Y = 0;
+
+ break;
+ case TabSide.Left:
+ _leftUpScrollIndicator.X = Pos.AnchorEnd (1);
+ _leftUpScrollIndicator.Y = 0;
+
+ break;
+ default:
+ throw new ArgumentOutOfRangeException ();
+ }
// indicate that
- _leftScrollIndicator.Visible = true;
+ _leftUpScrollIndicator.Visible = true;
// Ensures this is clicked instead of the first tab
- MoveSubviewToEnd (_leftScrollIndicator);
+ MoveSubviewToEnd (_leftUpScrollIndicator);
}
else
{
- _leftScrollIndicator.Visible = false;
+ _leftUpScrollIndicator.Visible = false;
}
// if there are more tabs to the right not visible
- if (ShouldDrawRightScrollIndicator ())
+ if (ShouldDrawRightDownScrollIndicator ())
{
- _rightScrollIndicator.X = Viewport.Width - 1;
- _rightScrollIndicator.Y = y;
+ switch (_host.Style.TabsSide)
+ {
+ case TabSide.Top:
+ case TabSide.Left:
+ _rightDownScrollIndicator.X = Pos.AnchorEnd (1);
+ _rightDownScrollIndicator.Y = Pos.AnchorEnd (1);
+
+ break;
+ case TabSide.Bottom:
+ _rightDownScrollIndicator.X = Pos.AnchorEnd (1);
+ _rightDownScrollIndicator.Y = 0;
+
+ break;
+ case TabSide.Right:
+ _rightDownScrollIndicator.X = 0;
+ _rightDownScrollIndicator.Y = Pos.AnchorEnd (1);
+
+ break;
+ default:
+ throw new ArgumentOutOfRangeException ();
+ }
// indicate that
- _rightScrollIndicator.Visible = true;
+ _rightDownScrollIndicator.Visible = true;
// Ensures this is clicked instead of the last tab if under this
- MoveSubviewToStart (_rightScrollIndicator);
+ MoveSubviewToEnd (_rightDownScrollIndicator);
}
else
{
- _rightScrollIndicator.Visible = false;
+ _rightDownScrollIndicator.Visible = false;
}
}
- private bool ShouldDrawRightScrollIndicator () { return _host._tabLocations!.LastOrDefault () != _host.Tabs.LastOrDefault (); }
+ private bool ShouldDrawRightDownScrollIndicator () { return _host._tabLocations!.LastOrDefault () != _host.Tabs.LastOrDefault (); }
}
diff --git a/Terminal.Gui/Views/TabView/TabSide.cs b/Terminal.Gui/Views/TabView/TabSide.cs
new file mode 100644
index 0000000000..eef3a51c39
--- /dev/null
+++ b/Terminal.Gui/Views/TabView/TabSide.cs
@@ -0,0 +1,27 @@
+๏ปฟnamespace Terminal.Gui;
+
+///
+/// Defines tab side.
+///
+public enum TabSide
+{
+ ///
+ /// Top side.
+ ///
+ Top,
+
+ ///
+ /// Bottom side.
+ ///
+ Bottom,
+
+ ///
+ /// Left side.
+ ///
+ Left,
+
+ ///
+ /// Right side.
+ ///
+ Right
+}
diff --git a/Terminal.Gui/Views/TabView/TabStyle.cs b/Terminal.Gui/Views/TabView/TabStyle.cs
index 85404d05d9..74107d2c1e 100644
--- a/Terminal.Gui/Views/TabView/TabStyle.cs
+++ b/Terminal.Gui/Views/TabView/TabStyle.cs
@@ -1,4 +1,5 @@
-๏ปฟnamespace Terminal.Gui;
+๏ปฟ#nullable enable
+namespace Terminal.Gui;
/// Describes render stylistic selections of a
public class TabStyle
@@ -7,12 +8,21 @@ public class TabStyle
public bool ShowBorder { get; set; } = true;
///
- /// True to show the top lip of tabs. False to directly begin with tab text during rendering. When true header
- /// line occupies 3 rows, when false only 2. Defaults to true.
- /// When is enabled this instead applies to the bottommost line of the control
+ /// True to show the top lip of tabs. False to directly begin with tab text during rendering. Defaults to true.
+ /// When true and or , header
+ /// line occupies 3 rows, when false only 2.
+ /// When is enabled this instead applies to the bottommost line of the control
+ /// When true and or , header
+ /// line occupies 1 more column, when false 1 column less.
+ /// When is enabled this instead applies to the rightmost column of the control
///
- public bool ShowTopLine { get; set; } = true;
+ public bool ShowInitialLine { get; set; } = true;
- /// True to render tabs at the bottom of the view instead of the top
- public bool TabsOnBottom { get; set; } = false;
+ /// Gets or sets the tabs side to render.
+ public TabSide TabsSide { get; set; }
+
+ ///
+ /// Gets or sets the tabs text alignments.
+ ///
+ public Alignment TabsTextAlignment { get; set; }
}
diff --git a/Terminal.Gui/Views/TabView/TabView.cs b/Terminal.Gui/Views/TabView/TabView.cs
index 73f286b564..6a910a16f1 100644
--- a/Terminal.Gui/Views/TabView/TabView.cs
+++ b/Terminal.Gui/Views/TabView/TabView.cs
@@ -27,8 +27,8 @@ public class TabView : View
public TabView ()
{
CanFocus = true;
- TabStop = TabBehavior.TabStop; // Because TabView has focusable subviews, it must be a TabGroup
- _tabsBar = new TabRow (this);
+ TabStop = TabBehavior.TabStop;
+ _tabsBar = new (this);
_containerView = new ();
ApplyStyleChanges ();
@@ -36,9 +36,53 @@ public TabView ()
base.Add (_containerView);
// Things this view knows how to do
- AddCommand (Command.Left, () => SwitchTabBy (-1));
+ AddCommand (
+ Command.Left,
+ () =>
+ {
+ if (Style.TabsSide is TabSide.Top or TabSide.Bottom)
+ {
+ return SwitchTabBy (-1);
+ }
+
+ return false;
+ });
+
+ AddCommand (
+ Command.Right,
+ () =>
+ {
+ if (Style.TabsSide is TabSide.Top or TabSide.Bottom)
+ {
+ return SwitchTabBy (1);
+ }
+
+ return false;
+ });
+
+ AddCommand (
+ Command.Up,
+ () =>
+ {
+ if (Style.TabsSide is TabSide.Left or TabSide.Right)
+ {
+ return SwitchTabBy (-1);
+ }
- AddCommand (Command.Right, () => SwitchTabBy (1));
+ return false;
+ });
+
+ AddCommand (
+ Command.Down,
+ () =>
+ {
+ if (Style.TabsSide is TabSide.Left or TabSide.Right)
+ {
+ return SwitchTabBy (1);
+ }
+
+ return false;
+ });
AddCommand (
Command.LeftStart,
@@ -87,6 +131,8 @@ public TabView ()
// Default keybindings for this view
KeyBindings.Add (Key.CursorLeft, Command.Left);
KeyBindings.Add (Key.CursorRight, Command.Right);
+ KeyBindings.Add (Key.CursorUp, Command.Up);
+ KeyBindings.Add (Key.CursorDown, Command.Down);
KeyBindings.Add (Key.Home, Command.LeftStart);
KeyBindings.Add (Key.End, Command.RightEnd);
KeyBindings.Add (Key.PageDown, Command.PageDown);
@@ -122,6 +168,7 @@ public Tab? SelectedTab
if (_selectedTab.View is { })
{
_selectedTab.View.CanFocusChanged -= ContainerViewCanFocus!;
+
// remove old content
_containerView.Remove (_selectedTab.View);
}
@@ -149,19 +196,14 @@ public Tab? SelectedTab
OnSelectedTabChanged (old!, _selectedTab!);
}
+
SetNeedsLayout ();
}
}
- private bool TabCanSetFocus ()
- {
- return IsInitialized && SelectedTab is { } && (_selectedTabHasFocus || !_containerView.CanFocus);
- }
+ private bool TabCanSetFocus () { return IsInitialized && SelectedTab is { } && (_selectedTabHasFocus || !_containerView.CanFocus); }
- private void ContainerViewCanFocus (object sender, EventArgs eventArgs)
- {
- _containerView.CanFocus = _containerView.Subviews.Count (v => v.CanFocus) > 0;
- }
+ private void ContainerViewCanFocus (object sender, EventArgs eventArgs) { _containerView.CanFocus = _containerView.Subviews.Count (v => v.CanFocus) > 0; }
private TabStyle _style = new ();
@@ -176,6 +218,7 @@ public TabStyle Style
{
return;
}
+
_style = value;
SetNeedsLayout ();
}
@@ -229,60 +272,102 @@ public void AddTab (Tab tab, bool andSelect)
///
public void ApplyStyleChanges ()
{
+ _tabLocations = CalculateViewport (Viewport);
+
_containerView.BorderStyle = Style.ShowBorder ? LineStyle.Single : LineStyle.None;
- _containerView.Width = Dim.Fill ();
- if (Style.TabsOnBottom)
+ switch (Style.TabsSide)
{
- // Tabs are along the bottom so just dodge the border
- if (Style.ShowBorder)
- {
- _containerView.Border!.Thickness = new Thickness (1, 1, 1, 0);
- }
+ case TabSide.Top:
+ // Tabs are along the top
+ if (Style.ShowBorder)
+ {
+ _containerView.Border!.Thickness = new (1, 0, 1, 1);
+ }
- _containerView.Y = 0;
+ _tabsBar.X = 0;
+ _tabsBar.Y = 0;
+ _tabsBar.Width = Dim.Fill ();
+ _tabsBar.Height = GetTabHeight (true);
- int tabHeight = GetTabHeight (false);
+ _containerView.X = 0;
- // Fill client area leaving space at bottom for tabs
- _containerView.Height = Dim.Fill (tabHeight);
+ //move content down to make space for tabs
+ _containerView.Y = Pos.Bottom (_tabsBar);
+ _containerView.Width = Dim.Fill ();
+ _containerView.Height = Dim.Fill ();
- _tabsBar.Height = tabHeight;
+ break;
+ case TabSide.Bottom:
+ // Tabs are along the bottom so just dodge the border
+ if (Style.ShowBorder)
+ {
+ _containerView.Border!.Thickness = new (1, 1, 1, 0);
+ }
- _tabsBar.Y = Pos.Bottom (_containerView);
- }
- else
- {
- // Tabs are along the top
- if (Style.ShowBorder)
- {
- _containerView.Border!.Thickness = new Thickness (1, 0, 1, 1);
- }
+ _tabsBar.X = 0;
+ _tabsBar.Width = Dim.Fill ();
+ int tabHeight = GetTabHeight (false);
+ _tabsBar.Height = tabHeight;
- _tabsBar.Y = 0;
+ _containerView.X = 0;
+ _containerView.Y = 0;
+ _containerView.Width = Dim.Fill ();
- int tabHeight = GetTabHeight (true);
+ // Fill client area leaving space at bottom for tabs
+ _containerView.Height = Dim.Fill (tabHeight);
- //move content down to make space for tabs
- _containerView.Y = Pos.Bottom (_tabsBar);
+ _tabsBar.Y = Pos.Bottom (_containerView);
- // Fill client area leaving space at bottom for border
- _containerView.Height = Dim.Fill ();
+ break;
+ case TabSide.Left:
+ // Tabs are along the left
+ if (Style.ShowBorder)
+ {
+ _containerView.Border!.Thickness = new (0, 1, 1, 1);
+ }
- // The top tab should be 2 or 3 rows high and on the top
+ _tabsBar.X = 0;
+ _tabsBar.Y = 0;
+ _tabsBar.Height = Dim.Fill ();
- _tabsBar.Height = tabHeight;
+ //move content right to make space for tabs
+ _containerView.X = Pos.Right (_tabsBar);
+ _containerView.Y = 0;
- // Should be able to just use 0 but switching between top/bottom tabs repeatedly breaks in ValidatePosDim if just using the absolute value 0
+ // Fill client area leaving space at left for tabs
+ _containerView.Width = Dim.Fill ();
+ _containerView.Height = Dim.Fill ();
+
+ break;
+ case TabSide.Right:
+ // Tabs are along the right
+ if (Style.ShowBorder)
+ {
+ _containerView.Border!.Thickness = new (1, 1, 0, 1);
+ }
+
+ _tabsBar.Y = 0;
+ _tabsBar.Height = Dim.Fill ();
+
+ //move content left to make space for tabs
+ _containerView.X = 0;
+ _containerView.Y = 0;
+
+ _containerView.Height = Dim.Fill ();
+
+ break;
+ default:
+ throw new ArgumentOutOfRangeException ();
}
SetNeedsLayout ();
}
- ///
+ ///
protected override void OnViewportChanged (DrawEventArgs e)
{
- _tabLocations = CalculateViewport (Viewport).ToArray ();
+ _tabLocations = CalculateViewport (Viewport);
base.OnViewportChanged (e);
}
@@ -296,10 +381,15 @@ public void EnsureSelectedTabIsVisible ()
}
// if current viewport does not include the selected tab
- if (!CalculateViewport (Viewport).Any (t => Equals (SelectedTab, t)))
+ if (_tabLocations is null || (_tabLocations is { } && !_tabLocations.Any (t => Equals (SelectedTab, t))))
{
// Set scroll offset so the first tab rendered is the
TabScrollOffset = Math.Max (0, Tabs.IndexOf (SelectedTab));
+ _tabLocations = CalculateViewport (Viewport);
+ }
+ else
+ {
+ RenderTabLine (_tabLocations);
}
}
@@ -309,7 +399,7 @@ public void EnsureSelectedTabIsVisible ()
/// The valid for the given value.
public int EnsureValidScrollOffsets (int value) { return Math.Max (Math.Min (value, Tabs.Count - 1), 0); }
- ///
+ ///
protected override void OnHasFocusChanged (bool newHasFocus, View? previousFocusedView, View? focusedView)
{
if (SelectedTab is { HasFocus: false } && !_containerView.CanFocus && focusedView == this)
@@ -388,6 +478,7 @@ public bool SwitchTabBy (int amount)
if (currentIdx == -1)
{
SelectedTab = Tabs.ElementAt (0);
+
return true;
}
@@ -430,88 +521,207 @@ protected override void Dispose (bool disposing)
}
/// Raises the event.
- protected virtual void OnSelectedTabChanged (Tab oldTab, Tab newTab)
- {
- SelectedTabChanged?.Invoke (this, new TabChangedEventArgs (oldTab, newTab));
- }
+ protected virtual void OnSelectedTabChanged (Tab oldTab, Tab newTab) { SelectedTabChanged?.Invoke (this, new (oldTab, newTab)); }
/// Returns which tabs to render at each x location.
///
- internal IEnumerable CalculateViewport (Rectangle bounds)
+ internal Tab []? CalculateViewport (Rectangle bounds)
{
UnSetCurrentTabs ();
+ List tabs = [];
var i = 1;
View? prevTab = null;
- // Starting at the first or scrolled to tab
- foreach (Tab tab in Tabs.Skip (TabScrollOffset))
+ switch (Style.TabsSide)
{
- if (prevTab is { })
- {
- tab.X = Pos.Right (prevTab) - 1;
- }
- else
- {
- tab.X = 0;
- }
+ case TabSide.Top:
+ case TabSide.Bottom:
+ // Starting at the first or scrolled to tab
+ foreach (Tab tab in Tabs.Skip (TabScrollOffset))
+ {
+ if (prevTab is { })
+ {
+ tab.X = Pos.Right (prevTab) - 1;
+ }
+ else
+ {
+ tab.X = 0;
+ }
- tab.Y = 0;
+ tab.Y = 0;
- // while there is space for the tab
- int tabTextWidth = tab.DisplayText.EnumerateRunes ().Sum (c => c.GetColumns ());
+ // while there is space for the tab
+ int tabTextWidth = tab.DisplayText.EnumerateRunes ().Sum (c => c.GetColumns ());
- // The maximum number of characters to use for the tab name as specified
- // by the user (MaxTabTextWidth). But not more than the width of the view
- // or we won't even be able to render a single tab!
- long maxWidth = Math.Max (0, Math.Min (bounds.Width - 3, MaxTabTextWidth));
+ // The maximum number of characters to use for the tab name as specified
+ // by the user (MaxTabTextWidth). But not more than the width of the view
+ // or we won't even be able to render a single tab!
+ long maxWidth = Math.Max (0, Math.Min (bounds.Width - 3, MaxTabTextWidth));
- tab.Width = 2;
- tab.Height = Style.ShowTopLine ? 3 : 2;
+ tab.Width = 2;
+ tab.Height = Style.ShowInitialLine ? 3 : 2;
- // if tab view is width <= 3 don't render any tabs
- if (maxWidth == 0)
- {
- tab.Visible = true;
- tab.MouseClick += Tab_MouseClick!;
- tab.Border!.MouseClick += Tab_MouseClick!;
+ // if tab view is width <= 3 don't render any tabs
+ if (maxWidth == 0)
+ {
+ tab.Visible = true;
+ tab.MouseClick += Tab_MouseClick!;
+ tab.Border!.MouseClick += Tab_MouseClick!;
+ tab.DisplayTextChanged += Tab_DisplayTextChanged;
- yield return tab;
+ tabs.Add (tab);
- break;
- }
+ break;
+ }
- if (tabTextWidth > maxWidth)
- {
- tab.Text = tab.DisplayText.Substring (0, (int)maxWidth);
- tabTextWidth = (int)maxWidth;
- }
- else
- {
- tab.Text = tab.DisplayText;
- }
+ if (tabTextWidth > maxWidth)
+ {
+ tab.Text = tab.DisplayText.Substring (0, (int)maxWidth);
+ tabTextWidth = (int)maxWidth;
+ }
+ else
+ {
+ tab.Text = tab.DisplayText;
+ }
- tab.Width = Math.Max (tabTextWidth + 2, 1);
- tab.Height = Style.ShowTopLine ? 3 : 2;
+ tab.Width = tabTextWidth + 2;
+ tab.Height = Style.ShowInitialLine ? 3 : 2;
- // if there is not enough space for this tab
- if (i + tabTextWidth >= bounds.Width)
- {
- tab.Visible = false;
+ // if there is not enough space for this tab
+ if (i + tabTextWidth >= bounds.Width)
+ {
+ tab.Visible = false;
+
+ break;
+ }
+
+ // there is enough space!
+ tab.Visible = true;
+ tab.MouseClick += Tab_MouseClick!;
+ tab.Border!.MouseClick += Tab_MouseClick!;
+ tab.DisplayTextChanged += Tab_DisplayTextChanged;
+
+ tabs.Add (tab);
+
+ prevTab = tab;
+
+ i += tabTextWidth + 1;
+ }
break;
- }
+ case TabSide.Left:
+ case TabSide.Right:
+ var maxColWidth = 0;
+
+ // Starting at the first or scrolled to tab
+ foreach (Tab tab in Tabs.Skip (TabScrollOffset))
+ {
+ tab.X = 0;
+
+ if (prevTab is { })
+ {
+ tab.Y = Pos.Bottom (prevTab) - 1;
+ }
+ else
+ {
+ tab.Y = 0;
+ }
+
+ // while there is space for the tab
+ int tabTextWidth = tab.DisplayText.EnumerateRunes ().Sum (c => c.GetColumns ());
+
+ // The maximum number of characters to use for the tab name as specified
+ // by the user (MaxTabTextWidth). But not more than the width of the view
+ // or we won't even be able to render a single tab!
+ long maxWidth = Math.Max (0, Math.Min (bounds.Width - (Style.ShowInitialLine ? 2 : 1), MaxTabTextWidth));
+
+ maxColWidth = GetMaxColWidth (Math.Min (tabTextWidth, (int)maxWidth));
+
+ // The maximum height to use for the tab. But not more than the height of the view
+ // or we won't even be able to render a single tab!
+ int maxHeight = Math.Max (0, Math.Min (bounds.Height - 2, 2));
+
+ tab.Height = 2;
+ tab.TextAlignment = Style.TabsTextAlignment;
+
+ // if tab view is height <= 3 don't render any tabs
+ if (maxHeight == 0)
+ {
+ tab.Width = maxColWidth;
+ tab.Visible = true;
+ tab.MouseClick += Tab_MouseClick!;
+ tab.Border!.MouseClick += Tab_MouseClick!;
+ tab.DisplayTextChanged += Tab_DisplayTextChanged;
+
+ tabs.Add (tab);
+
+ break;
+ }
+
+ if (tabTextWidth > maxWidth)
+ {
+ tab.Text = tab.DisplayText.Substring (0, (int)maxWidth);
+ tabTextWidth = (int)maxWidth;
+ }
+ else
+ {
+ tab.Text = tab.DisplayText;
+ }
+
+ maxColWidth = GetMaxColWidth (tabTextWidth);
+ tab.Height = 3;
+
+ // if there is not enough space for this tab
+ if (i + 1 >= bounds.Height)
+ {
+ tab.Visible = false;
+
+ break;
+ }
+
+ // there is enough space!
+ tab.Visible = true;
+ tab.MouseClick += Tab_MouseClick!;
+ tab.Border!.MouseClick += Tab_MouseClick!;
+ tab.DisplayTextChanged += Tab_DisplayTextChanged;
+
+ tabs.Add (tab);
+
+ prevTab = tab;
+
+ i += 2;
+ }
+
+ foreach (Tab t in tabs)
+ {
+ t.Width = maxColWidth;
+ }
+
+ _tabsBar.Width = maxColWidth;
+
+ if (Style.TabsSide == TabSide.Right)
+ {
+ _tabsBar.X = Pos.AnchorEnd (maxColWidth);
+ // Fill client area leaving space at right for tabs
+ _containerView.Width = Dim.Fill (maxColWidth);
+ }
- // there is enough space!
- tab.Visible = true;
- tab.MouseClick += Tab_MouseClick!;
- tab.Border!.MouseClick += Tab_MouseClick!;
+ int GetMaxColWidth (int textWidth)
+ {
+ int maxViewportWidth = Math.Max (0, Viewport.Width - (Style.ShowBorder ? 2 : 0));
- yield return tab;
+ if (Math.Max (textWidth + (Style.ShowInitialLine ? 2 : 1), maxColWidth) > maxViewportWidth)
+ {
+ return maxViewportWidth;
+ }
- prevTab = tab;
+ return Math.Max (textWidth + (Style.ShowInitialLine ? 2 : 1), maxColWidth);
+ }
- i += tabTextWidth + 1;
+ break;
+ default:
+ throw new ArgumentOutOfRangeException ();
}
if (TabCanSetFocus ())
@@ -522,41 +732,121 @@ internal IEnumerable CalculateViewport (Rectangle bounds)
{
SelectedTab?.View?.SetFocus ();
}
+
+ RenderTabLine (tabs.Count == 0 ? null : tabs.ToArray ());
+
+ SetNeedsLayout ();
+
+ return tabs.Count == 0 ? null : tabs.ToArray ();
+ }
+
+ private void Tab_DisplayTextChanged (object? sender, EventArgs e) { _tabLocations = CalculateViewport (Viewport); }
+
+ /// Renders the line with the tab names in it.
+ private void RenderTabLine (Tab []? tabLocations)
+ {
+ if (tabLocations is null)
+ {
+ return;
+ }
+
+ int topLine = Style.ShowInitialLine ? 1 : 0;
+
+ foreach (Tab toRender in tabLocations)
+ {
+ Tab tab = toRender;
+
+ if (toRender == SelectedTab)
+ {
+ switch (Style.TabsSide)
+ {
+ case TabSide.Top:
+ tab.Border!.Thickness = new (1, topLine, 1, 0);
+ tab.Margin!.Thickness = new (0, 0, 0, 1);
+
+ break;
+ case TabSide.Bottom:
+ tab.Border!.Thickness = new (1, 0, 1, topLine);
+ tab.Margin!.Thickness = new (0, 1, 0, 0);
+
+ break;
+ case TabSide.Left:
+ tab.Border!.Thickness = new (topLine, 1, 0, 1);
+ tab.Margin!.Thickness = new (0, 0, 1, 0);
+
+ break;
+ case TabSide.Right:
+ tab.Border!.Thickness = new (0, 1, topLine, 1);
+ tab.Margin!.Thickness = new (1, 0, 0, 0);
+
+ break;
+ default:
+ throw new ArgumentOutOfRangeException ();
+ }
+ }
+ else
+ {
+ tab.Margin!.Thickness = new (0, 0, 0, 0);
+
+ switch (Style.TabsSide)
+ {
+ case TabSide.Top:
+ tab.Border!.Thickness = new (1, topLine, 1, 1);
+
+ break;
+ case TabSide.Bottom:
+ tab.Border!.Thickness = new (1, 1, 1, topLine);
+
+ break;
+ case TabSide.Left:
+ tab.Border!.Thickness = new (topLine, 1, 1, 1);
+
+ break;
+ case TabSide.Right:
+ tab.Border!.Thickness = new (1, 1, topLine, 1);
+
+ break;
+ default:
+ throw new ArgumentOutOfRangeException ();
+ }
+ }
+
+ // Ensures updating TextFormatter constrains
+ tab.TextFormatter.ConstrainToWidth = tab.GetContentSize ().Width;
+ tab.TextFormatter.ConstrainToHeight = tab.GetContentSize ().Height;
+ }
}
///
- /// Returns the number of rows occupied by rendering the tabs, this depends on
- /// and can be 0 (e.g. if and you ask for ).
+ /// Returns the number of rows occupied by rendering the tabs, this depends on
+ /// and can be 0 (e.g. if and you ask for ).
///
/// True to measure the space required at the top of the control, false to measure space at the bottom.
/// .
///
private int GetTabHeight (bool top)
{
- if (top && Style.TabsOnBottom)
+ if (top && Style.TabsSide == TabSide.Bottom)
{
return 0;
}
- if (!top && !Style.TabsOnBottom)
+ if (!top && Style.TabsSide == TabSide.Top)
{
return 0;
}
- return Style.ShowTopLine ? 3 : 2;
+ return Style.ShowInitialLine ? 3 : 2;
}
- internal void Tab_MouseClick (object sender, MouseEventArgs e)
- {
- e.Handled = _tabsBar.NewMouseEvent (e) == true;
- }
+ internal void Tab_MouseClick (object sender, MouseEventArgs e) { e.Handled = _tabsBar.NewMouseEvent (e) == true; }
private void UnSetCurrentTabs ()
{
if (_tabLocations is null)
{
// Ensures unset any visible tab prior to TabScrollOffset
- for (int i = 0; i < TabScrollOffset; i++)
+ for (var i = 0; i < TabScrollOffset; i++)
{
Tab tab = Tabs.ElementAt (i);
@@ -564,6 +854,7 @@ private void UnSetCurrentTabs ()
{
tab.MouseClick -= Tab_MouseClick!;
tab.Border!.MouseClick -= Tab_MouseClick!;
+ tab.DisplayTextChanged -= Tab_DisplayTextChanged;
tab.Visible = false;
}
}
@@ -574,6 +865,7 @@ private void UnSetCurrentTabs ()
{
tabToRender.MouseClick -= Tab_MouseClick!;
tabToRender.Border!.MouseClick -= Tab_MouseClick!;
+ tabToRender.DisplayTextChanged -= Tab_DisplayTextChanged;
tabToRender.Visible = false;
}
@@ -584,6 +876,4 @@ private void UnSetCurrentTabs ()
/// Raises the event.
///
internal virtual void OnTabClicked (TabMouseEventArgs tabMouseEventArgs) { TabClicked?.Invoke (this, tabMouseEventArgs); }
-
-
-}
\ No newline at end of file
+}
diff --git a/UICatalog/Scenarios/TabViewExample.cs b/UICatalog/Scenarios/TabViewExample.cs
index 9d48c05685..6a6f574d99 100644
--- a/UICatalog/Scenarios/TabViewExample.cs
+++ b/UICatalog/Scenarios/TabViewExample.cs
@@ -1,4 +1,6 @@
-๏ปฟusing System.Linq;
+๏ปฟusing System;
+using System.Collections.Generic;
+using System.Linq;
using System.Text;
using Terminal.Gui;
@@ -12,7 +14,10 @@ public class TabViewExample : Scenario
private MenuItem _miShowBorder;
private MenuItem _miShowTabViewBorder;
private MenuItem _miShowTopLine;
- private MenuItem _miTabsOnBottom;
+ private MenuItem [] _miTabsSide;
+ private MenuItem _cachedTabsSide;
+ private MenuItem [] _miTabsTextAlignment;
+ private MenuItem _cachedTabsTextAlignment;
private TabView _tabView;
public override void Main ()
@@ -23,6 +28,9 @@ public override void Main ()
// Setup - Create a top-level application window and configure it.
Toplevel appWindow = new ();
+ _miTabsSide = SetTabsSide ();
+ _miTabsTextAlignment = SetTabsTextAlignment ();
+
var menu = new MenuBar
{
Menus =
@@ -54,17 +62,23 @@ public override void Main ()
{
Checked = true, CheckType = MenuItemCheckStyle.Checked
},
- _miTabsOnBottom =
- new ("_Tabs On Bottom", "", SetTabsOnBottom)
- {
- Checked = false, CheckType = MenuItemCheckStyle.Checked
- },
+ null,
+ _miTabsSide [0],
+ _miTabsSide [1],
+ _miTabsSide [2],
+ _miTabsSide [3],
+ null,
_miShowTabViewBorder =
new (
"_Show TabView Border",
"",
ShowTabViewBorder
- ) { Checked = true, CheckType = MenuItemCheckStyle.Checked }
+ ) { Checked = true, CheckType = MenuItemCheckStyle.Checked },
+ null,
+ _miTabsTextAlignment [0],
+ _miTabsTextAlignment [1],
+ _miTabsTextAlignment [2],
+ _miTabsTextAlignment [3]
}
)
]
@@ -241,12 +255,78 @@ private View GetInteractiveTab ()
private void Quit () { Application.RequestStop (); }
- private void SetTabsOnBottom ()
+ private MenuItem [] SetTabsSide ()
{
- _miTabsOnBottom.Checked = !_miTabsOnBottom.Checked;
+ List