Skip to content
Merged
Show file tree
Hide file tree
Changes from 128 commits
Commits
Show all changes
135 commits
Select commit Hold shift + click to select a range
f314848
Added Applicaton.Popover.
tig Sep 19, 2024
4073e23
Popover prototype
tig Sep 19, 2024
fd632e3
Merge branch 'v2_develop' into v2_3691-Popover
tig Sep 19, 2024
4da7f48
Merged v2_3750
tig Sep 22, 2024
9f84b3a
Testing highlight
tig Sep 22, 2024
aa5cf82
Merged latest
tig Sep 22, 2024
9222972
Merge branch 'v2_3750-MouseEnter' into v2_3691-Popover
tig Sep 23, 2024
f589416
Fixed click outside issue
tig Sep 23, 2024
5d1d6cb
Fixed DialogTests
tig Sep 23, 2024
c623206
Fixed click outside issue (agbain)
tig Sep 23, 2024
e2a4620
Enabled mouse wheel in Bar
tig Sep 23, 2024
7b7649a
Enabled mouse wheel in Bar
tig Sep 23, 2024
bfefabc
Progress. Broke arrangement
tig Sep 23, 2024
7346afb
Merge branch 'v2_develop' into v2_3691-Popover
tig Sep 24, 2024
ec847a3
Rebased onto v2_3750-MouseEnter
tig Sep 24, 2024
850c308
Merge branch 'v2_develop' into v2_3691-Popover
tig Sep 26, 2024
3e8ed7a
Added popover tests.
tig Sep 26, 2024
1369bb2
Can't set ForceDriver to empty in Resources/config.json.
tig Sep 26, 2024
3aa3598
added BUGBUG
tig Sep 26, 2024
ae4b172
Made Position/ScreenPosition clear
tig Sep 26, 2024
4e6bf04
Added View.IsInHierarchy tests
tig Sep 26, 2024
a5044df
Added Contextmenuv2 scenario.
tig Sep 26, 2024
06bcefe
Implemented CM2 in TextView
tig Sep 26, 2024
a708648
Removed unneeded CM stuff from testhelpers
tig Sep 26, 2024
d888de8
Shortcut API docs
tig Sep 26, 2024
8954fec
Fixed keybinding unit tests
tig Sep 27, 2024
47a9ef7
Fixed mouse handling
tig Sep 27, 2024
23c3ec8
Fighting with CM related unit test failures
tig Sep 27, 2024
493ece7
Unit tests pass. I think.
tig Sep 27, 2024
16e7689
Shortcut code cleanup
tig Sep 27, 2024
5d9e0d1
TextView uses new CM2
tig Sep 27, 2024
fb85d44
Starting on OnSelect etc...
tig Sep 28, 2024
bdc947e
Starting on OnSelect etc...
tig Sep 28, 2024
8b54152
Merge branch 'v2_develop' into v2_3691-Popover
tig Oct 2, 2024
6800168
Merged and debugged and mostly fixed stuff.
tig Oct 3, 2024
5d67850
Merge branch 'v2_develop' into v2_3691-Popover
tig Oct 7, 2024
be46664
Merged - builds
tig Oct 7, 2024
a68dec2
Fixed ContextMenuv2
tig Oct 7, 2024
040f73a
Merge branch 'v2_3691-Popover' of tig:tig/Terminal.Gui into v2_3691-P…
tig Oct 7, 2024
8346348
ContextMenu is working again.
tig Oct 8, 2024
22dc075
Ugh. ANd fixed button api docs
tig Oct 8, 2024
125bc4e
merged
tig Oct 11, 2024
ed0b179
Fixed DrawHorizontalShadowTransparent (vertical was already fixed).
tig Oct 11, 2024
4fef1c2
Merge branch 'v2_3691-Popover' of tig:tig/Terminal.Gui into v2_3691-P…
tig Oct 11, 2024
f5ab50f
Made Scenarios compatible with #nullable enable
tig Oct 11, 2024
90fb7cc
Merge branch 'v2_develop' into v2_3691-Popover
tig Oct 11, 2024
e81ab44
Undid some keybinding stuff
tig Oct 11, 2024
3d5d101
Fixed stuff
tig Oct 11, 2024
a243cc8
Sped up unit tests
tig Oct 11, 2024
e63fb7c
Sped up unit tests 2
tig Oct 11, 2024
2f3dbe7
Sped up unit tests 3
tig Oct 11, 2024
883ab67
Messing with menus
tig Oct 13, 2024
4547d1b
Merged v2_develop
tig Nov 5, 2024
ce572e8
Merge branch 'v2_develop' into v2_3691-Popover
tig Nov 7, 2024
8f27e8e
Merge branch 'v2_3691-Popover' of tig:tig/Terminal.Gui into v2_3691-P…
tig Nov 10, 2024
3fee0aa
merged latest v2_develop
tig Nov 10, 2024
bc23482
merged latest v2_develop
tig Nov 10, 2024
cf105dd
mergfed - probably broken
tig Nov 19, 2024
aa0499d
mergfed - probably broken2
tig Nov 19, 2024
b1e1da4
Added more Popover unit tests
tig Nov 24, 2024
2cc7297
Added more Popover unit tests2
tig Nov 24, 2024
9f2635d
Fixed positioning bug
tig Nov 24, 2024
677aaae
Fixed mouse bug
tig Nov 24, 2024
10711c7
Fixed Bar draw issue
tig Nov 24, 2024
15d9dfd
WIP
tig Nov 24, 2024
d554c70
Fixed merge issues. Code cleanup
tig Nov 25, 2024
3d1ec0e
Merged latest v2_develop
tig Nov 26, 2024
8bb63f4
Merge branch 'v2_develop' into v2_3691-ViewArrangement-Popover
tig Nov 26, 2024
7975004
Merge branch 'v2_develop' into v2_3691-ViewArrangement-Popover
tig Dec 5, 2024
4f5265c
Merge branch 'v2_develop' into v2_3691-ViewArrangement-Popover
tig Dec 10, 2024
b735b48
merge v2_develop
tig Dec 10, 2024
9f7d358
CM2 sorta works
tig Dec 10, 2024
e0014fa
Enabled Bar subclasses to have IDesignable
tig Dec 10, 2024
3880cc7
Added ViewportSettings.Transparent
tig Dec 14, 2024
4d6913b
Region -> nullable enable
tig Dec 14, 2024
b639b2c
Added ViewportSettigs Editor
tig Dec 14, 2024
e9e3588
merged v2_develop
tig Mar 6, 2025
be8210a
merged v2_develop part 2
tig Mar 6, 2025
3b89515
merged v2_develop part 3
tig Mar 6, 2025
3640334
Merge branch 'v2_3691-ViewArrangement-Popover' of tig:tig/Terminal.Gu…
tig Mar 9, 2025
51829e4
Merged latest
tig Mar 9, 2025
6fff834
WIP: GetViewsUnderMouse
tig Mar 9, 2025
4241cb3
WIP: More GetViewsUnderMouse work
tig Mar 9, 2025
57f20c6
Merge branch 'v2_develop' into v2_3691-ViewArrangement-Popover
tig Mar 10, 2025
c30742f
Bars works again
tig Mar 10, 2025
ed44e16
Added unit tests
tig Mar 10, 2025
804fdbc
CM now works
tig Mar 10, 2025
22e6e98
MenuItemv2 POC
tig Mar 10, 2025
b00cee2
SubMenu POC
tig Mar 13, 2025
bd5d3e8
Merge branch 'v2_3691-ViewArrangement-Popover' of tig:tig/Terminal.Gu…
tig Mar 13, 2025
856fe8a
CommandNotBound
tig Mar 13, 2025
a138289
More POC
tig Mar 13, 2025
7d54eb7
Optimize Margin to not defer draw if there's no shadow
tig Mar 13, 2025
06fb4da
Logger cleanup
tig Mar 13, 2025
0430fdc
Reverted Generic
tig Mar 13, 2025
33d4f3d
Merged.
tig Mar 13, 2025
3f3d2b5
Cascading mostly working
tig Mar 16, 2025
a5830c3
Merge branch 'v2_develop' into v2_3691-ViewArrangement-Popover
tig Mar 17, 2025
52b01e4
fixed layout bug
tig Mar 17, 2025
eb58ef5
API docs
tig Mar 17, 2025
4c413db
API docs
tig Mar 17, 2025
1ebc228
Fixed cascade
tig Mar 18, 2025
e0dde42
Events basically work
tig Mar 20, 2025
532213e
Merge branch 'v2_3691-ViewArrangement-Popover' of tig:tig/Terminal.Gu…
tig Mar 21, 2025
c7336d7
code cleanup
tig Mar 21, 2025
658c5f4
Fixed IsDefault bug;
tig Mar 21, 2025
a9acc85
Enabled hotkey support
tig Mar 21, 2025
a73f89f
Made context-menu-like
tig Mar 21, 2025
619d5c0
Improved usability
tig Mar 22, 2025
285c44e
Refactored ApplicationPopover again
tig Mar 24, 2025
7bf8dd0
Cleanup
tig Mar 25, 2025
84de5f6
Menuv2 POC basically complete
tig Mar 26, 2025
44a1656
Code Cleanup
tig Mar 26, 2025
5a35c27
Made menu API simpler
tig Mar 26, 2025
a1378e2
Fixed Strings bugs
tig Mar 26, 2025
e2e9475
Got old ContextMenu scenario mostly working
tig Mar 27, 2025
b1aaa5b
ContextMenu scenario now works
tig Mar 27, 2025
4b00b48
ContextMenu fixes
tig Mar 27, 2025
a5bf78d
ContextMenu fixes
tig Mar 27, 2025
b4150a8
Tons of menu cleanup
tig Mar 28, 2025
225a4ce
ContextMenu works in TextView
tig Mar 28, 2025
f8bfd39
Fixed unit tes
tig Mar 28, 2025
3d5d021
Added unit tests
tig Mar 28, 2025
9c3e7f9
Fixed tests
tig Mar 28, 2025
0f85cde
code cleanup
tig Mar 28, 2025
4fedce8
More code cleanup
tig Mar 28, 2025
7f9d002
Deep dive
tig Mar 28, 2025
321c3ee
scenario
tig Mar 28, 2025
b426e9d
typos
tig Mar 28, 2025
404105e
Demo colorpicker in a Menu
tig Mar 28, 2025
c4bfe8d
Added Region tests proving Region is broken in some Union cases
tig Mar 29, 2025
ed6f61d
Merge branch 'v2_develop' into v2_3691-ViewArrangement-Popover
tig Mar 29, 2025
4be0205
fixed v2win/net
tig Mar 29, 2025
a67bb3d
Merge branch 'v2_develop' into v2_3691-ViewArrangement-Popover
tig Mar 29, 2025
9b6e279
Merge branch 'v2_3691-ViewArrangement-Popover' of tig:tig/Terminal.Gu…
tig Mar 29, 2025
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
9 changes: 8 additions & 1 deletion Terminal.Gui/Application/Application.Initialization.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ internal static void InternalInit (
}

