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

Backport of a bunch of fixes from #3691 #3854

Merged
merged 2 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions Terminal.Gui/Application/Application.Driver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public static partial class Application // Driver abstractions
/// <summary>Gets the <see cref="ConsoleDriver"/> that has been selected. See also <see cref="ForceDriver"/>.</summary>
public static ConsoleDriver? Driver { get; internal set; }

// BUGBUG: Force16Colors should be nullable.
/// <summary>
/// Gets or sets whether <see cref="Application.Driver"/> will be forced to output only the 16 colors defined in
/// <see cref="ColorName16"/>. The default is <see langword="false"/>, meaning 24-bit (TrueColor) colors will be output
Expand All @@ -16,6 +17,7 @@ public static partial class Application // Driver abstractions
[SerializableConfigurationProperty (Scope = typeof (SettingsScope))]
public static bool Force16Colors { get; set; }

// BUGBUG: ForceDriver should be nullable.
/// <summary>
/// Forces the use of the specified driver (one of "fake", "ansi", "curses", "net", or "windows"). If not
/// specified, the driver is selected based on the platform.
Expand Down
5 changes: 5 additions & 0 deletions Terminal.Gui/Application/Application.Keyboard.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ public static bool RaiseKeyDownEvent (Key key)
{
if (binding.Value.BoundView is { })
{
if (!binding.Value.BoundView.Enabled)
{
return false;
}

bool? handled = binding.Value.BoundView?.InvokeCommands (binding.Value.Commands, binding.Key, binding.Value);

if (handled != null && (bool)handled)
Expand Down
5 changes: 5 additions & 0 deletions Terminal.Gui/Drawing/Glyphs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@
/// </remarks>
public class GlyphDefinitions
{
// IMPORTANT: If you change these, make sure to update the ./Resources/config.json file as
// IMPORTANT: it is the source of truth for the default glyphs at runtime.
// IMPORTANT: Configuration Manager test SaveDefaults uses this class to generate the default config file
// IMPORTANT: in ./UnitTests/bin/Debug/netX.0/config.json

/// <summary>File icon. Defaults to ☰ (Trigram For Heaven)</summary>
public Rune File { get; set; } = (Rune)'☰';

Expand Down
54 changes: 43 additions & 11 deletions Terminal.Gui/Input/KeyBindings.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#nullable enable

using static System.Formats.Asn1.AsnWriter;

namespace Terminal.Gui;

/// <summary>
Expand All @@ -17,7 +19,7 @@ public class KeyBindings
public KeyBindings () { }

/// <summary>Initializes a new instance bound to <paramref name="boundView"/>.</summary>
public KeyBindings (View boundView) { BoundView = boundView; }
public KeyBindings (View? boundView) { BoundView = boundView; }

/// <summary>Adds a <see cref="KeyBinding"/> to the collection.</summary>
/// <param name="key"></param>
Expand All @@ -27,7 +29,12 @@ public void Add (Key key, KeyBinding binding, View? boundViewForAppScope = null)
{
if (BoundView is { } && binding.Scope.FastHasFlags (KeyBindingScope.Application))
{
throw new ArgumentException ("Application scoped KeyBindings must be added via Application.KeyBindings.Add");
throw new InvalidOperationException ("Application scoped KeyBindings must be added via Application.KeyBindings.Add");
}

if (BoundView is { } && boundViewForAppScope is null)
{
boundViewForAppScope = BoundView;
}

if (TryGet (key, out KeyBinding _))
Expand Down Expand Up @@ -78,6 +85,10 @@ public void Add (Key key, KeyBindingScope scope, View? boundViewForAppScope = nu
{
throw new ArgumentException ("Application scoped KeyBindings must be added via Application.KeyBindings.Add");
}
else
{
// boundViewForAppScope = BoundView;
}

if (key is null || !key.IsValid)
{
Expand All @@ -93,11 +104,9 @@ public void Add (Key key, KeyBindingScope scope, View? boundViewForAppScope = nu
if (TryGet (key, out KeyBinding binding))
{
throw new InvalidOperationException (@$"A key binding for {key} exists ({binding}).");

//Bindings [key] = new (commands, scope, BoundView);
}

Add (key, new KeyBinding (commands, scope, BoundView), boundViewForAppScope);
Add (key, new KeyBinding (commands, scope, boundViewForAppScope), boundViewForAppScope);
}

/// <summary>
Expand All @@ -120,9 +129,14 @@ public void Add (Key key, KeyBindingScope scope, View? boundViewForAppScope = nu
/// </param>
public void Add (Key key, KeyBindingScope scope, params Command [] commands)
{
if (BoundView is null && !scope.FastHasFlags (KeyBindingScope.Application))
{
throw new InvalidOperationException ("BoundView cannot be null.");
}

if (BoundView is { } && scope.FastHasFlags (KeyBindingScope.Application))
{
throw new ArgumentException ("Application scoped KeyBindings must be added via Application.KeyBindings.Add");
throw new InvalidOperationException ("Application scoped KeyBindings must be added via Application.KeyBindings.Add");
}

if (key == Key.Empty || !key.IsValid)
Expand All @@ -140,7 +154,7 @@ public void Add (Key key, KeyBindingScope scope, params Command [] commands)
throw new InvalidOperationException (@$"A key binding for {key} exists ({binding}).");
}

Add (key, new KeyBinding (commands, scope, BoundView));
Add (key, new KeyBinding (commands, scope, BoundView), BoundView);
}

/// <summary>
Expand Down Expand Up @@ -219,14 +233,22 @@ public void Add (Key key, params Command [] commands)
/// <summary>The collection of <see cref="KeyBinding"/> objects.</summary>
public Dictionary<Key, KeyBinding> Bindings { get; } = new (new KeyEqualityComparer ());

/// <summary>
/// Gets the keys that are bound.
/// </summary>
/// <returns></returns>
public IEnumerable<Key> GetBoundKeys ()
{
return Bindings.Keys;
}

/// <summary>
/// The view that the <see cref="KeyBindings"/> are bound to.
/// </summary>
/// <remarks>
/// If <see langword="null"/>, the <see cref="KeyBindings"/> are not bound to a <see cref="View"/>. This is used for
/// Application.KeyBindings.
/// If <see langword="null"/> the KeyBindings object is being used for Application.KeyBindings.
/// </remarks>
public View? BoundView { get; }
internal View? BoundView { get; }

/// <summary>Removes all <see cref="KeyBinding"/> objects from the collection.</summary>
public void Clear () { Bindings.Clear (); }
Expand Down Expand Up @@ -312,7 +334,7 @@ public IEnumerable<Key> GetKeysFromCommands (params Command [] commands)
/// <param name="boundViewForAppScope">Optional View for <see cref="KeyBindingScope.Application"/> bindings.</param>
public void Remove (Key key, View? boundViewForAppScope = null)
{
if (!TryGet (key, out KeyBinding binding))
if (!TryGet (key, out KeyBinding _))
{
return;
}
Expand Down Expand Up @@ -371,6 +393,11 @@ public void ReplaceKey (Key oldKey, Key newKey)
/// <returns><see langword="true"/> if the Key is bound; otherwise <see langword="false"/>.</returns>
public bool TryGet (Key key, out KeyBinding binding)
{
//if (BoundView is null)
//{
// throw new InvalidOperationException ("KeyBindings must be bound to a View to use this method.");
//}

binding = new (Array.Empty<Command> (), KeyBindingScope.Disabled, null);

if (key.IsValid)
Expand All @@ -394,6 +421,11 @@ public bool TryGet (Key key, KeyBindingScope scope, out KeyBinding binding)
{
if (!key.IsValid)
{
//if (BoundView is null)
//{
// throw new InvalidOperationException ("KeyBindings must be bound to a View to use this method.");
//}

binding = new (Array.Empty<Command> (), KeyBindingScope.Disabled, null);
return false;
}
Expand Down
167 changes: 163 additions & 4 deletions Terminal.Gui/Resources/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,173 @@
// to throw exceptions.
"ConfigurationManager.ThrowOnJsonErrors": false,

"Application.NextTabKey": "Tab",
"Application.PrevTabKey": "Shift+Tab",
// --------------- Application Settings ---------------
"Key.Separator": "+",

"Application.ArrangeKey": "Ctrl+F5",
"Application.Force16Colors": false,
//"Application.ForceDriver": "", // TODO: ForceDriver should be nullable
"Application.IsMouseDisabled": false,
"Application.NextTabGroupKey": "F6",
"Application.NextTabKey": "Tab",
"Application.PrevTabGroupKey": "Shift+F6",
"Application.PrevTabKey": "Shift+Tab",
"Application.QuitKey": "Esc",
"Application.ArrangeKey": "Ctrl+F5",
"Key.Separator": "+",

// --------------- Colors ---------------


// --------------- View Specific Settings ---------------
"ContextMenu.DefaultKey": "Shift+F10",
"FileDialog.MaxSearchResults": 10000,
"FileDialogStyle.DefaultUseColors": false,
"FileDialogStyle.DefaultUseUnicodeCharacters": false,

// --------------- Glyphs ---------------
"Glyphs": {
"File": "☰",
"Folder": "꤉",
"HorizontalEllipsis": "…",
"VerticalFourDots": "⁞",
"CheckStateChecked": "☑",
"CheckStateUnChecked": "☐",
"CheckStateNone": "☒",
"Selected": "◉",
"UnSelected": "○",
"RightArrow": "►",
"LeftArrow": "◄",
"DownArrow": "▼",
"UpArrow": "▲",
"LeftDefaultIndicator": "►",
"RightDefaultIndicator": "◄",
"LeftBracket": "⟦",
"RightBracket": "⟧",
"BlocksMeterSegment": "▌",
"ContinuousMeterSegment": "█",
"Stipple": "░",
"Diamond": "◊",
"Close": "✘",
"Minimize": "❏",
"Maximize": "✽",
"Dot": "∙",
"BlackCircle": "●",
"Expand": "+",
"Collapse": "-",
"IdenticalTo": "≡",
"Move": "◊",
"SizeHorizontal": "↔",
"SizeVertical": "↕",
"SizeTopLeft": "↖",
"SizeTopRight": "↗",
"SizeBottomRight": "↘",
"SizeBottomLeft": "↙",
"Apple": "\uD83C\uDF4E",
"AppleBMP": "❦",
"HLine": "─",
"VLine": "│",
"HLineDbl": "═",
"VLineDbl": "║",
"HLineHvDa2": "╍",
"VLineHvDa3": "┇",
"HLineHvDa3": "┅",
"HLineHvDa4": "┉",
"VLineHvDa2": "╏",
"VLineHvDa4": "┋",
"HLineDa2": "╌",
"VLineDa3": "┆",
"HLineDa3": "┄",
"HLineDa4": "┈",
"VLineDa2": "╎",
"VLineDa4": "┊",
"HLineHv": "━",
"VLineHv": "┃",
"HalfLeftLine": "╴",
"HalfTopLine": "╵",
"HalfRightLine": "╶",
"HalfBottomLine": "╷",
"HalfLeftLineHv": "╸",
"HalfTopLineHv": "╹",
"HalfRightLineHv": "╺",
"HalfBottomLineLt": "╻",
"RightSideLineLtHv": "╼",
"BottomSideLineLtHv": "╽",
"LeftSideLineHvLt": "╾",
"TopSideLineHvLt": "╿",
"ULCorner": "┌",
"ULCornerDbl": "╔",
"ULCornerR": "╭",
"ULCornerHv": "┏",
"ULCornerHvLt": "┎",
"ULCornerLtHv": "┍",
"ULCornerDblSingle": "╓",
"ULCornerSingleDbl": "╒",
"LLCorner": "└",
"LLCornerHv": "┗",
"LLCornerHvLt": "┖",
"LLCornerLtHv": "┕",
"LLCornerDbl": "╚",
"LLCornerSingleDbl": "╘",
"LLCornerDblSingle": "╙",
"LLCornerR": "╰",
"URCorner": "┐",
"URCornerDbl": "╗",
"URCornerR": "╮",
"URCornerHv": "┓",
"URCornerHvLt": "┑",
"URCornerLtHv": "┒",
"URCornerDblSingle": "╖",
"URCornerSingleDbl": "╕",
"LRCorner": "┘",
"LRCornerDbl": "╝",
"LRCornerR": "╯",
"LRCornerHv": "┛",
"LRCornerDblSingle": "╜",
"LRCornerSingleDbl": "╛",
"LRCornerLtHv": "┙",
"LRCornerHvLt": "┚",
"LeftTee": "├",
"LeftTeeDblH": "╞",
"LeftTeeDblV": "╟",
"LeftTeeDbl": "╠",
"LeftTeeHvH": "┝",
"LeftTeeHvV": "┠",
"LeftTeeHvDblH": "┣",
"RightTee": "┤",
"RightTeeDblH": "╡",
"RightTeeDblV": "╢",
"RightTeeDbl": "╣",
"RightTeeHvH": "┥",
"RightTeeHvV": "┨",
"RightTeeHvDblH": "┫",
"TopTee": "┬",
"TopTeeDblH": "╤",
"TopTeeDblV": "╥",
"TopTeeDbl": "╦",
"TopTeeHvH": "┯",
"TopTeeHvV": "┰",
"TopTeeHvDblH": "┳",
"BottomTee": "┴",
"BottomTeeDblH": "╧",
"BottomTeeDblV": "╨",
"BottomTeeDbl": "╩",
"BottomTeeHvH": "┷",
"BottomTeeHvV": "┸",
"BottomTeeHvDblH": "┻",
"Cross": "┼",
"CrossDblH": "╪",
"CrossDblV": "╫",
"CrossDbl": "╬",
"CrossHvH": "┿",
"CrossHvV": "╂",
"CrossHv": "╋",
"ShadowVerticalStart": "▖",
"ShadowVertical": "▌",
"ShadowHorizontalStart": "▝",
"ShadowHorizontal": "▀",
"ShadowHorizontalEnd": "▘"
},

// --------------- Themes -----------------
"Theme": "Default",
"Themes": [
{
Expand Down
2 changes: 1 addition & 1 deletion Terminal.Gui/View/Layout/DimAuto.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ internal override int Calculate (int location, int superviewContentSize, View us
int screenX4 = dimension == Dimension.Width ? Application.Screen.Width * 4 : Application.Screen.Height * 4;
int autoMax = MaximumContentDim?.GetAnchor (superviewContentSize) ?? screenX4;

Debug.Assert (autoMin <= autoMax, "MinimumContentDim must be less than or equal to MaximumContentDim.");
Debug.WriteLineIf (autoMin > autoMax, "MinimumContentDim must be less than or equal to MaximumContentDim.");

if (Style.FastHasFlags (DimAutoStyle.Text))
{
Expand Down
10 changes: 9 additions & 1 deletion Terminal.Gui/View/View.Drawing.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ public void Draw ()
// Draw the Border and Padding.
// We clip to the frame to prevent drawing outside the frame.
saved = ClipFrame ();

DoDrawBorderAndPadding ();
SetClip (saved);

Expand All @@ -71,7 +72,7 @@ public void Draw ()
DoSetAttribute ();
DoClearViewport ();

// Draw the subviews
// Draw the subviews only if needed
if (SubViewNeedsDraw)
{
DoSetAttribute ();
Expand Down Expand Up @@ -166,6 +167,13 @@ private void DoDrawBorderAndPaddingSubViews ()

private void DoDrawBorderAndPadding ()
{
if (SubViewNeedsDraw)
{
// A Subview may add to the LineCanvas. This ensures any Adornment LineCanvas updates happen.
Border?.SetNeedsDraw ();
Padding?.SetNeedsDraw ();
}

if (OnDrawingBorderAndPadding ())
{
return;
Expand Down
Loading
Loading