Преглед изворни кода

Merge branch 'v2_3761_2886-Draw-and-Layout-Perf-tabview' of github.com:BDisp/Terminal.Gui into v2_3761_2886-Draw-and-Layout-Perf

Tig пре 9 месеци
родитељ
комит
c1597b3ded

+ 7 - 7
Terminal.Gui/View/View.Navigation.cs

@@ -850,18 +850,18 @@ public partial class View // Focus and cross-view navigation management (TabStop
         SetNeedsDisplay ();
     }
 
-    private void RaiseFocusChanged (bool newHasFocus, View? previousFocusedView, View? focusedVew)
+    private void RaiseFocusChanged (bool newHasFocus, View? previousFocusedView, View? focusedView)
     {
-        if (newHasFocus && focusedVew?.Focused is null)
+        if (newHasFocus && focusedView?.Focused is null)
         {
-            Application.Navigation?.SetFocused (focusedVew);
+            Application.Navigation?.SetFocused (focusedView);
         }
 
         // Call the virtual method
-        OnHasFocusChanged (newHasFocus, previousFocusedView, focusedVew);
+        OnHasFocusChanged (newHasFocus, previousFocusedView, focusedView);
 
         // Raise the event
-        var args = new HasFocusEventArgs (newHasFocus, newHasFocus, previousFocusedView, focusedVew);
+        var args = new HasFocusEventArgs (newHasFocus, newHasFocus, previousFocusedView, focusedView);
         HasFocusChanged?.Invoke (this, args);
     }
 
@@ -876,8 +876,8 @@ public partial class View // Focus and cross-view navigation management (TabStop
     /// </remarks>
     /// <param name="newHasFocus">The new value of <see cref="View.HasFocus"/>.</param>
     /// <param name="previousFocusedView"></param>
-    /// <param name="focusedVew">The view that is now focused. May be <see langword="null"/></param>
-    protected virtual void OnHasFocusChanged (bool newHasFocus, View? previousFocusedView, View? focusedVew) { }
+    /// <param name="focusedView">The view that is now focused. May be <see langword="null"/></param>
+    protected virtual void OnHasFocusChanged (bool newHasFocus, View? previousFocusedView, View? focusedView) { }
 
     /// <summary>Raised after <see cref="HasFocus"/> has changed.</summary>
     /// <remarks>

+ 1 - 1
Terminal.Gui/Views/ComboBox.cs

@@ -962,7 +962,7 @@ public class ComboBox : View, IDesignable
             return true;
         }
 
