Skip to content

Fixes #5043 - View.ScrollBars now only show if they fit - Fixes View.Viewport bug#5045

Merged
tig merged 12 commits intodevelopfrom
issue-5043-scrollbar
Apr 22, 2026
Merged

Fixes #5043 - View.ScrollBars now only show if they fit - Fixes View.Viewport bug#5045
tig merged 12 commits intodevelopfrom
issue-5043-scrollbar

Conversation

@tig
Copy link
Copy Markdown
Member

@tig tig commented Apr 21, 2026

Fixes

Pull request overview

This PR targets issue #5043 by preventing built-in scrollbars from becoming visible when there isn’t enough space to render them without consuming the entire content area, and by addressing a Viewport/adornment interaction that could incorrectly grow Frame when re-applying the current Viewport.

Changes:

  • Add scrollbar visibility guards (and a minimum-size rule) so scrollbars only show when they can fit.
  • Adjust View.SetViewport behavior and add viewport/adornment regression tests for the “adornments consume viewport” scenario.
  • Update Shortcut/Menu example and unit test code to accommodate the behavior changes.

tig added 4 commits April 21, 2026 09:23
Refactor Shortcut and related code to make CommandView nullable (View?) and update all usages to handle null values safely. Update property setters, event handlers, layout logic, and tests to use null-safe access. Initialize HelpView and KeyView with default Frames. Clean up redundant null checks and improve robustness against null reference exceptions when CommandView is replaced or disposed.
- Remove BorderStyle from TreeViewFileSystem tree view
- Prevent invalid viewport/frame updates in View
- Refine scrollbar visibility checks for valid content area
- Remove quit key binding from MenuBar, comment out in PopoverMenu
- Hide scrollbars if visible content size < 2 in auto mode
Refactored TreeViewFileSystem to use Runnable and improved layout logic. Enhanced View.Content.cs to prevent Frame growth when adornments consume the viewport. Expanded ViewportTests with cases for adornment edge cases. Applied code style and correctness improvements.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR targets issue #5043 by preventing built-in scrollbars from becoming visible when there isn’t enough space to render them without consuming the entire content area, and by addressing a Viewport/adornment interaction that could incorrectly grow Frame when re-applying the current Viewport.

Changes:

  • Add scrollbar visibility guards (and a minimum-size rule) so scrollbars only show when they can fit.
  • Adjust View.SetViewport behavior and add viewport/adornment regression tests for the “adornments consume viewport” scenario.
  • Update Shortcut/Menu example and unit test code to accommodate the behavior changes.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
Tests/UnitTestsParallelizable/Views/ShortcutTests.cs Updates Shortcut tests for CommandView nullability/layout expectations.
Tests/UnitTestsParallelizable/Views/ShortcutTests.KeyDown.cs Updates Shortcut input tests; adds null-conditional usage in assertions.
Tests/UnitTestsParallelizable/Views/EnableForDesignEventTests.cs Uses null-forgiving operator when casting CommandView.
Tests/UnitTestsParallelizable/ViewBase/Layout/ViewportTests.cs Adds regression tests ensuring Viewport = Viewport doesn’t grow Frame when adornments consume viewport.
Terminal.Gui/Views/Shortcut.cs Makes CommandView nullable and adds default Frames to subviews; adjusts layout logic.
Terminal.Gui/Views/ScrollBar/ScrollBar.cs Prevents Auto scrollbars from showing when too small to render both buttons.
Terminal.Gui/Views/Menu/MenuBar.cs Tweaks design-time Quit menu item creation.
Terminal.Gui/ViewBase/View.ScrollBars.cs Adds VisibleChanging cancellation logic to prevent scrollbars showing when they can’t fit.
Terminal.Gui/ViewBase/View.Content.cs Adds an early-return guard in SetViewport for “invalid” sizes / no-op scenarios.
Terminal.Gui/ViewBase/Adornment/AdornmentImpl.cs Adds (commented-out) debug assertion concept for unreasonable thickness values.
Examples/UICatalog/Scenarios/TreeViewFileSystem.cs Updates layout and replaces Window with Runnable for the scenario root.
Examples/UICatalog/Scenarios/Shortcuts.cs Updates event handler/lambda parameters and adds null-conditional access for CommandView.
Examples/UICatalog/Scenarios/PopoverMenus.cs Makes checkbox cast/assignment safe via as + null-conditional.
Comments suppressed due to low confidence (2)