Navigation = new ();
Popover = new ();

// For UnitTests
if (driver is { })
Expand Down Expand Up @@ -162,6 +163,12 @@ internal static void InternalInit (

SynchronizationContext.SetSynchronizationContext (new MainLoopSyncContext ());

// TODO: This is probably not needed
if (Popover.GetActivePopover () is View popover)
{
popover.Visible = false;
}

MainThreadId = Thread.CurrentThread.ManagedThreadId;
bool init = Initialized = true;
InitializedChanged?.Invoke (null, new (init));
Expand Down Expand Up @@ -265,6 +272,6 @@ internal static void UnsubscribeDriverEvents ()
/// </summary>
internal static void OnInitializedChanged (object sender, EventArgs<bool> e)
{
Application.InitializedChanged?.Invoke (sender,e);
Application.InitializedChanged?.Invoke (sender, e);
}
}
88 changes: 61 additions & 27 deletions Terminal.Gui/Application/Application.Keyboard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,19 @@ public static partial class Application // Keyboard handling
/// <returns><see langword="true"/> if the key was handled.</returns>
public static bool RaiseKeyDownEvent (Key key)
{
// TODO: This should match standard event patterns
KeyDown?.Invoke (null, key);

if (key.Handled)
{
return true;
}

if (Popover?.DispatchKeyDown (key) is true)
{
return true;
}

if (Top is null)
{
foreach (Toplevel topLevel in TopLevels.ToList ())
Expand All @@ -43,6 +49,27 @@ public static bool RaiseKeyDownEvent (Key key)
}
}