-        protected override void OnHasFocusChanged (bool newHasFocus, [CanBeNull] View previousFocusedView, [CanBeNull] View focusedVew)
+        protected override void OnHasFocusChanged (bool newHasFocus, [CanBeNull] View previousFocusedView, [CanBeNull] View focusedView)
         {
             if (newHasFocus)
             {

+ 4 - 3
Terminal.Gui/Views/Tab.cs

@@ -1,9 +1,10 @@
-namespace Terminal.Gui;
+#nullable enable
+namespace Terminal.Gui;
 
 /// <summary>A single tab in a <see cref="TabView"/>.</summary>
 public class Tab : View
 {
-    private string _displayText;
+    private string? _displayText;
 
     /// <summary>Creates a new unnamed tab with no controls inside.</summary>
     public Tab ()
@@ -27,5 +28,5 @@ public class Tab : View
 
     /// <summary>The control to display when the tab is selected.</summary>
     /// <value></value>
-    public View View { get; set; }
+    public View? View { get; set; }
 }

+ 68 - 56
Terminal.Gui/Views/TabView.cs

@@ -1,5 +1,4 @@
-using System.Diagnostics;
-
+#nullable enable
 namespace Terminal.Gui;
 
 /// <summary>Control that hosts multiple sub views, presenting a single one at once.</summary>
@@ -19,8 +18,8 @@ public class TabView : View
     /// <summary>This sub view is the 2 or 3 line control that represents the actual tabs themselves.</summary>
     private readonly TabRowView _tabsBar;
 
-    private Tab _selectedTab;
-    private TabToRender [] _tabLocations;
+    private Tab? _selectedTab;
+    private TabToRender []? _tabLocations;
     private int _tabScrollOffset;
 
     /// <summary>Initializes a <see cref="TabView"/> class.</summary>
@@ -48,7 +47,7 @@ public class TabView : View
                     () =>
                     {
                         TabScrollOffset = 0;
-                        SelectedTab = Tabs.FirstOrDefault ();
+                        SelectedTab = Tabs.FirstOrDefault ()!;
 
                         return true;
                     }
@@ -59,7 +58,7 @@ public class TabView : View
                     () =>
                     {
                         TabScrollOffset = Tabs.Count - 1;
-                        SelectedTab = Tabs.LastOrDefault ();
+                        SelectedTab = Tabs.LastOrDefault()!;
 
                         return true;
                     }
@@ -69,7 +68,7 @@ public class TabView : View
                     Command.PageDown,
                     () =>
                     {
-                        TabScrollOffset += _tabLocations.Length;
+                        TabScrollOffset += _tabLocations!.Length;
                         SelectedTab = Tabs.ElementAt (TabScrollOffset);
 
                         return true;
@@ -80,7 +79,7 @@ public class TabView : View
                     Command.PageUp,
                     () =>
                     {
-                        TabScrollOffset -= _tabLocations.Length;
+                        TabScrollOffset -= _tabLocations!.Length;
                         SelectedTab = Tabs.ElementAt (TabScrollOffset);
 
                         return true;
@@ -104,19 +103,20 @@ public class TabView : View
 
     /// <summary>The currently selected member of <see cref="Tabs"/> chosen by the user.</summary>
     /// <value></value>
-    public Tab SelectedTab
+    public Tab? SelectedTab
     {
         get => _selectedTab;
         set
         {
             UnSetCurrentTabs ();
 
-            Tab old = _selectedTab;
+            Tab? old = _selectedTab;
 
             if (_selectedTab is { })
             {
                 if (_selectedTab.View is { })
                 {
+                    _selectedTab.View.CanFocusChanged -= ContentViewCanFocus!;
                     // remove old content
                     _contentView.Remove (_selectedTab.View);
                 }
@@ -124,33 +124,36 @@ public class TabView : View
 
             _selectedTab = value;
 
-            if (value is { })
+            // add new content
+            if (_selectedTab?.View != null)
             {
-                // add new content
-                if (_selectedTab.View is { })
-                {
-                    _contentView.Add (_selectedTab.View);
-                    // _contentView.Id = $"_contentView for {_selectedTab.DisplayText}";
-                }
+                _selectedTab.View.CanFocusChanged += ContentViewCanFocus!;
+                _contentView.Add (_selectedTab.View);
+                // _contentView.Id = $"_contentView for {_selectedTab.DisplayText}";
             }
 
-            _contentView.CanFocus = _contentView.Subviews.Count (v => v.CanFocus) > 0;
+            ContentViewCanFocus (null!, null!);
 
             EnsureSelectedTabIsVisible ();
 
-            if (old != value)
+            if (old != _selectedTab)
             {
                 if (old?.HasFocus == true)
                 {
                     SelectedTab?.SetFocus ();
                 }
 
-                OnSelectedTabChanged (old, value);
+                OnSelectedTabChanged (old!, _selectedTab!);
             }
             SetNeedsLayout ();
         }
     }
 
+    private void ContentViewCanFocus (object sender, EventArgs eventArgs)
+    {
+        _contentView.CanFocus = _contentView.Subviews.Count (v => v.CanFocus) > 0;
+    }
+
     private TabStyle _style = new ();
 
     /// <summary>Render choices for how to display tabs.  After making changes, call <see cref="ApplyStyleChanges()"/>.</summary>
@@ -289,6 +292,19 @@ public class TabView : View
     /// <returns>The valid <see cref="TabScrollOffset"/> for the given value.</returns>
     public int EnsureValidScrollOffsets (int value) { return Math.Max (Math.Min (value, Tabs.Count - 1), 0); }
 
+    /// <inheritdoc />
+    protected override void OnHasFocusChanged (bool newHasFocus, View? previousFocusedView, View? focusedView)
+    {
+        if (SelectedTab is { } && !_contentView.CanFocus && focusedView == this)
+        {
+            SelectedTab?.SetFocus ();
+
+            return;
+        }
+
+        base.OnHasFocusChanged (newHasFocus, previousFocusedView, focusedView);
+    }
+
     /// <inheritdoc/>
     protected override bool OnDrawingContent (Rectangle viewport)
     {
@@ -313,7 +329,7 @@ public class TabView : View
     ///     tab's hosted <see cref="Tab.View"/> if appropriate.
     /// </summary>
     /// <param name="tab"></param>
-    public void RemoveTab (Tab tab)
+    public void RemoveTab (Tab? tab)
     {
         if (tab is null || !_tabs.Contains (tab))
         {
@@ -346,7 +362,7 @@ public class TabView : View
     }
 
     /// <summary>Event for when <see cref="SelectedTab"/> changes.</summary>
-    public event EventHandler<TabChangedEventArgs> SelectedTabChanged;
+    public event EventHandler<TabChangedEventArgs>? SelectedTabChanged;
 
     /// <summary>
     ///     Changes the <see cref="SelectedTab"/> by the given <paramref name="amount"/>. Positive for right, negative for
@@ -395,7 +411,7 @@ public class TabView : View
     ///     Event fired when a <see cref="Tab"/> is clicked.  Can be used to cancel navigation, show context menu (e.g. on
     ///     right click) etc.
     /// </summary>
-    public event EventHandler<TabMouseEventArgs> TabClicked;
+    public event EventHandler<TabMouseEventArgs>? TabClicked;
 
     /// <summary>Disposes the control and all <see cref="Tabs"/>.</summary>
     /// <param name="disposing"></param>
@@ -428,7 +444,7 @@ public class TabView : View
         UnSetCurrentTabs ();
 
         var i = 1;
-        View prevTab = null;
+        View? prevTab = null;
 
         // Starting at the first or scrolled to tab
         foreach (Tab tab in Tabs.Skip (TabScrollOffset))
@@ -463,9 +479,9 @@ public class TabView : View
             if (maxWidth == 0)
             {
                 tab.Visible = true;
-                tab.MouseClick += Tab_MouseClick;
+                tab.MouseClick += Tab_MouseClick!;
 
-                yield return new TabToRender (i, tab, string.Empty, Equals (SelectedTab, tab), 0);
+                yield return new TabToRender (tab, string.Empty, Equals (SelectedTab, tab));
 
                 break;
             }
@@ -489,9 +505,9 @@ public class TabView : View
 
             // there is enough space!
             tab.Visible = true;
-            tab.MouseClick += Tab_MouseClick;
+            tab.MouseClick += Tab_MouseClick!;
 
-            yield return new TabToRender (i, tab, text, Equals (SelectedTab, tab), tabTextWidth);
+            yield return new TabToRender (tab, text, Equals (SelectedTab, tab));
 
             i += tabTextWidth + 1;
         }
@@ -530,7 +546,7 @@ public class TabView : View
         {
             foreach (TabToRender tabToRender in _tabLocations)
             {
-                tabToRender.Tab.MouseClick -= Tab_MouseClick;
+                tabToRender.Tab.MouseClick -= Tab_MouseClick!;
                 tabToRender.Tab.Visible = false;
             }
 
@@ -565,7 +581,7 @@ public class TabView : View
                 Visible = false,
                 Text = Glyphs.RightArrow.ToString ()
             };
-            _rightScrollIndicator.MouseClick += _host.Tab_MouseClick;
+            _rightScrollIndicator.MouseClick += _host.Tab_MouseClick!;
 
             _leftScrollIndicator = new View
             {
@@ -575,14 +591,14 @@ public class TabView : View
                 Visible = false,
                 Text = Glyphs.LeftArrow.ToString ()
             };
-            _leftScrollIndicator.MouseClick += _host.Tab_MouseClick;
+            _leftScrollIndicator.MouseClick += _host.Tab_MouseClick!;
 
             Add (_rightScrollIndicator, _leftScrollIndicator);
         }
 
         protected override bool OnMouseEvent (MouseEventArgs me)
         {
-            Tab hit = me.View is Tab ? (Tab)me.View : null;
+            Tab? hit = me.View as Tab;
 
             if (me.IsSingleClicked)
             {
@@ -652,14 +668,20 @@ public class TabView : View
         {
             _host._tabLocations = _host.CalculateViewport (Viewport).ToArray ();
 
-            RenderTabLine ();
 
-            RenderUnderline ();
             SetAttribute (HasFocus ? GetFocusColor () : GetNormalColor ());
 
             return true;
         }
 
+        /// <inheritdoc />
+        protected override bool OnDrawingSubviews (Rectangle viewport)
+        {
+            RenderTabLine ();
+
+            return true;
+        }
+
         protected override void OnDrawComplete ()
         {
             if (_host._tabLocations is null)
@@ -1190,10 +1212,10 @@ public class TabView : View
                 }
 
                 tab.LineCanvas.Merge (lc);
-                tab.DrawAdornments ();
-            }
+                tab.RenderLineCanvas ();
 
-            return;
+                RenderUnderline ();
+            }
         }
 
         private int GetUnderlineYPosition ()
@@ -1209,21 +1231,15 @@ public class TabView : View
         /// <summary>Renders the line with the tab names in it.</summary>
         private void RenderTabLine ()
         {
-            TabToRender [] tabLocations = _host._tabLocations;
-            int y;
+            TabToRender []? tabLocations = _host._tabLocations;
 
-            if (_host.Style.TabsOnBottom)
+            if (tabLocations is null)
             {
-                y = 1;
-            }
-            else
-            {
-                y = _host.Style.ShowTopLine ? 1 : 0;
+                return;
             }
 
-            View selected = null;
+            View? selected = null;
             int topLine = _host.Style.ShowTopLine ? 1 : 0;
-            int width = Viewport.Width;
 
             foreach (TabToRender toRender in tabLocations)
             {
@@ -1257,7 +1273,7 @@ public class TabView : View
                         tab.Margin.Thickness = new Thickness (0, 0, 0, 0);
                     }
 
-                    tab.Width = Math.Max (tab.Width.GetAnchor (0) - 1, 1);
+                    tab.Width = Math.Max (tab.Width!.GetAnchor (0) - 1, 1);
                 }
                 else
                 {
@@ -1272,7 +1288,7 @@ public class TabView : View
                         tab.Margin.Thickness = new Thickness (0, 0, 0, 0);
                     }
 
-                    tab.Width = Math.Max (tab.Width.GetAnchor (0) - 1, 1);
+                    tab.Width = Math.Max (tab.Width!.GetAnchor (0) - 1, 1);
                 }
 
                 tab.Text = toRender.TextToRender;
@@ -1317,7 +1333,7 @@ public class TabView : View
         {
             int y = GetUnderlineYPosition ();
 
-            TabToRender selected = _host._tabLocations.FirstOrDefault (t => t.IsSelected);
+            TabToRender? selected = _host._tabLocations?.FirstOrDefault (t => t.IsSelected);
 
             if (selected is null)
             {
@@ -1363,17 +1379,15 @@ public class TabView : View
             }
         }
 
-        private bool ShouldDrawRightScrollIndicator () { return _host._tabLocations.LastOrDefault ()?.Tab != _host.Tabs.LastOrDefault (); }
+        private bool ShouldDrawRightScrollIndicator () { return _host._tabLocations!.LastOrDefault ()?.Tab != _host.Tabs.LastOrDefault (); }
     }
 
     private class TabToRender
     {
-        public TabToRender (int x, Tab tab, string textToRender, bool isSelected, int width)
+        public TabToRender (Tab tab, string textToRender, bool isSelected)
         {
-            X = x;
             Tab = tab;
             IsSelected = isSelected;
-            Width = width;
             TextToRender = textToRender;
         }
 
@@ -1383,7 +1397,5 @@ public class TabView : View
 
         public Tab Tab { get; }
         public string TextToRender { get; }
-        public int Width { get; }
-        public int X { get; set; }
     }
 }

+ 1 - 1
UICatalog/Scenarios/ASCIICustomButton.cs

@@ -111,7 +111,7 @@ public class ASCIICustomButtonTest : Scenario
             Add (_border, _fill, title);
         }
 
