From 9abfb1ae46c09298ac820be69edc6fd8d720f00f Mon Sep 17 00:00:00 2001 From: Tig Date: Sat, 8 Jun 2024 12:25:26 -0600 Subject: [PATCH] Dim.Auto (Content) is pretty horked. Broke Bar --- Terminal.Gui/View/Layout/DimAuto.cs | 144 ++++++++++++--------------- Terminal.Gui/View/Layout/PosAlign.cs | 1 + Terminal.Gui/Views/Bar.cs | 82 ++++++++++++--- Terminal.Gui/Views/Shortcut.cs | 13 ++- UICatalog/Scenarios/Bars.cs | 142 +++++++++++++------------- 5 files changed, 215 insertions(+), 167 deletions(-) diff --git a/Terminal.Gui/View/Layout/DimAuto.cs b/Terminal.Gui/View/Layout/DimAuto.cs index 6638eca37..738d687b3 100644 --- a/Terminal.Gui/View/Layout/DimAuto.cs +++ b/Terminal.Gui/View/Layout/DimAuto.cs @@ -22,6 +22,7 @@ public class DimAuto () : Dim /// /// Gets the maximum dimension the View's ContentSize will be fit to. NOT CURRENTLY SUPPORTED. /// + // ReSharper disable once ConvertToAutoProperty public required Dim? MaximumContentDim { @@ -34,6 +35,7 @@ public class DimAuto () : Dim /// /// Gets the minimum dimension the View's ContentSize will be constrained to. /// + // ReSharper disable once ConvertToAutoProperty public required Dim? MinimumContentDim { @@ -46,6 +48,7 @@ public class DimAuto () : Dim /// /// Gets the style of the DimAuto. /// + // ReSharper disable once ConvertToAutoProperty public required DimAutoStyle Style { @@ -62,7 +65,7 @@ public class DimAuto () : Dim var subviewsSize = 0; int autoMin = MinimumContentDim?.GetAnchor (superviewContentSize) ?? 0; - int autoMax = MaximumContentDim?.GetAnchor (superviewContentSize) ?? int.MaxValue; + int autoMax = MaximumContentDim?.GetAnchor (superviewContentSize) ?? superviewContentSize; if (Style.FastHasFlags (DimAutoStyle.Text)) { @@ -83,10 +86,11 @@ public class DimAuto () : Dim // TODO: This whole body of code is a WIP (for https://github.com/gui-cs/Terminal.Gui/pull/3451). subviewsSize = 0; - List includedSubviews = us.Subviews.ToList ();//.Where (v => !v.ExcludeFromLayout).ToList (); + List includedSubviews = us.Subviews.ToList (); //.Where (v => !v.ExcludeFromLayout).ToList (); List subviews; #region Not Anchored and Are Not Dependent + // Start with subviews that are not anchored to the end, aligned, or dependent on content size // [x] PosAnchorEnd // [x] PosAlign @@ -100,19 +104,25 @@ public class DimAuto () : Dim // [ ] DimView if (dimension == Dimension.Width) { - subviews = includedSubviews.Where (v => v.X is not PosAnchorEnd - && v.X is not PosAlign + subviews = includedSubviews.Where ( + v => v.X is not PosAnchorEnd + && v.X is not PosAlign + // && v.X is not PosCenter && v.Width is not DimAuto - && v.Width is not DimFill).ToList (); + && v.Width is not DimFill) + .ToList (); } else { - subviews = includedSubviews.Where (v => v.Y is not PosAnchorEnd - && v.Y is not PosAlign + subviews = includedSubviews.Where ( + v => v.Y is not PosAnchorEnd + && v.Y is not PosAlign + // && v.Y is not PosCenter && v.Height is not DimAuto - && v.Height is not DimFill).ToList (); + && v.Height is not DimFill) + .ToList (); } for (var i = 0; i < subviews.Count; i++) @@ -127,9 +137,11 @@ public class DimAuto () : Dim subviewsSize = size; } } + #endregion Not Anchored and Are Not Dependent #region Anchored + // Now, handle subviews that are anchored to the end // [x] PosAnchorEnd if (dimension == Dimension.Width) @@ -142,6 +154,7 @@ public class DimAuto () : Dim } int maxAnchorEnd = 0; + for (var i = 0; i < subviews.Count; i++) { View v = subviews [i]; @@ -149,52 +162,9 @@ public class DimAuto () : Dim } subviewsSize += maxAnchorEnd; + #endregion Anchored - #region Aligned - - // Now, handle subviews that are anchored to the end - // [x] PosAnchorEnd - int maxAlign = 0; - if (dimension == Dimension.Width) - { - // Use Linq to get a list of distinct GroupIds from the subviews - List groupIds = includedSubviews.Select (v => v.X is PosAlign posAlign ? posAlign.GroupId : -1).Distinct ().ToList (); - - foreach (var groupId in groupIds) - { - List dimensionsList = new (); - - // PERF: If this proves a perf issue, consider caching a ref to this list in each item - List posAlignsInGroup = includedSubviews.Where ( - v => - { - return dimension switch - { - Dimension.Width when v.X is PosAlign alignX => alignX.GroupId == groupId, - Dimension.Height when v.Y is PosAlign alignY => alignY.GroupId == groupId, - _ => false - }; - }) - .Select (v => dimension == Dimension.Width ? v.X as PosAlign : v.Y as PosAlign) - .ToList (); - - if (posAlignsInGroup.Count == 0) - { - continue; - } - - maxAlign = posAlignsInGroup [0].CalculateMinDimension (groupId, includedSubviews, dimension); - } - } - else - { - subviews = includedSubviews.Where (v => v.Y is PosAlign).ToList (); - } - - subviewsSize = int.Max (subviewsSize, maxAlign); - #endregion Aligned - #region Auto @@ -208,19 +178,12 @@ public class DimAuto () : Dim } int maxAuto = 0; + for (var i = 0; i < subviews.Count; i++) { View v = subviews [i]; - //if (dimension == Dimension.Width) - //{ - // v.SetRelativeLayout (new Size (autoMax - subviewsSize, 0)); - //} - //else - //{ - // v.SetRelativeLayout (new Size (0, autoMax - subviewsSize)); - //} - maxAuto = dimension == Dimension.Width ? v.Frame.X + v.Frame.Width : v.Frame.Y + v.Frame.Height; + maxAuto = CalculateMinDimension (us, dimension); if (maxAuto > subviewsSize) { @@ -229,32 +192,40 @@ public class DimAuto () : Dim } } -// subviewsSize += maxAuto; + // subviewsSize += maxAuto; #endregion Auto - //#region Center - //// Now, handle subviews that are Centered - //if (dimension == Dimension.Width) - //{ - // subviews = us.Subviews.Where (v => v.X is PosCenter).ToList (); - //} - //else - //{ - // subviews = us.Subviews.Where (v => v.Y is PosCenter).ToList (); - //} + #region Center - //int maxCenter = 0; - //for (var i = 0; i < subviews.Count; i++) - //{ - // View v = subviews [i]; - // maxCenter = dimension == Dimension.Width ? v.Frame.Width : v.Frame.Height; - //} + // Now, handle subviews that are Centered + if (dimension == Dimension.Width) + { + subviews = us.Subviews.Where (v => v.X is PosCenter).ToList (); + } + else + { + subviews = us.Subviews.Where (v => v.Y is PosCenter).ToList (); + } - //subviewsSize += maxCenter; - //#endregion Center + int maxCenter = 0; + + for (var i = 0; i < subviews.Count; i++) + { + View v = subviews [i]; + maxCenter = dimension == Dimension.Width ? v.Frame.Width : v.Frame.Height; + + if (maxCenter > subviewsSize) + { + // BUGBUG: Should we break here? Or choose min/max? + subviewsSize = maxCenter; + } + } + + #endregion Center #region Are Dependent + // Now, go back to those that are dependent on content size // [x] DimFill // [ ] DimPercent @@ -268,6 +239,7 @@ public class DimAuto () : Dim } int maxFill = 0; + for (var i = 0; i < subviews.Count; i++) { View v = subviews [i]; @@ -280,10 +252,12 @@ public class DimAuto () : Dim { v.SetRelativeLayout (new Size (0, autoMax - subviewsSize)); } + maxFill = dimension == Dimension.Width ? v.Frame.Width : v.Frame.Height; } subviewsSize += maxFill; + #endregion Are Dependent } } @@ -309,6 +283,16 @@ public class DimAuto () : Dim return int.Min (max, autoMax); } + internal int CalculateMinDimension (View us, Dimension dimension) + { + + + int min = dimension == Dimension.Width ? us.Frame.Width : us.Frame.Height; + + return min; + } + + internal override bool ReferencesOtherViews () { // BUGBUG: This is not correct. _contentSize may be null. diff --git a/Terminal.Gui/View/Layout/PosAlign.cs b/Terminal.Gui/View/Layout/PosAlign.cs index d1b2bce11..31bb81a26 100644 --- a/Terminal.Gui/View/Layout/PosAlign.cs +++ b/Terminal.Gui/View/Layout/PosAlign.cs @@ -198,6 +198,7 @@ public class PosAlign : Pos for (var index = 0; index < viewsInGroup.Count; index++) { View view = viewsInGroup [index]; + PosAlign? posAlign = dimension == Dimension.Width ? view.X as PosAlign : view.Y as PosAlign; if (posAlign is { }) diff --git a/Terminal.Gui/Views/Bar.cs b/Terminal.Gui/Views/Bar.cs index 534cc1d88..ec3aabf4f 100644 --- a/Terminal.Gui/Views/Bar.cs +++ b/Terminal.Gui/Views/Bar.cs @@ -99,13 +99,45 @@ public class Bar : View } barItem.Y = Pos.Center (); - barItem.SetRelativeLayout(new Size(int.MaxValue, int.MaxValue)); + barItem.SetRelativeLayout (new Size (int.MaxValue, int.MaxValue)); prevBarItem = barItem; } break; case Orientation.Vertical: + // CommandView is aligned left, HelpView is aligned right, KeyView is aligned right + // All CommandView's are the same width, all HelpView's are the same width, + // all KeyView's are the same width + + int maxCommandWidth = 0; + int maxHelpWidth = 0; + + List shortcuts = Subviews.Where (s => s is Shortcut && s.Visible).Cast ().ToList (); + + foreach (Shortcut shortcut in shortcuts) + { + // Let AutoSize do its thing to get the minimum width of each CommandView and HelpView + shortcut.CommandView.SetRelativeLayout (new Size (int.MaxValue, int.MaxValue)); + shortcut.KeyView.SetRelativeLayout (new Size (int.MaxValue, int.MaxValue)); + shortcut.HelpView.SetRelativeLayout (new Size (int.MaxValue, int.MaxValue)); + } + + maxCommandWidth = shortcuts.Max (s => s.CommandView.Frame.Width); + maxHelpWidth = shortcuts.Max (s => s.HelpView.Frame.Width); + + // Set the width of all CommandView's and HelpView's to the max width + foreach (Shortcut shortcut in shortcuts) + { + shortcut.CommandView.Width = Dim.Auto (minimumContentDim: maxCommandWidth); + shortcut.KeyView.Width = Dim.Auto (); + shortcut.HelpView.Width = Dim.Auto (minimumContentDim: maxHelpWidth); + + // shortcut.LayoutSubviews (); + } + + // Set the overall size of the Bar and arrange the views vertically + var maxBarItemWidth = 0; for (var index = 0; index < Subviews.Count; index++) @@ -128,6 +160,7 @@ public class Bar : View } prevBarItem = barItem; + if (barItem is Shortcut shortcut) { //shortcut.SetRelativeLayout (new (int.MaxValue, int.MaxValue)); @@ -137,32 +170,51 @@ public class Bar : View { maxBarItemWidth = Math.Max (maxBarItemWidth, barItem.Frame.Width); } + barItem.X = 0; } - for (var index = 0; index < Subviews.Count; index++) + foreach (Shortcut shortcut in shortcuts) { - var shortcut = Subviews [index] as Shortcut; - - if (shortcut is { Visible: false }) - { - continue; - } - if (Width is DimAuto) { - shortcut._container.Width = Dim.Auto (DimAutoStyle.Content, minimumContentDim: maxBarItemWidth); + shortcut.Width = Dim.Auto (DimAutoStyle.Content, minimumContentDim: maxBarItemWidth); } else { - shortcut._container.Width = Dim.Fill (); - shortcut.Width = Dim.Fill (); + //shortcut._container.Width = Dim.Fill (); + // shortcut.Width = Dim.Fill (); } - //shortcut.SetContentSize (new (maxBarItemWidth, 1)); - //shortcut.Width = Dim.Auto (DimAutoStyle.Content, minimumContentDim: int.Max(maxBarItemWidth, GetContentSize().Width)); - + shortcut.LayoutSubviews (); } + + + //for (var index = 0; index < Subviews.Count; index++) + //{ + // var shortcut = Subviews [index] as Shortcut; + + // if (shortcut is { Visible: false }) + // { + // continue; + // } + + // if (Width is DimAuto) + // { + // shortcut._container.Width = Dim.Auto (DimAutoStyle.Content, minimumContentDim: maxBarItemWidth); + // } + // else + // { + // shortcut._container.Width = Dim.Fill (); + // shortcut.Width = Dim.Fill (); + // } + + // //shortcut.SetContentSize (new (maxBarItemWidth, 1)); + // //shortcut.Width = Dim.Auto (DimAutoStyle.Content, minimumContentDim: int.Max(maxBarItemWidth, GetContentSize().Width)); + + //} + + break; } diff --git a/Terminal.Gui/Views/Shortcut.cs b/Terminal.Gui/Views/Shortcut.cs index 044145960..a5ca12d3f 100644 --- a/Terminal.Gui/Views/Shortcut.cs +++ b/Terminal.Gui/Views/Shortcut.cs @@ -59,7 +59,8 @@ public class Shortcut : View // Only the Shortcut (_container) should be able to have focus, not any subviews. CanFocus = true, Width = Dim.Auto (DimAutoStyle.Content, 1), - Height = Dim.Auto (DimAutoStyle.Content, 1) + Height = Dim.Auto (DimAutoStyle.Content, 1), + BorderStyle = LineStyle.Dashed }; CommandView = new (); @@ -71,8 +72,11 @@ public class Shortcut : View CanFocus = false, X = Pos.Align (Alignment.End, AlignmentModes.IgnoreFirstOrLast | AlignmentModes.AddSpaceBetweenItems), Y = Pos.Center (), + + // Helpview is the only subview that doesn't have a min width Width = Dim.Auto (DimAutoStyle.Text), - Height = Dim.Auto (DimAutoStyle.Text) + Height = Dim.Auto (DimAutoStyle.Text), + ColorScheme = Colors.ColorSchemes ["Error"] }; _container.Add (HelpView); @@ -86,8 +90,10 @@ public class Shortcut : View CanFocus = false, X = Pos.Align (Alignment.End, AlignmentModes.IgnoreFirstOrLast | AlignmentModes.AddSpaceBetweenItems), Y = Pos.Center (), + + // Bar will set the width of all KeyViews to the width of the widest KeyView. Width = Dim.Auto (DimAutoStyle.Text), - Height = Dim.Auto (DimAutoStyle.Text) + Height = Dim.Auto (DimAutoStyle.Text), }; _container.Add (KeyView); @@ -259,6 +265,7 @@ public class Shortcut : View // Right now, we don't set CanFocus to false here. _commandView.CanFocus = false; + // Bar will set the width of all CommandViews to the width of the widest CommandViews. _commandView.Width = Dim.Auto (DimAutoStyle.Text); _commandView.Height = Dim.Auto (DimAutoStyle.Text); _commandView.X = X = Pos.Align (Alignment.End, AlignmentModes.IgnoreFirstOrLast | AlignmentModes.AddSpaceBetweenItems); diff --git a/UICatalog/Scenarios/Bars.cs b/UICatalog/Scenarios/Bars.cs index ee43095c4..26a4e5aab 100644 --- a/UICatalog/Scenarios/Bars.cs +++ b/UICatalog/Scenarios/Bars.cs @@ -40,17 +40,21 @@ public class Bars : Scenario }; Application.Top.Add (eventLog); - //var shortcut1 = new Shortcut - //{ - // Title = "_Zigzag", - // Key = Key.Z.WithAlt, - // Text = "Gonna zig zag", - // KeyBindingScope = KeyBindingScope.HotKey, - // Command = Command.Accept, - // X = 10,// Pos.Center (), - // Y = 10,//Pos.Center () - // //Width = Dim.Auto(DimAutoStyle.Content, minimumContentDim: 50), - //}; + var shortcut1 = new Shortcut + { + Title = "_Zigzag", + Key = Key.Z.WithAlt, + Text = "Gonna zig zag", + KeyBindingScope = KeyBindingScope.HotKey, + Command = Command.Accept, + }; + shortcut1.Accept += (s, e) => + { + eventSource.Add ($"Accept: {s}"); + eventLog.MoveDown (); + }; + Application.Top.Add (shortcut1); + shortcut1.SetFocus (); //var shortcut2 = new Shortcut //{ @@ -64,74 +68,74 @@ public class Bars : Scenario // //Width = 50, //}; - //Application.Top.Add (shortcut1, shortcut2); - //shortcut1.SetFocus (); - var shortcut3 = new Shortcut - { - Title = "Shortcut3", - Key = Key.D3.WithCtrl, - Text = "Number Three", - KeyBindingScope = KeyBindingScope.Application, - Command = Command.Accept, - }; + //var shortcut3 = new Shortcut + //{ + // Title = "Shortcut3", + // Key = Key.D3.WithCtrl, + // Text = "Number Three", + // KeyBindingScope = KeyBindingScope.Application, + // Command = Command.Accept, + //}; - shortcut3.Accept += (s, e) => - { - eventSource.Add ($"Accept: {s}"); - eventLog.MoveDown (); - }; + //shortcut3.Accept += (s, e) => + // { + // eventSource.Add ($"Accept: {s}"); + // eventLog.MoveDown (); + // }; - var shortcut4 = new Shortcut - { - Title = "Shortcut4", - Text = "Number 4", - Key = Key.F4, - KeyBindingScope = KeyBindingScope.Application, - Command = Command.Accept, - }; + //var shortcut4 = new Shortcut + //{ + // Title = "Shortcut4", + // Text = "Number 4", + // Key = Key.F4, + // KeyBindingScope = KeyBindingScope.Application, + // Command = Command.Accept, + //}; - var cb = new CheckBox () - { - Title = "Hello",// shortcut4.Text - }; + //var cb = new CheckBox () + //{ + // Title = "Hello",// shortcut4.Text + //}; - cb.Toggled += (s, e) => - { - eventSource.Add ($"Toggled: {s}"); - eventLog.MoveDown (); - }; + //cb.Toggled += (s, e) => + // { + // eventSource.Add ($"Toggled: {s}"); + // eventLog.MoveDown (); + // }; - shortcut4.CommandView = cb; + //shortcut4.CommandView = cb; - shortcut4.Accept += (s, e) => - { - eventSource.Add ($"Accept: {s}"); - eventLog.MoveDown (); - }; + //shortcut4.Accept += (s, e) => + // { + // eventSource.Add ($"Accept: {s}"); + // eventLog.MoveDown (); + // }; - var bar = new Bar - { - X = 2, - Y = 2, - Orientation = Orientation.Vertical, - StatusBarStyle = false, - Width = Dim.Percent(40) - }; - bar.Add (shortcut3, shortcut4); + //var bar = new Bar + //{ + // X = 2, + // Y = Pos.Bottom(shortcut1), + // Orientation = Orientation.Vertical, + // StatusBarStyle = false, + // Width = Dim.Percent(40) + //}; + //bar.Add (shortcut3, shortcut4); - CheckBox hello = new () - { - Title = "Hello", - }; - Application.Top.Add (hello); - hello.Toggled += (s, e) => - { - eventSource.Add ($"Toggled: {s}"); - eventLog.MoveDown (); - }; + ////CheckBox hello = new () + ////{ + //// Title = "Hello", + //// X = 0, + //// Y = 1, + ////}; + ////Application.Top.Add (hello); + ////hello.Toggled += (s, e) => + //// { + //// eventSource.Add ($"Toggled: {s}"); + //// eventLog.MoveDown (); + //// }; - Application.Top.Add (bar); + //Application.Top.Add (bar); // BUGBUG: This should not be needed //Application.Top.LayoutSubviews ();