Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #3764. Makes common UI interactions consistent across built-in Views #3766

Merged
merged 75 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
700d869
Initial commit
tig Sep 29, 2024
8add6e0
RadioGroup
tig Sep 29, 2024
3b256f2
RadioGroup
tig Sep 29, 2024
8fbbba7
ListView
tig Sep 29, 2024
1d633c2
Refactored View command handling
tig Sep 30, 2024
66edb36
Fixed RadioGroup
tig Sep 30, 2024
f3b93a5
Fixed RadioGroup 2
tig Oct 1, 2024
40ee4c0
Fixed CheckBox
tig Oct 2, 2024
f860b17
Checkbox and RadioGroup mouse
tig Oct 2, 2024
878412e
Refactored Command.Accept
tig Oct 2, 2024
b5df0a1
Fixed Checkbox race condition
tig Oct 2, 2024
a5da3cd
Fixed TextView and IsDefault
tig Oct 2, 2024
a33ef5a
Fixed TextView
tig Oct 2, 2024
1cfe81a
Fixed Dialog/MessageBox tests
tig Oct 2, 2024
ee49337
Fixed ComboBox.
tig Oct 2, 2024
c6b8843
navigation.md
tig Oct 2, 2024
46c50ab
API docs.
tig Oct 2, 2024
a38a96a
Label API docs
tig Oct 2, 2024
4ce6d86
RadioGroup API docs
tig Oct 2, 2024
f81c86e
Made Text Scenario show Accept
tig Oct 2, 2024
7109a81
Disabled unix key bindings for TextView
tig Oct 2, 2024
4826704
API docs
tig Oct 2, 2024
1ab70e6
Merge branch 'v2_develop' into v2_3764-Common-Events
tig Oct 2, 2024
8cec593
Disabled unix key bindings for TextView. Unit test fix
tig Oct 2, 2024
fab5cc9
Disabled unix key bindings for TextView. Unit test fix 2
tig Oct 2, 2024
a809356
Disabled unix key bindings for TextView. Unit test fix 3
tig Oct 2, 2024
ac42da9
Manual backport from popover
tig Oct 3, 2024
1e19e95
Thinking through Adornments (again)
tig Oct 3, 2024
3649a04
Re-fixed
tig Oct 5, 2024
af110d9
In the middle of another refactoroing
tig Oct 5, 2024
6adeec6
More refactoring. Still WIP
tig Oct 5, 2024
68e8866
HexEditor - it was already broken!
tig Oct 6, 2024
923e5d1
Fixed ScreenPosition in tests
tig Oct 6, 2024
ce126b6
Fixed ScreenPosition in tests - MenuBar tests broke
tig Oct 6, 2024
d2bad30
Fixed MenuBar
tig Oct 6, 2024
3c3b4f8
Fixed Application tests
tig Oct 6, 2024
44259cc
Fixed HexView nav unit test
tig Oct 6, 2024
f2d27a5
Working on ComboBox
tig Oct 6, 2024
f5f850b
Fixed combobox
tig Oct 6, 2024
089059a
All unit test pass
tig Oct 6, 2024
58c1d59
Code cleanup
tig Oct 6, 2024
39bf844
Added more unit tests
tig Oct 6, 2024
c4e8ec4
All unit test pass for reals?
tig Oct 7, 2024
a7e166e
Shortcut code cleanup
tig Oct 7, 2024
33f4277
FileDialog code cleanup
tig Oct 7, 2024
f05f4cb
Slider code cleanup
tig Oct 7, 2024
9a51d07
Checkbox code cleanup
tig Oct 7, 2024
9dd0be3
Shortcut code cleanup
tig Oct 7, 2024
5b0ca95
Fixed checkbox issue
tig Oct 7, 2024
2a989df
Selected->Selecting
tig Oct 7, 2024
fc34585
Selected->Selecting
tig Oct 7, 2024
68b1e6f
Selected->Selecting
tig Oct 7, 2024
bb7e428
HotKeyHandled->HandlingHotKey
tig Oct 7, 2024
018dbc6
Accepted now takes CommandEventArgs
tig Oct 7, 2024
97684e4
api docs
tig Oct 7, 2024
78d0a8f
Accepted->Accepting
tig Oct 7, 2024
0bac3c9
Merge branch 'v2_develop' into v2_3764-Common-Events
tig Oct 7, 2024
b6e4e88
Merge branch 'v2_3764-Common-Events' of tig:tig/Terminal.Gui into v2_…
tig Oct 7, 2024
db22d10
Conceptual docs
tig Oct 7, 2024
1c226c7
Updated Generic
tig Oct 7, 2024
2b48337
Updated Generic
tig Oct 7, 2024
5006e00
Fixed TextView not handling space
tig Oct 7, 2024
eee6099
Bdisp feedback fixes
tig Oct 8, 2024
4410b54
Bdisp feedback fixes 2
tig Oct 8, 2024
b2049d8
Fixed Dialog & Messagebox
tig Oct 8, 2024
dc4ce1e
Fixed Dialogs
tig Oct 8, 2024
9e658ee
Command API doc and code clenaup
tig Oct 8, 2024
0b35303
Fixed Theme bugs
tig Oct 8, 2024
3408c41
Fixed Theme bugs 2
tig Oct 8, 2024
a349af0
Fixed #3781
tig Oct 8, 2024
cf772f8
Messed with some stuff. Probably broke some stuff.
tig Oct 8, 2024
14e2391
Fixed toplevel unit tests
tig Oct 8, 2024
7630b35
Fixed more menubar/statusbar
tig Oct 9, 2024
fd97867
Fixed more menubar/statusbar
tig Oct 9, 2024
2970e55
Mouse unit test diag
tig Oct 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CommunityToolkitExample/LoginView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ public LoginView (LoginViewModel viewModel)
{
ViewModel.Password = passwordInput.Text;
};
loginButton.Accept += (_, _) =>
loginButton.Accepting += (_, _) =>
tig marked this conversation as resolved.
Show resolved Hide resolved
{
if (!ViewModel.CanLogin) { return; }
ViewModel.LoginCommand.Execute (null);
};