-        protected override void OnHasFocusChanged (bool newHasFocus, [CanBeNull] View previousFocusedView, [CanBeNull] View focusedVew)
+        protected override void OnHasFocusChanged (bool newHasFocus, [CanBeNull] View previousFocusedView, [CanBeNull] View focusedView)
         {
             if (newHasFocus)
             {

+ 1 - 1
UnitTests/Views/ScrollViewTests.cs

@@ -1134,7 +1134,7 @@ public class ScrollViewTests (ITestOutputHelper output)
             CanFocus = true;
         }
 
-        protected override void OnHasFocusChanged (bool newHasFocus, [CanBeNull] View previousFocusedView, [CanBeNull] View focusedVew)
+        protected override void OnHasFocusChanged (bool newHasFocus, [CanBeNull] View previousFocusedView, [CanBeNull] View focusedView)
         {
             if (newHasFocus)
             {

+ 29 - 26
UnitTests/Views/TabViewTests.cs

@@ -103,7 +103,7 @@ public class TabViewTests (ITestOutputHelper output)
         Application.Shutdown ();
     }
 
-    [Fact (Skip = "#3789 Broke. The right way to fix is to refactor TabView to separate Layout and Draw")]
+    [Fact]
     [AutoInitShutdown]
     public void MouseClick_ChangesTab ()
     {
@@ -188,7 +188,7 @@ public class TabViewTests (ITestOutputHelper output)
         top.Dispose ();
     }
 
-    [Fact (Skip = "#3789 Broke. The right way to fix is to refactor TabView to separate Layout and Draw")]
+    [Fact]
     [AutoInitShutdown]
     public void MouseClick_Right_Left_Arrows_ChangesTab ()
     {
@@ -274,7 +274,7 @@ public class TabViewTests (ITestOutputHelper output)
         top.Dispose ();
     }
 
-    [Fact (Skip = "#3789 Broke. The right way to fix is to refactor TabView to separate Layout and Draw")]
+    [Fact]
     [AutoInitShutdown]
     public void MouseClick_Right_Left_Arrows_ChangesTab_With_Border ()
     {
@@ -369,7 +369,7 @@ public class TabViewTests (ITestOutputHelper output)
         top.Dispose ();
     }
 
-    [Fact (Skip="#3789 Broke. The right way to fix is to refactor TabView to separate Layout and Draw")]
+    [Fact]
     [AutoInitShutdown]
     public void ProcessKey_Down_Up_Right_Left_Home_End_PageDown_PageUp ()
     {
@@ -429,7 +429,7 @@ public class TabViewTests (ITestOutputHelper output)
         Assert.Equal (tab2, tv.SelectedTab);
         Assert.Equal (btn, top.MostFocused);
 
-        // Add a focusable subview to Selected Tab
+        // Add a focusable subview to Selected Tab View which is a Label with CanFocus as false
         var btnSubView = new View ()
         {
             Id = "btnSubView",
@@ -438,9 +438,17 @@ public class TabViewTests (ITestOutputHelper output)
         };
         tv.SelectedTab.View.Add (btnSubView);
 
+        Assert.False (tv.SelectedTab.View.CanFocus);
+
         // Press cursor up. Should focus the subview in the selected tab.
         Application.RaiseKeyDownEvent (Key.CursorUp);
         Assert.Equal (tab2, tv.SelectedTab);
+        Assert.NotEqual (btnSubView, top.MostFocused);
+        Assert.Equal (tab2, top.MostFocused);
+
+        tv.SelectedTab.View.CanFocus = true;
+        Application.RaiseKeyDownEvent (Key.CursorDown);
+        Assert.Equal (tab2, tv.SelectedTab);
         Assert.Equal (btnSubView, top.MostFocused);
 
         Application.RaiseKeyDownEvent (Key.CursorUp);
@@ -451,24 +459,18 @@ public class TabViewTests (ITestOutputHelper output)
         Application.RaiseKeyDownEvent (Key.CursorDown);
         Assert.Equal (btn, top.MostFocused);
 
-        // Press the cursor down key again will focus next view in the toplevel, whic is the TabView
+        // Press the cursor down key again will focus next view in the toplevel, which is the TabView
         Application.RaiseKeyDownEvent (Key.CursorDown);
         Assert.Equal (tab2, tv.SelectedTab);
         Assert.Equal (tv, top.Focused);
-        Assert.Equal (tab1, tv.MostFocused);
+        // Due to the RestoreFocus method prioritize the _previouslyFocused, so btnSubView will be focused again
+        Assert.Equal (btnSubView, tv.MostFocused);
 
-        // Press the cursor down key to focus the selected tab view hosting again
-        Application.RaiseKeyDownEvent (Key.CursorDown);
-        Assert.Equal (tab2, tv.SelectedTab);
-        Assert.Equal (btnSubView, top.MostFocused);
-
-        // Press the cursor up key to focus the selected tab
+        // Press the cursor up key to focus the selected tab which it's the only way to do that
         Application.RaiseKeyDownEvent (Key.CursorUp);
-        Application.Refresh ();
-
-        // Is the selected tab focused
         Assert.Equal (tab2, tv.SelectedTab);
         Assert.Equal (tv, top.Focused);
+        Assert.Equal (tab2, top.Focused.MostFocused);
         Assert.Equal (tv.MostFocused, top.Focused.MostFocused);
 
         // Press the cursor left key to select the previous tab
@@ -479,6 +481,7 @@ public class TabViewTests (ITestOutputHelper output)
         Assert.Equal (tab1, tv.SelectedTab);
         Assert.Equal (tv, top.Focused);
         Assert.Equal (tv.MostFocused, top.Focused.MostFocused);
+        Assert.Equal (tab1, top.Focused.MostFocused);
 
         // Press the end key to select the last tab
         Application.RaiseKeyDownEvent (Key.End);
@@ -595,7 +598,7 @@ public class TabViewTests (ITestOutputHelper output)
         Application.Shutdown ();
     }
 
-    [Fact (Skip = "#3789 Broke. The right way to fix is to refactor TabView to separate Layout and Draw")]
+    [Fact]
     [SetupFakeDriver]
     public void ShowTopLine_False_TabsOnBottom_False_TestTabView_Width3 ()
     {
@@ -643,7 +646,7 @@ public class TabViewTests (ITestOutputHelper output)
                                                      );
     }
 
-    [Fact (Skip = "#3789 Broke. The right way to fix is to refactor TabView to separate Layout and Draw")]
+    [Fact]
     [SetupFakeDriver]
     public void ShowTopLine_False_TabsOnBottom_False_TestThinTabView_WithLongNames ()
     {
@@ -735,7 +738,7 @@ public class TabViewTests (ITestOutputHelper output)
                                                      );
     }
 