bool? commandHandled = InvokeCommandsBoundToKey (key);
if(commandHandled is true)
{
return true;
}

return false;
}

/// <summary>
/// Invokes any commands bound at the Applicaiton-level to <paramref name="key"/>.
/// </summary>
/// <param name="key"></param>
/// <returns>
/// <see langword="null"/> if no command was found; input processing should continue.
/// <see langword="false"/> if the command was invoked and was not handled (or cancelled); input processing should continue.
/// <see langword="true"/> if the command was invoked the command was handled (or cancelled); input processing should stop.
/// </returns>
public static bool? InvokeCommandsBoundToKey (Key key)
{
bool? handled = null;
// Invoke any Application-scoped KeyBindings.
// The first view that handles the key will stop the loop.
// foreach (KeyValuePair<Key, KeyBinding> binding in KeyBindings.GetBindings (key))
Expand All @@ -52,22 +79,17 @@ public static bool RaiseKeyDownEvent (Key key)
{
if (!binding.Target.Enabled)
{
return false;
return null;
}

bool? handled = binding.Target?.InvokeCommands (binding.Commands, binding);

if (handled != null && (bool)handled)
{
return true;
}
handled = binding.Target?.InvokeCommands (binding.Commands, binding);
}
else
{
// BUGBUG: this seems unneeded.
if (!KeyBindings.TryGet (key, out KeyBinding keybinding))
{
return false;
return null;
}

bool? toReturn = null;
Expand All @@ -77,30 +99,42 @@ public static bool RaiseKeyDownEvent (Key key)
toReturn = InvokeCommand (command, key, keybinding);
}

return toReturn ?? true;
handled = toReturn ?? true;
}
}

