diff --git a/Terminal.Gui/Application/ApplicationOverlapped.cs b/Terminal.Gui/Application/ApplicationOverlapped.cs index 14a4163ea..fa11ae1f8 100644 --- a/Terminal.Gui/Application/ApplicationOverlapped.cs +++ b/Terminal.Gui/Application/ApplicationOverlapped.cs @@ -79,7 +79,7 @@ public static class ApplicationOverlapped if (top is Toplevel && Application.Top?.Subviews.Count > 1 && Application.Top.Subviews [^1] != top) { - Application.Top.BringSubviewToFront (top); + Application.Top.MoveSubviewToStart (top); } } diff --git a/Terminal.Gui/View/View.Hierarchy.cs b/Terminal.Gui/View/View.Hierarchy.cs index 5e899e809..b9949174d 100644 --- a/Terminal.Gui/View/View.Hierarchy.cs +++ b/Terminal.Gui/View/View.Hierarchy.cs @@ -226,9 +226,11 @@ public partial class View // SuperView/SubView hierarchy management (SuperView, public event EventHandler Removed; - /// Moves one position towards the start of the list - /// The subview to move forward. - public void BringSubviewForward (View subview) + /// + /// Moves one position towards the end of the list. + /// + /// The subview to move. + public void MoveSubviewTowardsEnd (View subview) { PerformActionForSubview ( subview, @@ -245,9 +247,11 @@ public partial class View // SuperView/SubView hierarchy management (SuperView, ); } - /// Moves to the start of the list. - /// The subview to send to the start. - public void BringSubviewToFront (View subview) + /// + /// Moves to the end of the list. + /// + /// The subview to move. + public void MoveSubviewToEnd (View subview) { PerformActionForSubview ( subview, @@ -260,9 +264,11 @@ public partial class View // SuperView/SubView hierarchy management (SuperView, } - /// Moves one position towards the end of the list - /// The subview to move backwards. - public void SendSubviewBackwards (View subview) + /// + /// Moves one position towards the start of the list. + /// + /// The subview to move. + public void MoveSubviewTowardsStart (View subview) { PerformActionForSubview ( subview, @@ -279,9 +285,11 @@ public partial class View // SuperView/SubView hierarchy management (SuperView, ); } - /// Moves to the end of the list. - /// The subview to send to the end. - public void SendSubviewToBack (View subview) + /// + /// Moves to the start of the list. + /// + /// The subview to move. + public void MoveSubviewToStart (View subview) { PerformActionForSubview ( subview, diff --git a/Terminal.Gui/Views/ComboBox.cs b/Terminal.Gui/Views/ComboBox.cs index 20d9ca361..55592d8ce 100644 --- a/Terminal.Gui/Views/ComboBox.cs +++ b/Terminal.Gui/Views/ComboBox.cs @@ -495,7 +495,7 @@ public class ComboBox : View, IDesignable Reset (true); _listview.Clear (); _listview.TabStop = TabBehavior.NoStop; - SuperView?.SendSubviewToBack (this); + SuperView?.MoveSubviewToEnd (this); Rectangle rect = _listview.ViewportToScreen (_listview.IsInitialized ? _listview.Viewport : Rectangle.Empty); SuperView?.SetNeedsDisplay (rect); OnCollapsed (); @@ -795,7 +795,7 @@ public class ComboBox : View, IDesignable _listview.Clear (); _listview.Height = CalculateHeight (); - SuperView?.BringSubviewToFront (this); + SuperView?.MoveSubviewToStart (this); } private bool UnixEmulation () diff --git a/Terminal.Gui/Views/FileDialog.cs b/Terminal.Gui/Views/FileDialog.cs index a45243a89..62ad9e494 100644 --- a/Terminal.Gui/Views/FileDialog.cs +++ b/Terminal.Gui/Views/FileDialog.cs @@ -89,10 +89,11 @@ public class FileDialog : Dialog NavigateIf (k, KeyCode.CursorUp, _tableView); NavigateIf (k, KeyCode.CursorRight, _btnOk); }; - _btnCancel.Accept += (s, e) => { - Canceled = true; - Application.RequestStop (); - }; + _btnCancel.Accept += (s, e) => + { + Canceled = true; + Application.RequestStop (); + }; _btnUp = new Button { X = 0, Y = 1, NoPadding = true }; _btnUp.Text = GetUpButtonText (); @@ -290,6 +291,8 @@ public class FileDialog : Dialog UpdateNavigationVisibility (); + // BUGBUG: This TabOrder is counter-intuitive. The tab order for a dialog should match the + // order the Views' are presented, left to right, top to bottom. // Determines tab order Add (_btnToggleSplitterCollapse); Add (_tbFind); @@ -458,19 +461,6 @@ public class FileDialog : Dialog _btnForward.Text = GetForwardButtonText (); _btnToggleSplitterCollapse.Text = GetToggleSplitterText (false); - if (Style.FlipOkCancelButtonLayoutOrder) - { - _btnCancel.X = Pos.Func (CalculateOkButtonPosX); - _btnOk.X = Pos.Right (_btnCancel) + 1; - - //// Flip tab order too for consistency - //int? p1 = _btnOk.TabIndex; - //int? p2 = _btnCancel.TabIndex; - - //_btnOk.TabIndex = p2; - //_btnCancel.TabIndex = p1; - } - _tbPath.Caption = Style.PathCaption; _tbFind.Caption = Style.SearchCaption; @@ -549,6 +539,12 @@ public class FileDialog : Dialog Title = GetDefaultTitle (); } + if (Style.FlipOkCancelButtonLayoutOrder) + { + _btnCancel.X = Pos.Func (CalculateOkButtonPosX); + _btnOk.X = Pos.Right (_btnCancel) + 1; + MoveSubviewTowardsFront (_btnCancel); + } LayoutSubviews (); } @@ -591,7 +587,7 @@ public class FileDialog : Dialog internal void ApplySort () { - FileSystemInfoStats [] stats = State?.Children ?? new FileSystemInfoStats[0]; + FileSystemInfoStats [] stats = State?.Children ?? new FileSystemInfoStats [0]; // This portion is never reordered (always .. at top then folders) IOrderedEnumerable forcedOrder = stats @@ -1549,7 +1545,7 @@ public class FileDialog : Dialog public SearchState (IDirectoryInfo dir, FileDialog parent, string searchTerms) : base (dir, parent) { parent.SearchMatcher.Initialize (searchTerms); - Children = new FileSystemInfoStats[0]; + Children = new FileSystemInfoStats [0]; BeginSearch (); } diff --git a/Terminal.Gui/Views/TabView.cs b/Terminal.Gui/Views/TabView.cs index e6959a491..aaeb34069 100644 --- a/Terminal.Gui/Views/TabView.cs +++ b/Terminal.Gui/Views/TabView.cs @@ -1348,7 +1348,7 @@ public class TabView : View _leftScrollIndicator.Visible = true; // Ensures this is clicked instead of the first tab - BringSubviewToFront (_leftScrollIndicator); + MoveSubviewToStart (_leftScrollIndicator); _leftScrollIndicator.Draw (); } else @@ -1366,7 +1366,7 @@ public class TabView : View _rightScrollIndicator.Visible = true; // Ensures this is clicked instead of the last tab if under this - BringSubviewToFront (_rightScrollIndicator); + MoveSubviewToStart (_rightScrollIndicator); _rightScrollIndicator.Draw (); } else diff --git a/UICatalog/Scenarios/Editor.cs b/UICatalog/Scenarios/Editor.cs index 652ecc733..abf285985 100644 --- a/UICatalog/Scenarios/Editor.cs +++ b/UICatalog/Scenarios/Editor.cs @@ -736,7 +736,7 @@ public class Editor : Scenario private void ShowFindReplace (bool isFind = true) { _findReplaceWindow.Visible = true; - _findReplaceWindow.SuperView.BringSubviewToFront (_findReplaceWindow); + _findReplaceWindow.SuperView.MoveSubviewToStart (_findReplaceWindow); _tabView.SetFocus (); _tabView.SelectedTab = isFind ? _tabView.Tabs.ToArray () [0] : _tabView.Tabs.ToArray () [1]; _tabView.SelectedTab.View.FocusDeepest (NavigationDirection.Forward, null); diff --git a/UnitTests/FileServices/FileDialogTests.cs b/UnitTests/FileServices/FileDialogTests.cs index 1c0954168..8b8b2e19b 100644 --- a/UnitTests/FileServices/FileDialogTests.cs +++ b/UnitTests/FileServices/FileDialogTests.cs @@ -99,13 +99,9 @@ public class FileDialogTests (ITestOutputHelper output) string openIn = Path.Combine (Environment.CurrentDirectory, "zz"); Directory.CreateDirectory (openIn); dlg.Path = openIn + Path.DirectorySeparatorChar; -#if BROKE_IN_2927 - Send ('f', ConsoleKey.F, false, true, false); -#else Application.OnKeyDown (Key.Tab); Application.OnKeyDown (Key.Tab); Application.OnKeyDown (Key.Tab); -#endif Assert.IsType (dlg.MostFocused); var tf = (TextField)dlg.MostFocused; diff --git a/UnitTests/View/SubviewTests.cs b/UnitTests/View/SubviewTests.cs index 37cda5ac4..692678ab1 100644 --- a/UnitTests/View/SubviewTests.cs +++ b/UnitTests/View/SubviewTests.cs @@ -373,4 +373,130 @@ public class SubviewTests view.Remove (subview); Assert.Equal (new Size (5, 5), view.GetContentSize ()); } + + [Fact] + public void MoveSubviewToStart () + { + View superView = new (); + + View subview1 = new View () + { + Id = "subview1" + }; + + View subview2 = new View () + { + Id = "subview2" + }; + + View subview3 = new View () + { + Id = "subview3" + }; + + superView.Add (subview1, subview2, subview3); + + superView.MoveSubviewToStart (subview2); + Assert.Equal(subview2, superView.Subviews [0]); + + superView.MoveSubviewToStart (subview3); + Assert.Equal (subview3, superView.Subviews [0]); + } + + + [Fact] + public void MoveSubviewTowardsFront () + { + View superView = new (); + + View subview1 = new View () + { + Id = "subview1" + }; + + View subview2 = new View () + { + Id = "subview2" + }; + + View subview3 = new View () + { + Id = "subview3" + }; + + superView.Add (subview1, subview2, subview3); + + superView.MoveSubviewTowardsFront (subview2); + Assert.Equal (subview2, superView.Subviews [0]); + + superView.MoveSubviewTowardsFront (subview3); + Assert.Equal (subview3, superView.Subviews [1]); + + // Already at front, what happens? + superView.MoveSubviewTowardsFront (subview2); + Assert.Equal (subview2, superView.Subviews [0]); + } + + [Fact] + public void MoveSubviewToEnd () + { + View superView = new (); + + View subview1 = new View () + { + Id = "subview1" + }; + + View subview2 = new View () + { + Id = "subview2" + }; + + View subview3 = new View () + { + Id = "subview3" + }; + + superView.Add (subview1, subview2, subview3); + + superView.MoveSubviewToEnd (subview1); + Assert.Equal (subview1, superView.Subviews [^1]); + + superView.MoveSubviewToEnd (subview2); + Assert.Equal (subview2, superView.Subviews [^1]); + } + + + [Fact] + public void MoveSubviewTowardsEnd () + { + View superView = new (); + + View subview1 = new View () + { + Id = "subview1" + }; + + View subview2 = new View () + { + Id = "subview2" + }; + + View subview3 = new View () + { + Id = "subview3" + }; + + superView.Add (subview1, subview2, subview3); + + superView.MoveSubviewTowardsEnd (subview2); + Assert.Equal (subview2, superView.Subviews [^1]); + + superView.MoveSubviewTowardsEnd (subview1); + Assert.Equal (subview1, superView.Subviews [1]); + + // Already at end, what happens? + superView.MoveSubviewTowardsEnd (subview2); + Assert.Equal (subview2, superView.Subviews [^1]); + } } diff --git a/docfx/docs/migratingfromv1.md b/docfx/docs/migratingfromv1.md index feb73c967..8aab789e5 100644 --- a/docfx/docs/migratingfromv1.md +++ b/docfx/docs/migratingfromv1.md @@ -434,3 +434,13 @@ In v1, you could add timeouts via `Application.MainLoop.AddTimeout` among other + Application.AddTimeout (TimeSpan time, Func callback) ``` +## `SendSubviewXXX` renamed and corrected + +In v1, the `View` methods to move Subviews within the Subviews list were poorly named and actually operated in reverse of what their names suggested. + +In v2, these methods have been named correctly. + +- `SendSubViewToBack` -> `MoveSubviewToStart` - Moves the specified subview to the start of the list. +- `SendSubViewBackward` -> `MoveSubviewTowardsStart` - Moves the specified subview one position towards the start of the list. +- `SendSubViewToFront` -> `MoveSubviewToEnd` - Moves the specified subview to the end of the list. +- `SendSubViewForward` -> `MoveSubviewTowardsEnd` - Moves the specified subview one position towards the end of the list.