-    [Fact (Skip = "#3789 Broke. The right way to fix is to refactor TabView to separate Layout and Draw")]
+    [Fact]
     [SetupFakeDriver]
     public void ShowTopLine_False_TabsOnBottom_True_TestTabView_Width3 ()
     {
@@ -783,7 +786,7 @@ public class TabViewTests (ITestOutputHelper output)
                                                      );
     }
 
-    [Fact (Skip = "#3789 Broke. The right way to fix is to refactor TabView to separate Layout and Draw")]
+    [Fact]
     [SetupFakeDriver]
     public void ShowTopLine_False_TabsOnBottom_True_TestThinTabView_WithLongNames ()
     {
@@ -875,7 +878,7 @@ public class TabViewTests (ITestOutputHelper output)
                                                      );
     }
 
-    [Fact (Skip = "#3789 Broke. The right way to fix is to refactor TabView to separate Layout and Draw")]
+    [Fact]
     [SetupFakeDriver]
     public void ShowTopLine_True_TabsOnBottom_False_TestTabView_Width3 ()
     {
@@ -919,7 +922,7 @@ public class TabViewTests (ITestOutputHelper output)
                                                      );
     }
 
-    [Fact (Skip = "#3789 Broke. The right way to fix is to refactor TabView to separate Layout and Draw")]
+    [Fact]
     [SetupFakeDriver]
     public void ShowTopLine_True_TabsOnBottom_False_TestThinTabView_WithLongNames ()
     {
@@ -1009,7 +1012,7 @@ public class TabViewTests (ITestOutputHelper output)
                                                      );
     }
 
