Hacked in Application.Navigation.Set/GetFocused

This commit is contained in:
Tig
2024-08-03 07:21:49 -06:00
parent ac9d0118dc
commit 4985da476e
4 changed files with 110 additions and 20 deletions

View File

@@ -7,6 +7,7 @@ namespace Terminal.Gui;
/// </summary>
public class ApplicationNavigation
{
/// <summary>
/// Initializes a new instance of the <see cref="ApplicationNavigation"/> class.
/// </summary>
@@ -15,6 +16,75 @@ public class ApplicationNavigation
// TODO: Move navigation key bindings here from AddApplicationKeyBindings
}
private View? _focused = null;
/// <summary>
/// Gets the most focused <see cref="View"/> in the application, if there is one.
/// </summary>
public View? GetFocused () { return _focused; }
/// <summary>
/// INTERNAL method to record the most focused <see cref="View"/> in the application.
/// </summary>
/// <remarks>
/// Raises <see cref="FocusedChanged"/>.
/// </remarks>
internal void SetFocused (View? value)
{
if (_focused == value)
{
return;
}
_focused = value;
FocusedChanged?.Invoke (null, EventArgs.Empty);
return;
}
/// <summary>
/// Raised when the most focused <see cref="View"/> in the application has changed.
/// </summary>
public event EventHandler<EventArgs>? FocusedChanged;
/// <summary>
/// Gets whether <paramref name="view"/> is in the Subview hierarchy of <paramref name="start"/>.
/// </summary>
/// <param name="start"></param>
/// <param name="view"></param>
/// <returns></returns>
public static bool IsInHierarchy (View start, View? view)
{
if (view is null)
{
return false;
}
if (view == start)
{
return true;
}
foreach (View subView in start.Subviews)
{
if (view == subView)
{
return true;
}
var found = IsInHierarchy (subView, view);
if (found)
{
return found;
}
}
return false;
}
/// <summary>
/// Gets the deepest focused subview of the specified <paramref name="view"/>.
/// </summary>

View File

@@ -72,6 +72,11 @@ public partial class View // Focus and cross-view navigation management (TabStop
{
if (Focused.AdvanceFocus (direction, behavior))
{
// TODO: Temporary hack to make Application.Navigation.FocusChanged work
if (Focused.Focused is null)
{
Application.Navigation!.SetFocused (Focused);
}
return true;
}
}
@@ -144,6 +149,12 @@ public partial class View // Focus and cross-view navigation management (TabStop
SetFocus (view);
// TODO: Temporary hack to make Application.Navigation.FocusChanged work
if (view.Focused is null)
{
Application.Navigation!.SetFocused (view);
}
return true;
}
@@ -604,6 +615,13 @@ public partial class View // Focus and cross-view navigation management (TabStop
{
// If there is no SuperView, then this is a top-level view
SetFocus (this);
}
// TODO: Temporary hack to make Application.Navigation.FocusChanged work
if (HasFocus && Focused.Focused is null)
{
Application.Navigation!.SetFocused (Focused);
}
// TODO: This is a temporary hack to make overlapped non-Toplevels have a zorder. See also: View.OnDrawContent.

View File

@@ -34,27 +34,27 @@ public class AdornmentsEditor : View
TabStop = TabBehavior.TabGroup;
Application.MouseEvent += Application_MouseEvent;
//ApplicationNavigation.FocusedChanged += ApplicationNavigationOnFocusedChanged;
//Application.MouseEvent += Application_MouseEvent;
Application.Navigation!.FocusedChanged += ApplicationNavigationOnFocusedChanged;
Initialized += AdornmentsEditor_Initialized;
}
//private void ApplicationNavigationOnFocusedChanged (object sender, EventArgs e)
//{
// if (ApplicationNavigation.IsInHierarchy (this, ApplicationNavigation.Focused))
// {
// return;
// }
private void ApplicationNavigationOnFocusedChanged (object sender, EventArgs e)
{
if (ApplicationNavigation.IsInHierarchy (this, Application.Navigation!.GetFocused ()))
{
return;
}
// if (ApplicationNavigation.Focused is Adornment adornment)
// {
// ViewToEdit = adornment.Parent;
// }
// else
// {
// ViewToEdit = ApplicationNavigation.Focused;
// }
//}
if (Application.Navigation!.GetFocused () is Adornment adornment)
{
ViewToEdit = adornment.Parent;
}
else
{
ViewToEdit = Application.Navigation.GetFocused ();
}
}
/// <summary>
/// Gets or sets whether the AdornmentsEditor should automatically select the View to edit when the mouse is clicked
@@ -128,7 +128,7 @@ public class AdornmentsEditor : View
_diagPaddingCheckBox.Y = Pos.Bottom (_paddingEditor);
_diagRulerCheckBox = new () { Text = "_Diagnostic Ruler" };
_diagRulerCheckBox.State = Diagnostics.FastHasFlags(ViewDiagnosticFlags.Ruler) ? CheckState.Checked : CheckState.UnChecked;
_diagRulerCheckBox.State = Diagnostics.FastHasFlags (ViewDiagnosticFlags.Ruler) ? CheckState.Checked : CheckState.UnChecked;
_diagRulerCheckBox.Toggle += (s, e) =>
{
@@ -192,7 +192,7 @@ public class AdornmentsEditor : View
_borderEditor.AdornmentToEdit = _viewToEdit?.Border ?? null;
_paddingEditor.AdornmentToEdit = _viewToEdit?.Padding ?? null;
_lblView.Text = $"{_viewToEdit?.GetType ().Name}: {_viewToEdit?.Id}" ?? string.Empty;
_lblView.Text = $"{_viewToEdit?.GetType ().Name}: {_viewToEdit?.Id}" ?? string.Empty;
return;
}

View File

@@ -40,6 +40,7 @@ public class ScenarioTests : TestsAllViews
var initialized = false;
var shutdown = false;
object timeout = null;
int iterationCount = 0;
Application.InitializedChanged += OnApplicationOnInitializedChanged;
@@ -106,7 +107,7 @@ public class ScenarioTests : TestsAllViews
}
Assert.Fail (
$"'{scenario.GetName ()}' failed to Quit with {Application.QuitKey} after {abortTime}ms. Force quit.");
$"'{scenario.GetName ()}' failed to Quit with {Application.QuitKey} after {abortTime}ms and {iterationCount} iterations. Force quit.");
Application.ResetState (true);
@@ -115,6 +116,7 @@ public class ScenarioTests : TestsAllViews
void OnApplicationOnIteration (object s, IterationEventArgs a)
{
iterationCount++;
if (Application.IsInitialized)
{
// Press QuitKey