Skip to content

Fixes #4183 - Rewrites TabView#4829

Draft
tig wants to merge 33 commits intogui-cs:v2_developfrom
tig:issue-4183-tabview
Draft

Fixes #4183 - Rewrites TabView#4829
tig wants to merge 33 commits intogui-cs:v2_developfrom
tig:issue-4183-tabview

Conversation

@tig
Copy link
Collaborator

@tig tig commented Mar 11, 2026

Fixes

Proposed Changes/Todos

  • Todo 1

Pull Request checklist:

  • I've named my PR in the form of "Fixes #issue. Terse description."
  • My code follows the style guidelines of Terminal.Gui - if you use Visual Studio, hit CTRL-K-D to automatically reformat your files before committing.
  • My code follows the Terminal.Gui library design guidelines
  • I ran dotnet test before commit
  • I have made corresponding changes to the API documentation (using /// style comments)
  • My changes generate no new warnings
  • I have checked my code and corrected any poor grammar or misspellings
  • I conducted basic QA to assure all features are working

tig and others added 14 commits March 9, 2026 09:20
Remove all old TabView source files (~3,570 lines across 6 files),
old TabView tests, and TabViewExample scenario. Fix compilation errors
in scenarios that referenced deleted types by stubbing out TabView-
dependent scenarios (Notepad, ConfigurationEditor) and replacing
TabView usage with direct views (Editor, Images, AnsiRequests).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add BorderGap record struct and gap lists (TopGaps, BottomGaps,
LeftGaps, RightGaps) to Border. Gaps create exclusion regions in
the border's LineCanvas, allowing TabView to punch openings where
the selected tab connects to the content area.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements the new TabView using modern v2 patterns:
- Tab: Simple View subclass (Visible=false by default, Dim.Fill)
- TabRow: Internal view in Padding that renders tab headers with
  rounded borders, positioned adjacent with 1-cell overlap
- TabView: Orchestrator with Wizard-style show/hide, nullable
  SelectedTabIndex, keyboard commands (Ctrl+Left/Right/Home/End),
  IDesignable support, and CWP SelectedTabChanged event

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New scenario for exercising TabView with:
- Demo TabView with 3 example tabs (label, text+button, multi-line)
- Configuration pane: TabsOnBottom toggle, MaxTabTextWidth,
  Add/Remove tab buttons, SelectedTabIndex display, Prev/Next nav
- AdornmentsEditor targeting the demo TabView
- EventLog for monitoring tab change events

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use ValueChangingEventArgs.Handled to clamp MaxTabTextWidth
input to 1-100 range instead of non-existent MinValue/MaxValue.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@tig tig marked this pull request as draft March 11, 2026 22:51
tig and others added 15 commits March 11, 2026 21:20
…, disposal fixes

- Change TabView.Border.Thickness to (1,0,1,1) so tab headers form the top
- Add Border.DrawSegmentedVerticalLine for gap-aware vertical line rendering
- Use RightGaps instead of Exclude for correct corner glyphs (╮ not ┤)
- TabRow draws horizontal continuation line from last tab to right edge
- Fix RebuildHeaders to dispose old header views (prevents "Not Disposed" leaks)
- Guard OnSubViewRemoved during disposal to prevent orphaned header creation
- Clear SelectedTabChanged event before base disposal to prevent ObjectDisposedException
- Add disposal tests that fail without fixes (verify Border==null after dispose)
- Update all visual rendering tests for new no-top-border layout

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…sOnBottom

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Refactored TabViewExample for more adaptive layout using Dim.Fill and Pos.AnchorEnd, and compacted configuration controls. Updated TabView and TabRow to use base.SuperViewRendersLineCanvas = true. Improved command registration with method group syntax. Enhanced Side enum documentation. Updated tabview-rewrite.md to mark navigation and visual polish as partial, added a detailed TabsOnBottom fix plan, and documented additional known issues. Minor code cleanups and formatting improvements.
- Fix text/continuation line overlap in TabRow.UpdateHeaderAppearance()
  by adding Padding.Top=1 compensation for selected header when TabsOnBottom
- Extract visual rendering tests to TabViewVisualTests.cs (28 tests)
- Add 13 new visual regression tests covering tabs-on-bottom, state
  transitions, padding assertions, and edge cases
- Update plan with fix status

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements mnemonic (hotkey) selection for TabView tabs by overriding OnHandlingHotKey in Tab. Ensures TabStop is set for tabs and tab headers. Updates TabViewExample and adds comprehensive unit tests for hotkey selection, event raising, and keyboard navigation. Refactors focus management logic for robustness. Improves TabView disposal and focus behavior. Updates documentation and marks hotkey issue as fixed.
- Replace bool TabsOnBottom with Side TabSide enum (Top/Bottom only, Left/Right ignored)
- Add 6 hotkey navigation unit tests proving Tab.OnHandlingHotKey works
- Replace CheckBox with OptionSelector<Side> in TabViewExample, disable Left/Right
- Update all tests and visual tests for TabSide rename
- Add focusable tab headers with hot-normal/hot-focus attribute routing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Make TabRow focusable and add focus event handlers to TabRow/TabView
- Enhance mouse and keyboard navigation for tab headers
- Refactor Padding subview logic and mouse handling
- Set TabView.Padding as a tab stop for accessibility
- Add visual tests for tab scrolling and indicator rendering
- Clean up code and remove unused usings
- Prepares for future tab scrolling support and better accessibility
…iewport scrolling

- TabRow.UpdateContentSizeForScrolling() computes total header width and sets ContentSize
- TabRow.EnsureHeaderVisible() scrolls viewport to reveal selected tab header
- TabView.SelectedTabIndex setter calls EnsureHeaderVisible on tab change
- Rewrite scroll tests to verify content size and forward viewport scrolling
- Skip scroll-back rendering test pending investigation
- Update plan to reflect scrolling progress

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Design plan for implementing tab headers as a first-class Border
capability (BorderSettings.Tab) instead of using a separate TabRow
with dynamically-created header views. Leverages existing
Thickness.Top == 3 rendering and LineCanvas auto-join for the
flowing connected tab style. Includes renderings for all four
sides (Top, Bottom, Left, Right) and a plan for migrating
BorderTests to UnitTestsParallelizable.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Major rewrite of tabview-border-based-design.md to propose a new, border-based approach for tabbed interfaces in Terminal.Gui v2. Tabs are now rendered as part of the Border adornment, leveraging a shared LineCanvas for auto-joining borders and eliminating the need for TabRow and dynamic header Views. The document details the new API surface (BorderSettings.Tab, TabOffset, TabWidth), explains rendering for all four sides, and provides implementation phases. Scrolling, focus, and mouse handling are addressed, with ASCII diagrams and tables clarifying the design. The new approach aims to be the reference for compound views in v2.
Add support for transparent borders drawn on top

Introduce transparent border rendering, similar to transparent margins, by drawing borders with the Transparent flag after all content. Refactor border drawing logic and region exclusion to support this feature. Update demo and editors for improved usability and identifier display. Move ShowViewIdentifier to EditorBase and ensure consistent OnViewToEditChanged behavior. Cache clip regions for correct transparent rendering.
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.

Refactor/rewrite TabView to use modern v2 capabilities

1 participant