Refactored subview methods

This commit is contained in:
Tig
2024-08-26 13:52:33 -07:00
parent 1b1a2524e7
commit 4b479a60f3
9 changed files with 177 additions and 41 deletions

View File

@@ -79,7 +79,7 @@ public static class ApplicationOverlapped
if (top is Toplevel && Application.Top?.Subviews.Count > 1 && Application.Top.Subviews [^1] != top) if (top is Toplevel && Application.Top?.Subviews.Count > 1 && Application.Top.Subviews [^1] != top)
{ {
Application.Top.BringSubviewToFront (top); Application.Top.MoveSubviewToStart (top);
} }
} }

View File

@@ -226,9 +226,11 @@ public partial class View // SuperView/SubView hierarchy management (SuperView,
public event EventHandler<SuperViewChangedEventArgs> Removed; public event EventHandler<SuperViewChangedEventArgs> Removed;
/// <summary>Moves <paramref name="subview"/> one position towards the start of the <see cref="Subviews"/> list</summary> /// <summary>
/// <param name="subview">The subview to move forward.</param> /// Moves <paramref name="subview"/> one position towards the end of the <see cref="Subviews"/> list.
public void BringSubviewForward (View subview) /// </summary>
/// <param name="subview">The subview to move.</param>
public void MoveSubviewTowardsEnd (View subview)
{ {
PerformActionForSubview ( PerformActionForSubview (
subview, subview,
@@ -245,9 +247,11 @@ public partial class View // SuperView/SubView hierarchy management (SuperView,
); );
} }
/// <summary>Moves <paramref name="subview"/> to the start of the <see cref="Subviews"/> list.</summary> /// <summary>
/// <param name="subview">The subview to send to the start.</param> /// Moves <paramref name="subview"/> to the end of the <see cref="Subviews"/> list.
public void BringSubviewToFront (View subview) /// </summary>
/// <param name="subview">The subview to move.</param>
public void MoveSubviewToEnd (View subview)
{ {
PerformActionForSubview ( PerformActionForSubview (
subview, subview,
@@ -260,9 +264,11 @@ public partial class View // SuperView/SubView hierarchy management (SuperView,
} }
/// <summary>Moves <paramref name="subview"/> one position towards the end of the <see cref="Subviews"/> list</summary> /// <summary>
/// <param name="subview">The subview to move backwards.</param> /// Moves <paramref name="subview"/> one position towards the start of the <see cref="Subviews"/> list.
public void SendSubviewBackwards (View subview) /// </summary>
/// <param name="subview">The subview to move.</param>
public void MoveSubviewTowardsStart (View subview)
{ {
PerformActionForSubview ( PerformActionForSubview (
subview, subview,
@@ -279,9 +285,11 @@ public partial class View // SuperView/SubView hierarchy management (SuperView,
); );
} }
/// <summary>Moves <paramref name="subview"/> to the end of the <see cref="Subviews"/> list.</summary> /// <summary>
/// <param name="subview">The subview to send to the end.</param> /// Moves <paramref name="subview"/> to the start of the <see cref="Subviews"/> list.
public void SendSubviewToBack (View subview) /// </summary>
/// <param name="subview">The subview to move.</param>
public void MoveSubviewToStart (View subview)
{ {
PerformActionForSubview ( PerformActionForSubview (
subview, subview,

View File

@@ -495,7 +495,7 @@ public class ComboBox : View, IDesignable
Reset (true); Reset (true);
_listview.Clear (); _listview.Clear ();
_listview.TabStop = TabBehavior.NoStop; _listview.TabStop = TabBehavior.NoStop;
SuperView?.SendSubviewToBack (this); SuperView?.MoveSubviewToEnd (this);
Rectangle rect = _listview.ViewportToScreen (_listview.IsInitialized ? _listview.Viewport : Rectangle.Empty); Rectangle rect = _listview.ViewportToScreen (_listview.IsInitialized ? _listview.Viewport : Rectangle.Empty);
SuperView?.SetNeedsDisplay (rect); SuperView?.SetNeedsDisplay (rect);
OnCollapsed (); OnCollapsed ();
@@ -795,7 +795,7 @@ public class ComboBox : View, IDesignable
_listview.Clear (); _listview.Clear ();
_listview.Height = CalculateHeight (); _listview.Height = CalculateHeight ();
SuperView?.BringSubviewToFront (this); SuperView?.MoveSubviewToStart (this);
} }
private bool UnixEmulation () private bool UnixEmulation ()

View File

@@ -89,10 +89,11 @@ public class FileDialog : Dialog
NavigateIf (k, KeyCode.CursorUp, _tableView); NavigateIf (k, KeyCode.CursorUp, _tableView);
NavigateIf (k, KeyCode.CursorRight, _btnOk); NavigateIf (k, KeyCode.CursorRight, _btnOk);
}; };
_btnCancel.Accept += (s, e) => { _btnCancel.Accept += (s, e) =>
Canceled = true; {
Application.RequestStop (); Canceled = true;
}; Application.RequestStop ();
};
_btnUp = new Button { X = 0, Y = 1, NoPadding = true }; _btnUp = new Button { X = 0, Y = 1, NoPadding = true };
_btnUp.Text = GetUpButtonText (); _btnUp.Text = GetUpButtonText ();
@@ -290,6 +291,8 @@ public class FileDialog : Dialog
UpdateNavigationVisibility (); 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 // Determines tab order
Add (_btnToggleSplitterCollapse); Add (_btnToggleSplitterCollapse);
Add (_tbFind); Add (_tbFind);
@@ -458,19 +461,6 @@ public class FileDialog : Dialog
_btnForward.Text = GetForwardButtonText (); _btnForward.Text = GetForwardButtonText ();
_btnToggleSplitterCollapse.Text = GetToggleSplitterText (false); _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; _tbPath.Caption = Style.PathCaption;
_tbFind.Caption = Style.SearchCaption; _tbFind.Caption = Style.SearchCaption;
@@ -549,6 +539,12 @@ public class FileDialog : Dialog
Title = GetDefaultTitle (); Title = GetDefaultTitle ();
} }
if (Style.FlipOkCancelButtonLayoutOrder)
{
_btnCancel.X = Pos.Func (CalculateOkButtonPosX);
_btnOk.X = Pos.Right (_btnCancel) + 1;
MoveSubviewTowardsFront (_btnCancel);
}
LayoutSubviews (); LayoutSubviews ();
} }
@@ -591,7 +587,7 @@ public class FileDialog : Dialog
internal void ApplySort () 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) // This portion is never reordered (always .. at top then folders)
IOrderedEnumerable<FileSystemInfoStats> forcedOrder = stats IOrderedEnumerable<FileSystemInfoStats> forcedOrder = stats
@@ -1549,7 +1545,7 @@ public class FileDialog : Dialog
public SearchState (IDirectoryInfo dir, FileDialog parent, string searchTerms) : base (dir, parent) public SearchState (IDirectoryInfo dir, FileDialog parent, string searchTerms) : base (dir, parent)
{ {
parent.SearchMatcher.Initialize (searchTerms); parent.SearchMatcher.Initialize (searchTerms);
Children = new FileSystemInfoStats[0]; Children = new FileSystemInfoStats [0];
BeginSearch (); BeginSearch ();
} }

