mirror of
https://github.com/gui-cs/Terminal.Gui.git
synced 2025-12-26 15:57:56 +01:00
Addressed feedback #1
This commit is contained in:
@@ -35,7 +35,7 @@ dotnet run
|
||||
* [API Documentation](https://gui-cs.github.io/Terminal.GuiV2Docs/api/Terminal.Gui.html)
|
||||
* [Documentation Home](https://gui-cs.github.io/Terminal.GuiV2Docs)
|
||||
|
||||
The above documentation matches the most recent Nuget release from the `v2_develop` branch. Get the [v1 documentation here]( (This is the v2 API documentation. For v1 go here: https://gui-cs.github.io/Terminal.Gui/api/Terminal.Gui.html)
|
||||
The above documentation matches the most recent Nuget release from the `v2_develop` branch. Get the [v1 documentation here](This is the v2 API documentation. For v1 go here: https://gui-cs.github.io/Terminal.Gui/api/Terminal.Gui.html)
|
||||
|
||||
See the [`Terminal.Gui/` README](https://github.com/gui-cs/Terminal.Gui/tree/master/Terminal.Gui) for an overview of how the library is structured.
|
||||
|
||||
|
||||
@@ -1,45 +1,49 @@
|
||||
#nullable enable
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Terminal.Gui;
|
||||
|
||||
public static partial class Application // Keyboard handling
|
||||
{
|
||||
private static Key _nextTabGroupKey = Key.F6; // Resources/config.json overrrides
|
||||
private static Key _nextTabKey = Key.Tab; // Resources/config.json overrrides
|
||||
|
||||
/// <summary>Alternative key to navigate forwards through views. Ctrl+Tab is the primary key.</summary>
|
||||
[SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
|
||||
public static Key NextTabKey
|
||||
{
|
||||
get => _nextTabKey;
|
||||
set
|
||||
{
|
||||
if (_nextTabKey != value)
|
||||
{
|
||||
ReplaceKey (_nextTabKey, value);
|
||||
_nextTabKey = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
private static Key _prevTabGroupKey = Key.F6.WithShift; // Resources/config.json overrrides
|
||||
|
||||
private static Key _prevTabKey = Key.Tab.WithShift; // Resources/config.json overrrides
|
||||
|
||||
/// <summary>Alternative key to navigate backwards through views. Shift+Ctrl+Tab is the primary key.</summary>
|
||||
[SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
|
||||
public static Key PrevTabKey
|
||||
{
|
||||
get => _prevTabKey;
|
||||
set
|
||||
{
|
||||
if (_prevTabKey != value)
|
||||
{
|
||||
ReplaceKey (_prevTabKey, value);
|
||||
_prevTabKey = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
private static Key _quitKey = Key.Esc; // Resources/config.json overrrides
|
||||
|
||||
private static Key _nextTabGroupKey = Key.F6; // Resources/config.json overrrides
|
||||
static Application () { AddApplicationKeyBindings (); }
|
||||
|
||||
/// <summary>Gets the key bindings for this view.</summary>
|
||||
public static KeyBindings KeyBindings { get; internal set; } = new ();
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when the user presses a key. Fired by <see cref="OnKeyDown"/>.
|
||||
/// <para>
|
||||
/// Set <see cref="Key.Handled"/> to <see langword="true"/> to indicate the key was handled and to prevent
|
||||
/// additional processing.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// All drivers support firing the <see cref="KeyDown"/> event. Some drivers (Curses) do not support firing the
|
||||
/// <see cref="KeyDown"/> and <see cref="KeyUp"/> events.
|
||||
/// <para>Fired after <see cref="KeyDown"/> and before <see cref="KeyUp"/>.</para>
|
||||
/// </remarks>
|
||||
public static event EventHandler<Key>? KeyDown;
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when the user releases a key. Fired by <see cref="OnKeyUp"/>.
|
||||
/// <para>
|
||||
/// Set <see cref="Key.Handled"/> to <see langword="true"/> to indicate the key was handled and to prevent
|
||||
/// additional processing.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// All drivers support firing the <see cref="KeyDown"/> event. Some drivers (Curses) do not support firing the
|
||||
/// <see cref="KeyDown"/> and <see cref="KeyUp"/> events.
|
||||
/// <para>Fired after <see cref="KeyDown"/>.</para>
|
||||
/// </remarks>
|
||||
public static event EventHandler<Key>? KeyUp;
|
||||
|
||||
/// <summary>Alternative key to navigate forwards through views. Ctrl+Tab is the primary key.</summary>
|
||||
[SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
|
||||
@@ -56,71 +60,21 @@ public static partial class Application // Keyboard handling
|
||||
}
|
||||
}
|
||||
|
||||
private static Key _prevTabGroupKey = Key.F6.WithShift; // Resources/config.json overrrides
|
||||
|
||||
/// <summary>Alternative key to navigate backwards through views. Shift+Ctrl+Tab is the primary key.</summary>
|
||||
/// <summary>Alternative key to navigate forwards through views. Ctrl+Tab is the primary key.</summary>
|
||||
[SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
|
||||
public static Key PrevTabGroupKey
|
||||
public static Key NextTabKey
|
||||
{
|
||||
get => _prevTabGroupKey;
|
||||
get => _nextTabKey;
|
||||
set
|
||||
{
|
||||
if (_prevTabGroupKey != value)
|
||||
if (_nextTabKey != value)
|
||||
{
|
||||
ReplaceKey (_prevTabGroupKey, value);
|
||||
_prevTabGroupKey = value;
|
||||
ReplaceKey (_nextTabKey, value);
|
||||
_nextTabKey = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Key _quitKey = Key.Esc; // Resources/config.json overrrides
|
||||
|
||||
/// <summary>Gets or sets the key to quit the application.</summary>
|
||||
[SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
|
||||
public static Key QuitKey
|
||||
{
|
||||
get => _quitKey;
|
||||
set
|
||||
{
|
||||
if (_quitKey != value)
|
||||
{
|
||||
ReplaceKey (_quitKey, value);
|
||||
_quitKey = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ReplaceKey (Key oldKey, Key newKey)
|
||||
{
|
||||
if (KeyBindings.Bindings.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (newKey == Key.Empty)
|
||||
{
|
||||
KeyBindings.Remove (oldKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
KeyBindings.ReplaceKey (oldKey, newKey);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when the user presses a key. Fired by <see cref="OnKeyDown"/>.
|
||||
/// <para>
|
||||
/// Set <see cref="Key.Handled"/> to <see langword="true"/> to indicate the key was handled and to prevent
|
||||
/// additional processing.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// All drivers support firing the <see cref="KeyDown"/> event. Some drivers (Curses) do not support firing the
|
||||
/// <see cref="KeyDown"/> and <see cref="KeyUp"/> events.
|
||||
/// <para>Fired after <see cref="KeyDown"/> and before <see cref="KeyUp"/>.</para>
|
||||
/// </remarks>
|
||||
public static event EventHandler<Key>? KeyDown;
|
||||
|
||||
/// <summary>
|
||||
/// Called by the <see cref="ConsoleDriver"/> when the user presses a key. Fires the <see cref="KeyDown"/> event
|
||||
/// then calls <see cref="View.NewKeyDownEvent"/> on all top level views. Called after <see cref="OnKeyDown"/> and
|
||||
@@ -217,20 +171,6 @@ public static partial class Application // Keyboard handling
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event fired when the user releases a key. Fired by <see cref="OnKeyUp"/>.
|
||||
/// <para>
|
||||
/// Set <see cref="Key.Handled"/> to <see langword="true"/> to indicate the key was handled and to prevent
|
||||
/// additional processing.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// All drivers support firing the <see cref="KeyDown"/> event. Some drivers (Curses) do not support firing the
|
||||
/// <see cref="KeyDown"/> and <see cref="KeyUp"/> events.
|
||||
/// <para>Fired after <see cref="KeyDown"/>.</para>
|
||||
/// </remarks>
|
||||
public static event EventHandler<Key>? KeyUp;
|
||||
|
||||
/// <summary>
|
||||
/// Called by the <see cref="ConsoleDriver"/> when the user releases a key. Fires the <see cref="KeyUp"/> event
|
||||
/// then calls <see cref="View.NewKeyUpEvent"/> on all top level views. Called after <see cref="OnKeyDown"/>.
|
||||
@@ -268,33 +208,50 @@ public static partial class Application // Keyboard handling
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>Gets the key bindings for this view.</summary>
|
||||
public static KeyBindings KeyBindings { get; internal set; } = new ();
|
||||
/// <summary>Alternative key to navigate backwards through views. Shift+Ctrl+Tab is the primary key.</summary>
|
||||
[SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
|
||||
public static Key PrevTabGroupKey
|
||||
{
|
||||
get => _prevTabGroupKey;
|
||||
set
|
||||
{
|
||||
if (_prevTabGroupKey != value)
|
||||
{
|
||||
ReplaceKey (_prevTabGroupKey, value);
|
||||
_prevTabGroupKey = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Commands for Application.
|
||||
/// </summary>
|
||||
private static Dictionary<Command, Func<CommandContext, bool?>>? CommandImplementations { get; set; }
|
||||
/// <summary>Alternative key to navigate backwards through views. Shift+Ctrl+Tab is the primary key.</summary>
|
||||
[SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
|
||||
public static Key PrevTabKey
|
||||
{
|
||||
get => _prevTabKey;
|
||||
set
|
||||
{
|
||||
if (_prevTabKey != value)
|
||||
{
|
||||
ReplaceKey (_prevTabKey, value);
|
||||
_prevTabKey = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// Sets the function that will be invoked for a <see cref="Command"/>.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// If AddCommand has already been called for <paramref name="command"/> <paramref name="f"/> will
|
||||
/// replace the old one.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This version of AddCommand is for commands that do not require a <see cref="CommandContext"/>.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="command">The command.</param>
|
||||
/// <param name="f">The function.</param>
|
||||
private static void AddCommand (Command command, Func<bool?> f) { CommandImplementations! [command] = ctx => f (); }
|
||||
|
||||
static Application () { AddApplicationKeyBindings (); }
|
||||
/// <summary>Gets or sets the key to quit the application.</summary>
|
||||
[SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
|
||||
public static Key QuitKey
|
||||
{
|
||||
get => _quitKey;
|
||||
set
|
||||
{
|
||||
if (_quitKey != value)
|
||||
{
|
||||
ReplaceKey (_quitKey, value);
|
||||
_quitKey = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static void AddApplicationKeyBindings ()
|
||||
{
|
||||
@@ -303,7 +260,7 @@ public static partial class Application // Keyboard handling
|
||||
// Things this view knows how to do
|
||||
AddCommand (
|
||||
Command.QuitToplevel, // TODO: IRunnable: Rename to Command.Quit to make more generic.
|
||||
() =>
|
||||
static () =>
|
||||
{
|
||||
if (ApplicationOverlapped.OverlappedTop is { })
|
||||
{
|
||||
@@ -320,7 +277,7 @@ public static partial class Application // Keyboard handling
|
||||
|
||||
AddCommand (
|
||||
Command.Suspend,
|
||||
() =>
|
||||
static () =>
|
||||
{
|
||||
Driver?.Suspend ();
|
||||
|
||||
@@ -330,40 +287,22 @@ public static partial class Application // Keyboard handling
|
||||
|
||||
AddCommand (
|
||||
Command.NextView,
|
||||
() =>
|
||||
{
|
||||
View? current = Application.Current;
|
||||
if (current is { })
|
||||
{
|
||||
return current.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
static () => Current?.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabStop));
|
||||
|
||||
AddCommand (
|
||||
Command.PreviousView,
|
||||
() =>
|
||||
{
|
||||
View? current = Application.Current;
|
||||
if (current is { })
|
||||
{
|
||||
return current.AdvanceFocus (NavigationDirection.Backward, TabBehavior.TabStop);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
static () => Current?.AdvanceFocus (NavigationDirection.Backward, TabBehavior.TabStop));
|
||||
|
||||
AddCommand (
|
||||
Command.NextViewOrTop,
|
||||
() =>
|
||||
static () =>
|
||||
{
|
||||
// TODO: This OverlapppedTop tomfoolery goes away in addressing #2491
|
||||
if (ApplicationOverlapped.OverlappedTop is null)
|
||||
{
|
||||
View? current = Application.Current;
|
||||
if (current is { })
|
||||
if ((View?)Current is { })
|
||||
{
|
||||
return current.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabGroup);
|
||||
return Current.AdvanceFocus (NavigationDirection.Forward, TabBehavior.TabGroup);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -379,19 +318,19 @@ public static partial class Application // Keyboard handling
|
||||
|
||||
AddCommand (
|
||||
Command.PreviousViewOrTop,
|
||||
() =>
|
||||
static () =>
|
||||
{
|
||||
// TODO: This OverlapppedTop tomfoolery goes away in addressing #2491
|
||||
if (ApplicationOverlapped.OverlappedTop is null)
|
||||
{
|
||||
View? current = Application.Current;
|
||||
if (current is { })
|
||||
if ((View?)Current is { })
|
||||
{
|
||||
return current.AdvanceFocus (NavigationDirection.Backward, TabBehavior.TabGroup);
|
||||
return Current.AdvanceFocus (NavigationDirection.Backward, TabBehavior.TabGroup);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ApplicationOverlapped.OverlappedMovePrevious();
|
||||
ApplicationOverlapped.OverlappedMovePrevious ();
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -402,7 +341,7 @@ public static partial class Application // Keyboard handling
|
||||
|
||||
AddCommand (
|
||||
Command.Refresh,
|
||||
() =>
|
||||
static () =>
|
||||
{
|
||||
Refresh ();
|
||||
|
||||
@@ -464,4 +403,44 @@ public static partial class Application // Keyboard handling
|
||||
.Distinct ()
|
||||
.ToList ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <para>
|
||||
/// Sets the function that will be invoked for a <see cref="Command"/>.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// If AddCommand has already been called for <paramref name="command"/> <paramref name="f"/> will
|
||||
/// replace the old one.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This version of AddCommand is for commands that do not require a <see cref="CommandContext"/>.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="command">The command.</param>
|
||||
/// <param name="f">The function.</param>
|
||||
private static void AddCommand (Command command, Func<bool?> f) { CommandImplementations! [command] = ctx => f (); }
|
||||
|
||||
/// <summary>
|
||||
/// Commands for Application.
|
||||
/// </summary>
|
||||
private static Dictionary<Command, Func<CommandContext, bool?>>? CommandImplementations { get; set; }
|
||||
|
||||
private static void ReplaceKey (Key oldKey, Key newKey)
|
||||
{
|
||||
if (KeyBindings.Bindings.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (newKey == Key.Empty)
|
||||
{
|
||||
KeyBindings.Remove (oldKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
KeyBindings.ReplaceKey (oldKey, newKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,11 +19,13 @@ public class Adornments : Scenario
|
||||
var editor = new AdornmentsEditor
|
||||
{
|
||||
AutoSelectViewToEdit = true,
|
||||
|
||||
// This is for giggles, to show that the editor can be moved around.
|
||||
Arrangement = ViewArrangement.Movable,
|
||||
X = Pos.AnchorEnd(),
|
||||
X = Pos.AnchorEnd ()
|
||||
};
|
||||
editor.Border.Thickness = new Thickness (1, 2, 1, 1);
|
||||
|
||||
editor.Border.Thickness = new (1, 2, 1, 1);
|
||||
|
||||
app.Add (editor);
|
||||
|
||||
@@ -31,7 +33,8 @@ public class Adornments : Scenario
|
||||
{
|
||||
Title = "The _Window",
|
||||
Arrangement = ViewArrangement.Movable,
|
||||
// X = Pos.Center (),
|
||||
|
||||
// X = Pos.Center (),
|
||||
Width = Dim.Percent (60),
|
||||
Height = Dim.Percent (80)
|
||||
};
|
||||
@@ -127,9 +130,36 @@ public class Adornments : Scenario
|
||||
#endif
|
||||
};
|
||||
|
||||
Application.MouseEvent += ApplicationOnMouseEvent;
|
||||
|
||||
Application.Run (app);
|
||||
app.Dispose ();
|
||||
|
||||
Application.Shutdown ();
|
||||
|
||||
return;
|
||||
|
||||
void ApplicationOnMouseEvent (object sender, MouseEvent e)
|
||||
{
|
||||
if (!editor.AutoSelectViewToEdit || editor.FrameToScreen ().Contains (e.Position))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Add a setting (property) so only subviews of a specified view are considered.
|
||||
View view = e.View;
|
||||
|
||||
if (view is { } && e.Flags == MouseFlags.Button1Clicked)
|
||||
{
|
||||
if (view is Adornment adornment)
|
||||
{
|
||||
editor.ViewToEdit = adornment.Parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
editor.ViewToEdit = view;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,6 @@ public class AdornmentsEditor : View
|
||||
|
||||
TabStop = TabBehavior.TabGroup;
|
||||
|
||||
//Application.MouseEvent += Application_MouseEvent;
|
||||
Application.Navigation!.FocusedChanged += ApplicationNavigationOnFocusedChanged;
|
||||
Initialized += AdornmentsEditor_Initialized;
|
||||
}
|
||||
|
||||
@@ -155,35 +153,4 @@ public class AdornmentsEditor : View
|
||||
Add (_diagRulerCheckBox);
|
||||
_diagRulerCheckBox.Y = Pos.Bottom (_diagPaddingCheckBox);
|
||||
}
|
||||
|
||||
private void Application_MouseEvent (object sender, MouseEvent e)
|
||||
{
|
||||
if (!AutoSelectViewToEdit || FrameToScreen ().Contains (e.Position))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Add a setting (property) so only subviews of a specified view are considered.
|
||||
View view = e.View;
|
||||
|
||||
if (view is { } && e.Flags == MouseFlags.Button1Clicked)
|
||||
{
|
||||
if (view is Adornment adornment)
|
||||
{
|
||||
ViewToEdit = adornment.Parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
ViewToEdit = view;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplicationNavigationOnFocusedChanged (object sender, EventArgs e)
|
||||
{
|
||||
if (ApplicationNavigation.IsInHierarchy (this, Application.Navigation!.GetFocused ()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -407,8 +407,35 @@ public class ContentScrolling : Scenario
|
||||
|
||||
app.Closed += (s, e) => View.Diagnostics = _diagnosticFlags;
|
||||
|
||||
Application.MouseEvent += ApplicationOnMouseEvent;
|
||||
|
||||
Application.Run (app);
|
||||
app.Dispose ();
|
||||
Application.Shutdown ();
|
||||
|
||||
return;
|
||||
|
||||
void ApplicationOnMouseEvent (object sender, MouseEvent e)
|
||||
{
|
||||
if (!editor.AutoSelectViewToEdit || editor.FrameToScreen ().Contains (e.Position))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Add a setting (property) so only subviews of a specified view are considered.
|
||||
View view = e.View;
|
||||
|
||||
if (view is { } && e.Flags == MouseFlags.Button1Clicked)
|
||||
{
|
||||
if (view is Adornment adornment)
|
||||
{
|
||||
editor.ViewToEdit = adornment.Parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
editor.ViewToEdit = view;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
165
UICatalog/Scenarios/Navigation.cs
Normal file
165
UICatalog/Scenarios/Navigation.cs
Normal file
@@ -0,0 +1,165 @@
|
||||
using Terminal.Gui;
|
||||
|
||||
namespace UICatalog.Scenarios;
|
||||
|
||||
[ScenarioMetadata ("Navigation", "Navigation Tester")]
|
||||
[ScenarioCategory ("Mouse and Keyboard")]
|
||||
[ScenarioCategory ("Layout")]
|
||||
public class Navigation : Scenario
|
||||
{
|
||||
public override void Main ()
|
||||
{
|
||||
Application.Init ();
|
||||
|
||||
Window app = new ()
|
||||
{
|
||||
Title = GetQuitKeyAndName (),
|
||||
TabStop = TabBehavior.TabGroup
|
||||
};
|
||||
|
||||
var editor = new AdornmentsEditor
|
||||
{
|
||||
X = 0,
|
||||
Y = 0,
|
||||
AutoSelectViewToEdit = true,
|
||||
TabStop = TabBehavior.NoStop
|
||||
};
|
||||
app.Add (editor);
|
||||
|
||||
FrameView testFrame = new ()
|
||||
{
|
||||
Title = "_1 Test Frame",
|
||||
X = Pos.Right (editor),
|
||||
Width = Dim.Fill (),
|
||||
Height = Dim.Fill (),
|
||||
};
|
||||
|
||||
app.Add (testFrame);
|
||||
|
||||
Button button = new ()
|
||||
{
|
||||
X = 0,
|
||||
Y = 0,
|
||||
Title = $"TopButton _{GetNextHotKey ()}",
|
||||
};
|
||||
|
||||
testFrame.Add (button);
|
||||
|
||||
var tiledView1 = CreateTiledView (0, 2, 2);
|
||||
var tiledView2 = CreateTiledView (1, Pos.Right (tiledView1), Pos.Top (tiledView1));
|
||||
|
||||
testFrame.Add (tiledView1);
|
||||
testFrame.Add (tiledView2);
|
||||
|
||||
var tiledView3 = CreateTiledView (1, Pos.Right (tiledView2), Pos.Top (tiledView2));
|
||||
tiledView3.TabStop = TabBehavior.TabGroup;
|
||||
tiledView3.BorderStyle = LineStyle.Double;
|
||||
testFrame.Add (tiledView3);
|
||||
|
||||
var overlappedView1 = CreateOverlappedView (2, Pos.Center () - 5, Pos.Center ());
|
||||
var tiledSubView = CreateTiledView (4, 0, 2);
|
||||
overlappedView1.Add (tiledSubView);
|
||||
|
||||
var overlappedView2 = CreateOverlappedView (3, Pos.Center () + 10, Pos.Center () + 5);
|
||||
|
||||
// BUGBUG: F6 through nested tab groups doesn't work yet.
|
||||
#if NESTED_TABGROUPS
|
||||
var overlappedInOverlapped1 = CreateOverlappedView (4, 1, 4);
|
||||
overlappedView2.Add (overlappedInOverlapped1);
|
||||
|
||||
var overlappedInOverlapped2 = CreateOverlappedView (5, 10, 7);
|
||||
overlappedView2.Add (overlappedInOverlapped2);
|
||||
|
||||
#endif
|
||||
|
||||
testFrame.Add (overlappedView1);
|
||||
testFrame.Add (overlappedView2);
|
||||
|
||||
button = new ()
|
||||
{
|
||||
X = Pos.AnchorEnd (),
|
||||
Y = Pos.AnchorEnd (),
|
||||
Title = $"TopButton _{GetNextHotKey ()}",
|
||||
};
|
||||
|
||||
testFrame.Add (button);
|
||||
|
||||
Application.Run (app);
|
||||
app.Dispose ();
|
||||
Application.Shutdown ();
|
||||
}
|
||||
|
||||
private int _hotkeyCount;
|
||||
|
||||
private char GetNextHotKey ()
|
||||
{
|
||||
return (char)((int)'A' + _hotkeyCount++);
|
||||
}
|
||||
|
||||
private View CreateTiledView (int id, Pos x, Pos y)
|
||||
{
|
||||
View overlapped = new View
|
||||
{
|
||||
X = x,
|
||||
Y = y,
|
||||
Height = Dim.Auto (),
|
||||
Width = Dim.Auto (),
|
||||
Title = $"Tiled{id} _{GetNextHotKey ()}",
|
||||
Id = $"Tiled{id}",
|
||||
BorderStyle = LineStyle.Single,
|
||||
CanFocus = true, // Can't drag without this? BUGBUG
|
||||
TabStop = TabBehavior.TabStop,
|
||||
Arrangement = ViewArrangement.Fixed
|
||||
};
|
||||
|
||||
Button button = new ()
|
||||
{
|
||||
Title = $"Tiled Button{id} _{GetNextHotKey ()}"
|
||||
};
|
||||
overlapped.Add (button);
|
||||
|
||||
button = new ()
|
||||
{
|
||||
Y = Pos.Bottom (button),
|
||||
Title = $"Tiled Button{id} _{GetNextHotKey ()}"
|
||||
};
|
||||
overlapped.Add (button);
|
||||
|
||||
return overlapped;
|
||||
}
|
||||
|
||||
|
||||
private View CreateOverlappedView (int id, Pos x, Pos y)
|
||||
{
|
||||
View overlapped = new View
|
||||
{
|
||||
X = x,
|
||||
Y = y,
|
||||
Height = Dim.Auto (),
|
||||
Width = Dim.Auto (),
|
||||
Title = $"Overlapped{id} _{GetNextHotKey ()}",
|
||||
ColorScheme = Colors.ColorSchemes ["Toplevel"],
|
||||
Id = $"Overlapped{id}",
|
||||
ShadowStyle = ShadowStyle.Transparent,
|
||||
BorderStyle = LineStyle.Double,
|
||||
CanFocus = true, // Can't drag without this? BUGBUG
|
||||
TabStop = TabBehavior.TabGroup,
|
||||
Arrangement = ViewArrangement.Movable | ViewArrangement.Overlapped
|
||||
};
|
||||
|
||||
Button button = new ()
|
||||
{
|
||||
Title = $"Button{id} _{GetNextHotKey ()}"
|
||||
};
|
||||
overlapped.Add (button);
|
||||
|
||||
button = new ()
|
||||
{
|
||||
Y = Pos.Bottom (button),
|
||||
Title = $"Button{id} _{GetNextHotKey ()}"
|
||||
};
|
||||
overlapped.Add (button);
|
||||
|
||||
return overlapped;
|
||||
}
|
||||
}
|
||||
@@ -55,11 +55,36 @@ public class ShadowStyles : Scenario
|
||||
};
|
||||
app.Add (button);
|
||||
|
||||
Application.MouseEvent += ApplicationOnMouseEvent;
|
||||
|
||||
Application.Run (app);
|
||||
app.Dispose ();
|
||||
|
||||
Application.Shutdown ();
|
||||
|
||||
return;
|
||||
|
||||
void ApplicationOnMouseEvent (object sender, MouseEvent e)
|
||||
{
|
||||
if (!editor.AutoSelectViewToEdit || editor.FrameToScreen ().Contains (e.Position))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Add a setting (property) so only subviews of a specified view are considered.
|
||||
View view = e.View;
|
||||
|
||||
if (view is { } && e.Flags == MouseFlags.Button1Clicked)
|
||||
{
|
||||
if (view is Adornment adornment)
|
||||
{
|
||||
editor.ViewToEdit = adornment.Parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
editor.ViewToEdit = view;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Terminal.Gui;
|
||||
using System;
|
||||
using Terminal.Gui;
|
||||
|
||||
namespace UICatalog.Scenarios;
|
||||
|
||||
@@ -47,36 +48,6 @@ public class ViewExperiments : Scenario
|
||||
|
||||
testFrame.Add (button);
|
||||
|
||||
var tiledView1 = CreateTiledView (0, 2, 2);
|
||||
var tiledView2 = CreateTiledView (1, Pos.Right (tiledView1), Pos.Top (tiledView1));
|
||||
|
||||
testFrame.Add (tiledView1);
|
||||
testFrame.Add (tiledView2);
|
||||
|
||||
var tiledView3 = CreateTiledView (1, Pos.Right (tiledView2), Pos.Top (tiledView2));
|
||||
tiledView3.TabStop = TabBehavior.TabGroup;
|
||||
tiledView3.BorderStyle = LineStyle.Double;
|
||||
testFrame.Add (tiledView3);
|
||||
|
||||
var overlappedView1 = CreateOverlappedView (2, Pos.Center () - 5, Pos.Center ());
|
||||
var tiledSubView = CreateTiledView (4, 0, 2);
|
||||
overlappedView1.Add (tiledSubView);
|
||||
|
||||
var overlappedView2 = CreateOverlappedView (3, Pos.Center () + 10, Pos.Center () + 5);
|
||||
|
||||
// BUGBUG: F6 through nested tab groups doesn't work yet.
|
||||
#if NESTED_TABGROUPS
|
||||
var overlappedInOverlapped1 = CreateOverlappedView (4, 1, 4);
|
||||
overlappedView2.Add (overlappedInOverlapped1);
|
||||
|
||||
var overlappedInOverlapped2 = CreateOverlappedView (5, 10, 7);
|
||||
overlappedView2.Add (overlappedInOverlapped2);
|
||||
|
||||
#endif
|
||||
|
||||
testFrame.Add (overlappedView1);
|
||||
testFrame.Add (overlappedView2);
|
||||
|
||||
button = new ()
|
||||
{
|
||||
X = Pos.AnchorEnd (),
|
||||
@@ -85,10 +56,54 @@ public class ViewExperiments : Scenario
|
||||
};
|
||||
|
||||
testFrame.Add (button);
|
||||
Application.MouseEvent += ApplicationOnMouseEvent;
|
||||
Application.Navigation.FocusedChanged += NavigationOnFocusedChanged;
|
||||
|
||||
|
||||
Application.Run (app);
|
||||
app.Dispose ();
|
||||
|
||||
Application.Shutdown ();
|
||||
|
||||
return;
|
||||
|
||||
|
||||
void NavigationOnFocusedChanged (object sender, EventArgs e)
|
||||
{
|
||||
if (!ApplicationNavigation.IsInHierarchy (testFrame, Application.Navigation!.GetFocused ()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
editor.ViewToEdit = Application.Navigation!.GetFocused ();
|
||||
}
|
||||
void ApplicationOnMouseEvent (object sender, MouseEvent e)
|
||||
{
|
||||
if (e.Flags != MouseFlags.Button1Clicked)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!editor.AutoSelectViewToEdit || !testFrame.FrameToScreen ().Contains (e.Position))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Add a setting (property) so only subviews of a specified view are considered.
|
||||
View view = e.View;
|
||||
|
||||
if (view is { } && e.Flags == MouseFlags.Button1Clicked)
|
||||
{
|
||||
if (view is Adornment adornment)
|
||||
{
|
||||
editor.ViewToEdit = adornment.Parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
editor.ViewToEdit = view;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int _hotkeyCount;
|
||||
@@ -110,7 +125,7 @@ public class ViewExperiments : Scenario
|
||||
Id = $"Tiled{id}",
|
||||
BorderStyle = LineStyle.Single,
|
||||
CanFocus = true, // Can't drag without this? BUGBUG
|
||||
TabStop = TabBehavior.TabStop,
|
||||
TabStop = TabBehavior.TabGroup,
|
||||
Arrangement = ViewArrangement.Fixed
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user