return false;
return handled;
}

static bool? InvokeCommand (Command command, Key key, KeyBinding binding)
/// <summary>
/// Invokes an Application-bound commmand.
/// </summary>
/// <param name="command">The Command to invoke</param>
/// <param name="key">The Application-bound Key that was pressed.</param>
/// <param name="binding">Describes the binding.</param>
/// <returns>
/// <see langword="null"/> if no command was found; input processing should continue.
/// <see langword="false"/> if the command was invoked and was not handled (or cancelled); input processing should continue.
/// <see langword="true"/> if the command was invoked the command was handled (or cancelled); input processing should stop.
/// </returns>
/// <exception cref="NotSupportedException"></exception>
public static bool? InvokeCommand (Command command, Key key, KeyBinding binding)
{
if (!_commandImplementations!.ContainsKey (command))
{
if (!_commandImplementations!.ContainsKey (command))
{
throw new NotSupportedException (
@$"A KeyBinding was set up for the command {command} ({key}) but that command is not supported by Application."
);
}

if (_commandImplementations.TryGetValue (command, out View.CommandImplementation? implementation))
{
CommandContext<KeyBinding> context = new (command, binding); // Create the context here
throw new NotSupportedException (
@$"A KeyBinding was set up for the command {command} ({key}) but that command is not supported by Application."
);
}

return implementation (context);
}
if (_commandImplementations.TryGetValue (command, out View.CommandImplementation? implementation))
{
CommandContext<KeyBinding> context = new (command, null, binding); // Create the context here

return false;
return implementation (context);
}

return null;
}