-    [Fact (Skip = "#3789 Broke. The right way to fix is to refactor TabView to separate Layout and Draw")]
+    [Fact]
     [SetupFakeDriver]
     public void ShowTopLine_True_TabsOnBottom_False_With_Unicode ()
     {
@@ -1050,7 +1053,7 @@ public class TabViewTests (ITestOutputHelper output)
                                                      );
     }
 
-    [Fact (Skip = "#3789 Broke. The right way to fix is to refactor TabView to separate Layout and Draw")]
+    [Fact]
     [SetupFakeDriver]
     public void ShowTopLine_True_TabsOnBottom_True_TestTabView_Width3 ()
     {
@@ -1098,7 +1101,7 @@ public class TabViewTests (ITestOutputHelper output)
                                                      );
     }
 
-    [Fact (Skip = "#3789 Broke. The right way to fix is to refactor TabView to separate Layout and Draw")]
+    [Fact]
     [SetupFakeDriver]
     public void ShowTopLine_True_TabsOnBottom_True_TestThinTabView_WithLongNames ()
     {
@@ -1174,7 +1177,7 @@ public class TabViewTests (ITestOutputHelper output)
                                                      );
     }
 
-    [Fact (Skip = "#3789 Broke. The right way to fix is to refactor TabView to separate Layout and Draw")]
+    [Fact]
     [SetupFakeDriver]
     public void ShowTopLine_True_TabsOnBottom_True_With_Unicode ()
     {