clearButton.Accept += (_, _) =>
clearButton.Accepting += (_, _) =>
{
ViewModel.ClearCommand.Execute (null);
};
Expand Down
2 changes: 1 addition & 1 deletion Example/Example.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public ExampleWindow ()
};

// When login button is clicked display a message popup
btnLogin.Accept += (s, e) =>
btnLogin.Accepting += (s, e) =>
{
if (userNameText.Text == "admin" && passwordText.Text == "password")
{
Expand Down
2 changes: 1 addition & 1 deletion NativeAot/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@
};

// When login button is clicked display a message popup
btnLogin.Accept += (s, e) =>
btnLogin.Accepting += (s, e) =>

Check failure on line 96 in NativeAot/Program.cs

View workflow job for this annotation

GitHub Actions / build_release

'Button' does not contain a definition for 'Accepting' and no accessible extension method 'Accepting' accepting a first argument of type 'Button' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 96 in NativeAot/Program.cs

View workflow job for this annotation

GitHub Actions / build_release

'Button' does not contain a definition for 'Accepting' and no accessible extension method 'Accepting' accepting a first argument of type 'Button' could be found (are you missing a using directive or an assembly reference?)
{
if (userNameText.Text == "admin" && passwordText.Text == "password")
{
Expand Down
4 changes: 2 additions & 2 deletions ReactiveExample/LoginView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public LoginView (LoginViewModel viewModel)

login
.Events ()
.Accept
.Accepting
.InvokeCommand (ViewModel, x => x.Login)
.DisposeWith (_disposable);
})
Expand All @@ -120,7 +120,7 @@ public LoginView (LoginViewModel viewModel)

clear
.Events ()
.Accept
.Accepting
.InvokeCommand (ViewModel, x => x.ClearCommand)
.DisposeWith (_disposable);
})
Expand Down
2 changes: 1 addition & 1 deletion SelfContained/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
};

// When login button is clicked display a message popup
btnLogin.Accept += (s, e) =>
btnLogin.Accepting += (s, e) =>

Check failure on line 95 in SelfContained/Program.cs

View workflow job for this annotation

GitHub Actions / build_release

'Button' does not contain a definition for 'Accepting' and no accessible extension method 'Accepting' accepting a first argument of type 'Button' could be found (are you missing a using directive or an assembly reference?)