/// <summary>
Expand Down Expand Up @@ -167,7 +201,7 @@ internal static void AddKeyBindings ()
{
_commandImplementations.Clear ();

// Things this view knows how to do
// Things Application knows how to do
AddCommand (
Command.Quit,
static () =>
Expand Down Expand Up @@ -213,7 +247,7 @@ internal static void AddKeyBindings ()
);

AddCommand (
Command.Edit,
Command.Arrange,
static () =>
{
View? viewToArrange = Navigation?.GetFocused ();
Expand Down Expand Up @@ -249,7 +283,7 @@ internal static void AddKeyBindings ()
KeyBindings.Add (PrevTabKey, Command.PreviousTabStop);
KeyBindings.Add (NextTabGroupKey, Command.NextTabGroup);
KeyBindings.Add (PrevTabGroupKey, Command.PreviousTabGroup);
KeyBindings.Add (ArrangeKey, Command.Edit);
KeyBindings.Add (ArrangeKey, Command.Arrange);

KeyBindings.Add (Key.CursorRight, Command.NextTabStop);
KeyBindings.Add (Key.CursorDown, Command.NextTabStop);
Expand Down
16 changes: 16 additions & 0 deletions Terminal.Gui/Application/Application.Mouse.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#nullable enable
using System.ComponentModel;
using System.Diagnostics;

namespace Terminal.Gui;

Expand Down Expand Up @@ -168,6 +169,20 @@ internal static void RaiseMouseEvent (MouseEventArgs mouseEvent)
return;
}

// Dismiss the Popover if the user presses mouse outside of it
if (mouseEvent.IsPressed
&& Popover?.GetActivePopover () as View is { Visible: true } visiblePopover
&& View.IsInHierarchy (visiblePopover, deepestViewUnderMouse, includeAdornments: true) is false)
{

visiblePopover.Visible = false;

// Recurse once so the event can be handled below the popover
RaiseMouseEvent (mouseEvent);

return;
}

if (HandleMouseGrab (deepestViewUnderMouse, mouseEvent))
{
return;
Expand Down Expand Up @@ -216,6 +231,7 @@ internal static void RaiseMouseEvent (MouseEventArgs mouseEvent)
else
{
// The mouse was outside any View's Viewport.
//Debug.Fail ("this should not happen.");

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

Expand Down
9 changes: 9 additions & 0 deletions Terminal.Gui/Application/Application.Popover.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#nullable enable

namespace Terminal.Gui;

public static partial class Application // Popover handling
{
/// <summary>Gets the Application <see cref="Popover"/> manager.</summary>
public static ApplicationPopover? Popover { get; internal set; }
}
17 changes: 14 additions & 3 deletions Terminal.Gui/Application/Application.Run.cs
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ public static Toplevel Run (Func<Exception, bool>? errorHandler = null, IConsole
[RequiresUnreferencedCode ("AOT")]
[RequiresDynamicCode ("AOT")]
public static T Run<T> (Func<Exception, bool>? errorHandler = null, IConsoleDriver? driver = null)
where T : Toplevel, new ()
where T : Toplevel, new()
{
return ApplicationImpl.Instance.Run<T> (errorHandler, driver);
}
Expand Down Expand Up @@ -426,7 +426,16 @@ public static T Run<T> (Func<Exception, bool>? errorHandler = null, IConsoleDriv

internal static void LayoutAndDrawImpl (bool forceDraw = false)
{
bool neededLayout = View.Layout (TopLevels.Reverse (), Screen.Size);
List<View> tops = [..TopLevels];

if (Popover?.GetActivePopover () as View is { Visible: true } visiblePopover)
{
visiblePopover.SetNeedsDraw ();
visiblePopover.SetNeedsLayout ();
tops.Insert (0, visiblePopover);
}

bool neededLayout = View.Layout (tops.ToArray ().Reverse (), Screen.Size);

if (ClearScreenNextIteration)
{
Expand All @@ -440,7 +449,7 @@ internal static void LayoutAndDrawImpl (bool forceDraw = false)
}

View.SetClipToScreen ();
View.Draw (TopLevels, neededLayout || forceDraw);
View.Draw (tops, neededLayout || forceDraw);
View.SetClipToScreen ();
Driver?.Refresh ();
}
Expand Down Expand Up @@ -555,6 +564,8 @@ public static void End (RunState runState)
{
ArgumentNullException.ThrowIfNull (runState);

Popover?.HidePopover (Popover?.GetActivePopover ());

runState.Toplevel.OnUnloaded ();

// End the RunState.Toplevel
Expand Down
11 changes: 10 additions & 1 deletion Terminal.Gui/Application/Application.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ internal static List<CultureInfo> GetAvailableCulturesFromEmbeddedResources ()
.ToList ();
}

// BUGBUG: This does not return en-US even though it's supported by default
internal static List<CultureInfo> GetSupportedCultures ()
{
CultureInfo [] cultures = CultureInfo.GetCultures (CultureTypes.AllCultures);
Expand Down Expand Up @@ -148,6 +149,12 @@ internal static void ResetState (bool ignoreDisposed = false)
t!.Running = false;
}

if (Popover?.GetActivePopover () is View popover)
{
popover.Visible = false;
}
Popover = null;

TopLevels.Clear ();
#if DEBUG_IDISPOSABLE

Expand Down Expand Up @@ -197,7 +204,9 @@ internal static void ResetState (bool ignoreDisposed = false)
Initialized = false;

// Mouse
_lastMousePosition = null;
// Do not clear _lastMousePosition; Popover's require it to stay set with
// last mouse pos.
//_lastMousePosition = null;
_cachedViewsUnderMouse.Clear ();
WantContinuousButtonPressedView = null;
MouseEvent = null;
Expand Down
4 changes: 4 additions & 0 deletions Terminal.Gui/Application/ApplicationNavigation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ internal void SetFocused (View? value)
/// </returns>
public bool AdvanceFocus (NavigationDirection direction, TabBehavior? behavior)
{
if (Application.Popover?.GetActivePopover () as View is { Visible: true } visiblePopover)
{
return visiblePopover.AdvanceFocus (direction, behavior);
}
return Application.Top is { } && Application.Top.AdvanceFocus (direction, behavior);
}
}
Loading
Loading