View File

@@ -1348,7 +1348,7 @@ public class TabView : View
_leftScrollIndicator.Visible = true; _leftScrollIndicator.Visible = true;
// Ensures this is clicked instead of the first tab // Ensures this is clicked instead of the first tab
BringSubviewToFront (_leftScrollIndicator); MoveSubviewToStart (_leftScrollIndicator);
_leftScrollIndicator.Draw (); _leftScrollIndicator.Draw ();
} }
else else
@@ -1366,7 +1366,7 @@ public class TabView : View
_rightScrollIndicator.Visible = true; _rightScrollIndicator.Visible = true;
// Ensures this is clicked instead of the last tab if under this // Ensures this is clicked instead of the last tab if under this
BringSubviewToFront (_rightScrollIndicator); MoveSubviewToStart (_rightScrollIndicator);
_rightScrollIndicator.Draw (); _rightScrollIndicator.Draw ();
} }
else else

View File

@@ -736,7 +736,7 @@ public class Editor : Scenario
private void ShowFindReplace (bool isFind = true) private void ShowFindReplace (bool isFind = true)
{ {
_findReplaceWindow.Visible = true; _findReplaceWindow.Visible = true;
_findReplaceWindow.SuperView.BringSubviewToFront (_findReplaceWindow); _findReplaceWindow.SuperView.MoveSubviewToStart (_findReplaceWindow);
_tabView.SetFocus (); _tabView.SetFocus ();
_tabView.SelectedTab = isFind ? _tabView.Tabs.ToArray () [0] : _tabView.Tabs.ToArray () [1]; _tabView.SelectedTab = isFind ? _tabView.Tabs.ToArray () [0] : _tabView.Tabs.ToArray () [1];
_tabView.SelectedTab.View.FocusDeepest (NavigationDirection.Forward, null); _tabView.SelectedTab.View.FocusDeepest (NavigationDirection.Forward, null);

View File

@@ -99,13 +99,9 @@ public class FileDialogTests (ITestOutputHelper output)
string openIn = Path.Combine (Environment.CurrentDirectory, "zz"); string openIn = Path.Combine (Environment.CurrentDirectory, "zz");
Directory.CreateDirectory (openIn); Directory.CreateDirectory (openIn);
dlg.Path = openIn + Path.DirectorySeparatorChar; 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); Application.OnKeyDown (Key.Tab);
Application.OnKeyDown (Key.Tab); Application.OnKeyDown (Key.Tab);
#endif
Assert.IsType<TextField> (dlg.MostFocused); Assert.IsType<TextField> (dlg.MostFocused);
var tf = (TextField)dlg.MostFocused; var tf = (TextField)dlg.MostFocused;

View File

@@ -373,4 +373,130 @@ public class SubviewTests
view.Remove (subview); view.Remove (subview);
Assert.Equal (new Size (5, 5), view.GetContentSize ()); 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]);
}
} }

View File

@@ -434,3 +434,13 @@ In v1, you could add timeouts via `Application.MainLoop.AddTimeout` among other
+ Application.AddTimeout (TimeSpan time, Func<bool> callback) + Application.AddTimeout (TimeSpan time, Func<bool> 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.