Check failure on line 95 in SelfContained/Program.cs

View workflow job for this annotation

GitHub Actions / build_release

'Button' does not contain a definition for 'Accepting' and no accessible extension method 'Accepting' accepting a first argument of type 'Button' could be found (are you missing a using directive or an assembly reference?)
{
if (userNameText.Text == "admin" && passwordText.Text == "password")
{
Expand Down
16 changes: 16 additions & 0 deletions Terminal.Gui/Application/Application.Initialization.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#nullable enable
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;

Expand Down Expand Up @@ -80,6 +81,16 @@ internal static void InternalInit (
if (driver is { })
{
Driver = driver;

if (driver is FakeDriver)
{
// We're running unit tests. Disable loading config files other than default
if (Locations == ConfigLocations.All)
{
Locations = ConfigLocations.DefaultOnly;
Reset ();
}
}
}

// Start the process of configuration management.
Expand All @@ -88,7 +99,12 @@ internal static void InternalInit (
// valid after a Driver is loaded. In this case we need just
// `Settings` so we can determine which driver to use.
// Don't reset, so we can inherit the theme from the previous run.
string previousTheme = Themes?.Theme ?? string.Empty;
Load ();
if (Themes is { } && !string.IsNullOrEmpty (previousTheme) && previousTheme != "Default")
{
ThemeManager.SelectedTheme = previousTheme;
}
Apply ();

AddApplicationKeyBindings ();
Expand Down
4 changes: 2 additions & 2 deletions Terminal.Gui/Application/Application.Keyboard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ public static bool OnKeyDown (Key keyEvent)
);
}

if (CommandImplementations.TryGetValue (command, out Func<CommandContext, bool?>? implementation))
if (CommandImplementations.TryGetValue (command, out View.CommandImplementation? implementation))
{
var context = new CommandContext (command, keyEvent, appBinding); // Create the context here

Expand Down Expand Up @@ -418,7 +418,7 @@ internal static List<KeyBinding> GetViewKeyBindings ()
/// <summary>
/// Commands for Application.
/// </summary>
private static Dictionary<Command, Func<CommandContext, bool?>>? CommandImplementations { get; set; }
private static Dictionary<Command, View.CommandImplementation>? CommandImplementations { get; set; }

private static void ReplaceKey (Key oldKey, Key newKey)
{
Expand Down
60 changes: 39 additions & 21 deletions Terminal.Gui/Application/Application.Mouse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ namespace Terminal.Gui;

public static partial class Application // Mouse handling
{
internal static Point? _lastMousePosition;

/// <summary>
/// Gets the most recent position of the mouse.
/// </summary>
public static Point? GetLastMousePosition () { return _lastMousePosition; }

/// <summary>Disable or enable the mouse. The mouse is enabled by default.</summary>
[SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
public static bool IsMouseDisabled { get; set; }
Expand Down Expand Up @@ -132,12 +139,18 @@ private static void OnUnGrabbedMouse (View? view)
/// <param name="mouseEvent">The mouse event with coordinates relative to the screen.</param>
internal static void OnMouseEvent (MouseEvent mouseEvent)
{
_lastMousePosition = mouseEvent.ScreenPosition;

if (IsMouseDisabled)
{
return;
}

List<View?> currentViewsUnderMouse = View.GetViewsUnderMouse (mouseEvent.Position);
// The position of the mouse is the same as the screen position at the application level.
//Debug.Assert (mouseEvent.Position == mouseEvent.ScreenPosition);
mouseEvent.Position = mouseEvent.ScreenPosition;

List<View?> currentViewsUnderMouse = View.GetViewsUnderMouse (mouseEvent.ScreenPosition);

View? deepestViewUnderMouse = currentViewsUnderMouse.LastOrDefault ();

Expand All @@ -159,7 +172,7 @@ internal static void OnMouseEvent (MouseEvent mouseEvent)
return;
}

if (GrabMouse (deepestViewUnderMouse, mouseEvent))
if (HandleMouseGrab (deepestViewUnderMouse, mouseEvent))
{
return;
}
Expand All @@ -180,44 +193,47 @@ internal static void OnMouseEvent (MouseEvent mouseEvent)
return;
}

// TODO: Move this after call to RaiseMouseEnterLeaveEvents once MouseEnter/Leave don't use MouseEvent anymore.
MouseEvent? me;
// Create a view-relative mouse event to send to the view that is under the mouse.
MouseEvent? viewMouseEvent;

if (deepestViewUnderMouse is Adornment adornment)
{
Point frameLoc = adornment.ScreenToFrame (mouseEvent.Position);
Point frameLoc = adornment.ScreenToFrame (mouseEvent.ScreenPosition);

me = new ()
viewMouseEvent = new ()
{
Position = frameLoc,
Flags = mouseEvent.Flags,
ScreenPosition = mouseEvent.Position,
ScreenPosition = mouseEvent.ScreenPosition,
View = deepestViewUnderMouse
};
}
else if (deepestViewUnderMouse.ViewportToScreen (Rectangle.Empty with { Size = deepestViewUnderMouse.Viewport.Size }).Contains (mouseEvent.Position))
{
Point viewportLocation = deepestViewUnderMouse.ScreenToViewport (mouseEvent.Position);
Point viewportLocation = deepestViewUnderMouse.ScreenToViewport (mouseEvent.ScreenPosition);

me = new ()
viewMouseEvent = new ()
{
Position = viewportLocation,
Flags = mouseEvent.Flags,
ScreenPosition = mouseEvent.Position,
ScreenPosition = mouseEvent.ScreenPosition,
View = deepestViewUnderMouse
};
}
else
{
Debug.Fail ("This should never happen");
// The mouse was outside any View's Viewport.

// Debug.Fail ("This should never happen. If it does please file an Issue!!");

return;
}

RaiseMouseEnterLeaveEvents (me.ScreenPosition, currentViewsUnderMouse);
RaiseMouseEnterLeaveEvents (viewMouseEvent.ScreenPosition, currentViewsUnderMouse);

WantContinuousButtonPressedView = deepestViewUnderMouse.WantContinuousButtonPressed ? deepestViewUnderMouse : null;

while (deepestViewUnderMouse.NewMouseEvent (me) is not true && MouseGrabView is not { })
while (deepestViewUnderMouse.NewMouseEvent (viewMouseEvent) is not true && MouseGrabView is not { })
{
if (deepestViewUnderMouse is Adornment adornmentView)
{
Expand All @@ -233,38 +249,38 @@ internal static void OnMouseEvent (MouseEvent mouseEvent)
break;
}

Point boundsPoint = deepestViewUnderMouse.ScreenToViewport (mouseEvent.Position);
Point boundsPoint = deepestViewUnderMouse.ScreenToViewport (mouseEvent.ScreenPosition);

me = new ()
viewMouseEvent = new ()
{
Position = boundsPoint,
Flags = mouseEvent.Flags,
ScreenPosition = mouseEvent.Position,
ScreenPosition = mouseEvent.ScreenPosition,
View = deepestViewUnderMouse
};
}
}

internal static bool GrabMouse (View? deepestViewUnderMouse, MouseEvent mouseEvent)
internal static bool HandleMouseGrab (View? deepestViewUnderMouse, MouseEvent mouseEvent)
{
if (MouseGrabView is { })
{

#if DEBUG_IDISPOSABLE
if (MouseGrabView.WasDisposed)
{
throw new ObjectDisposedException (MouseGrabView.GetType ().FullName);
}
#endif

// If the mouse is grabbed, send the event to the view that grabbed it.
// The coordinates are relative to the Bounds of the view that grabbed the mouse.
Point frameLoc = MouseGrabView.ScreenToViewport (mouseEvent.Position);
Point frameLoc = MouseGrabView.ScreenToViewport (mouseEvent.ScreenPosition);

var viewRelativeMouseEvent = new MouseEvent
{
Position = frameLoc,
Flags = mouseEvent.Flags,
ScreenPosition = mouseEvent.Position,
ScreenPosition = mouseEvent.ScreenPosition,
View = deepestViewUnderMouse ?? MouseGrabView
};

Expand Down Expand Up @@ -297,6 +313,7 @@ internal static void RaiseMouseEnterLeaveEvents (Point screenPosition, List<View
{
// Tell any views that are no longer under the mouse that the mouse has left
List<View?> viewsToLeave = _cachedViewsUnderMouse.Where (v => v is { } && !currentViewsUnderMouse.Contains (v)).ToList ();

foreach (View? view in viewsToLeave)
{
if (view is null)
Expand All @@ -322,7 +339,8 @@ internal static void RaiseMouseEnterLeaveEvents (Point screenPosition, List<View
}

_cachedViewsUnderMouse.Add (view);
bool raise = false;
var raise = false;

if (view is Adornment { Parent: { } } adornmentView)
{
Point superViewLoc = adornmentView.Parent.SuperView?.ScreenToViewport (screenPosition) ?? screenPosition;
Expand Down
3 changes: 1 addition & 2 deletions Terminal.Gui/Application/Application.cs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ internal static void ResetState (bool ignoreDisposed = false)
IsInitialized = false;

// Mouse
_lastMousePosition = null;
_cachedViewsUnderMouse.Clear ();
WantContinuousButtonPressedView = null;
MouseEvent = null;
Expand All @@ -214,8 +215,6 @@ internal static void ResetState (bool ignoreDisposed = false)

AddApplicationKeyBindings ();

Colors.Reset ();

// Reset synchronization context to allow the user to run async/await,
// as the main loop has been ended, the synchronization context from
// gui.cs does no longer process any callbacks. See #1084 for more details:
Expand Down
17 changes: 13 additions & 4 deletions Terminal.Gui/Configuration/ConfigurationManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -197,10 +197,19 @@ public static void Apply ()

try
{
settings = Settings?.Apply () ?? false;

themes = !string.IsNullOrEmpty (ThemeManager.SelectedTheme)
&& (ThemeManager.Themes? [ThemeManager.SelectedTheme]?.Apply () ?? false);
if (string.IsNullOrEmpty (ThemeManager.SelectedTheme))
{
// First start. Apply settings first. This ensures if a config sets Theme to something other than "Default", it gets used
settings = Settings?.Apply () ?? false;
themes = !string.IsNullOrEmpty (ThemeManager.SelectedTheme)
&& (ThemeManager.Themes? [ThemeManager.SelectedTheme]?.Apply () ?? false);
}
else
{
// Subsequently. Apply Themes first using whatever the SelectedTheme is
themes = ThemeManager.Themes? [ThemeManager.SelectedTheme]?.Apply () ?? false;
settings = Settings?.Apply () ?? false;
}
appSettings = AppSettings?.Apply () ?? false;
}
catch (JsonException e)
Expand Down
2 changes: 1 addition & 1 deletion Terminal.Gui/Configuration/ThemeManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ internal static string SelectedTheme
string oldTheme = _theme;
_theme = value;

if (oldTheme != _theme && Settings! ["Themes"]?.PropertyValue is Dictionary<string, ThemeScope> themes && themes.ContainsKey (_theme))
if ((oldTheme != _theme || oldTheme != Settings! ["Theme"].PropertyValue as string) && Settings! ["Themes"]?.PropertyValue is Dictionary<string, ThemeScope> themes && themes.ContainsKey (_theme))
{
Settings! ["Theme"].PropertyValue = _theme;
Instance.OnThemeChanged (oldTheme);
Expand Down
2 changes: 2 additions & 0 deletions Terminal.Gui/ConsoleDrivers/WindowsDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ public WindowsConsole ()

public bool WriteToConsole (Size size, ExtendedCharInfo [] charInfoBuffer, Coord bufferSize, SmallRect window, bool force16Colors)
{
//Debug.WriteLine ("WriteToConsole");

if (_screenBuffer == nint.Zero)
{
ReadFromConsoleOutput (size, bufferSize, ref window);
Expand Down
4 changes: 2 additions & 2 deletions Terminal.Gui/FileServices/DefaultFileOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,14 +135,14 @@ private bool Prompt (string title, string defaultText, out string result)
var confirm = false;
var btnOk = new Button { IsDefault = true, Text = Strings.btnOk };

btnOk.Accept += (s, e) =>
btnOk.Accepting += (s, e) =>
{
confirm = true;
Application.RequestStop ();
};
var btnCancel = new Button { Text = Strings.btnCancel };

btnCancel.Accept += (s, e) =>
btnCancel.Accepting += (s, e) =>
{
confirm = false;
Application.RequestStop ();
Expand Down
Loading
Loading