Terminal.Gui/Views/Shortcut.cs:260

  • CommandView is now nullable, but this block dereferences it (CommandView.SuperView, Add(CommandView)) based on CommandView?.Visible == true. This will produce nullable warnings and can still pass a null to Add(...). Consider caching View commandView = CommandView! after a null check, or keep CommandView non-nullable if it is required by design.
        if (CommandView?.Visible == true)
        {
            if (CommandView.SuperView is null)
            {
                Add (CommandView);
                SetCommandViewDefaultLayout ();

Examples/UICatalog/Scenarios/Shortcuts.cs:339

  • The condition uses framedShortcut.CommandView?.Margin is { }, but inside the block framedShortcut.CommandView is dereferenced without a null check. With CommandView now nullable this will produce nullable warnings. Consider caching View commandView = framedShortcut.CommandView!; after an explicit not-null check, then use commandView inside the block.
        if (framedShortcut.CommandView?.Margin is { })
        {
            framedShortcut.CommandView.SchemeName = SchemeManager.SchemesToSchemeName (Schemes.Dialog);
            framedShortcut.HelpView.SchemeName = SchemeManager.SchemesToSchemeName (Schemes.Error);
            framedShortcut.KeyView.SchemeName = SchemeManager.SchemesToSchemeName (Schemes.Base);

Comment thread Examples/UICatalog/Scenarios/TreeViewFileSystem.cs
Comment thread Terminal.Gui/Views/Shortcut.cs Outdated
Comment thread Tests/UnitTestsParallelizable/Views/ShortcutTests.cs
Comment thread Tests/UnitTestsParallelizable/Views/ShortcutTests.KeyDown.cs
Comment thread Terminal.Gui/ViewBase/View.ScrollBars.cs
Comment thread Terminal.Gui/ViewBase/Adornment/AdornmentImpl.cs Outdated
Comment thread Terminal.Gui/Views/Shortcut.cs
Comment thread Tests/UnitTestsParallelizable/Views/ShortcutTests.cs
Comment thread Terminal.Gui/ViewBase/View.Content.cs
Comment thread Terminal.Gui/Views/Menu/MenuBar.cs
tig and others added 4 commits April 21, 2026 13:57
When the scheme name is "Accent", the code now derives the accent scheme from the "Base" scheme using the driver's default attribute, rather than returning the named "Accent" scheme directly. This ensures consistent accent theming based on the current base scheme.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Removed null check and updated usages to support CommandView being null. Used null-conditional operators to prevent exceptions and set Title to an empty string when CommandView is null.
@tig tig requested a review from BDisp April 21, 2026 20:02
… layout logic

Removed arbitrary screenX4 upper bounds in dimension and layout calculations, using int.MaxValue instead. This change affects maximum content dimension, text formatting constraints, and layout for centered and anchored subviews, improving flexibility and correctness for large dimension scenarios.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (1)

Terminal.Gui/Views/Shortcut.cs:446

  • The XML docs for CommandView still include an ArgumentNullException <exception> tag, but the setter no longer throws on null and the property is now nullable. Please update the docs to reflect the actual behavior (or reintroduce the null guard if CommandView is intended to be non-null).
    /// <summary>
    ///     Gets or sets the View that displays the command text and hotkey.
    /// </summary>
    /// <exception cref="ArgumentNullException"></exception>
    /// <remarks>

Comment thread Terminal.Gui/ViewBase/Layout/DimAuto.cs Outdated
Comment thread Terminal.Gui/ViewBase/View.Drawing.Scheme.cs Outdated
Comment thread Terminal.Gui/ViewBase/View.Content.cs Outdated
Comment thread Terminal.Gui/Views/Shortcut.cs Outdated
tig added 2 commits April 21, 2026 15:01
- Arrangement scenario now sets SchemeName via SchemeManager instead of assigning a custom Scheme directly.
- DropDownList overrides OnMouseEvent to handle popover activation when ReadOnly and left mouse button is pressed.
Fix Accent scheme fallback, cleanup, and disposal logic

- Derive Accent scheme from Base if missing background color
- Simplify ConstrainToSize assignment in DimAuto.cs
- Reformat namespace in View.Content.cs
- Use _commandView field consistently in Shortcut disposal
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

Terminal.Gui/Views/Shortcut.cs:519

  • CommandView was changed from non-nullable to View? and the setter no longer rejects null, but the class docs/remarks describe Shortcut as a composite containing a CommandView and command dispatch relies on it as the relay target. This is a public API surface change for nullable-reference-type consumers and may be unintentionally loosening an invariant. If null is not a supported state, consider restoring the non-nullable type + ThrowIfNull; if it is supported, consider updating the XML docs and ensuring all callers (and derived types like MenuItem) have a clear contract for the null case.
    public View? CommandView
    {
        get => _commandView;
        set
        {
            // Clean up old
            _commandView?.GettingAttributeForRole -= SubViewOnGettingAttributeForRole;
            Remove (_commandView);
            _commandView?.Dispose ();

            // Set new
            _commandView = value;

#if DEBUG
            if (string.IsNullOrEmpty (_commandView?.Id))
            {
                _commandView?.Id = "_commandView";
            }
#endif
            _commandView?.GettingAttributeForRole += SubViewOnGettingAttributeForRole;

            // If the CommandView has a hotkey, we use that. Otherwise, we use '_' to indicate the hotkey is in the Title.
            if (_commandView?.HotKey != Key.Empty)
            {
                HotKeySpecifier = (Rune)'\xffff';
            }
            else
            {
                HotKeySpecifier = (Rune)'_';
            }
            Title = _commandView?.Text ?? string.Empty;

            UpdateKeyBindings (Key.Empty);
            UpdateMouseBindings ();
            ShowHide ();
        }

Comment thread Terminal.Gui/ViewBase/View.Content.cs
Copilot finished work on behalf of tig April 21, 2026 21:43
Copy link
Copy Markdown
Collaborator

@BDisp BDisp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That sounds good to me. I just have two questions that I'm a little unsure about.

Comment thread Terminal.Gui/ViewBase/View.ScrollBars.cs
Comment thread Terminal.Gui/ViewBase/View.ScrollBars.cs
@tig tig merged commit 975c390 into develop Apr 22, 2026
11 checks passed
@tig tig deleted the issue-5043-scrollbar branch April 22, 2026 14:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dim.Auto restricts size to 4x screen size View.ScrollBar should no make scrollbars visible if Padding can't fit

4 participants