0.4.3 — Split Layouts, Installer Uninstaller & Install Log#

Released

SplitView Widget#

Allow the Host window’s content area to be divided into multiple panes, each with its own TabBar and TabManager, with a draggable sash between panes. Two screens can run side by side (or stacked) in a single window without spawning a DetachedWindow.

  • New SplitView widget (VIStk/Widgets/_SplitView.py) replaces the single TabManager in Host

  • Wraps a ttk.PanedWindow (horizontal or vertical); each slot is either a TabManager (leaf) or a nested SplitView (branch)

  • Tree-of-panes model supports arbitrary split arrangements

  • SplitView.split(pane, direction) — replaces a TabManager leaf with a new SplitView containing the original pane and a fresh empty TabManager; direction is "right" or "down"

  • SplitView.remove_pane(pane) — collapses the parent SplitView, promoting the surviving sibling; dissolves if root becomes a single TabManager

  • Sash positions default to 50/50; user can drag freely

Focused Pane#

  • SplitView.focused_pane tracks the last-interacted pane

  • Clicking a tab or content frame sets that pane as focused

  • HostMenu and window title always reflect the focused pane’s active tab

  • Focus transfers to the nearest remaining pane when the focused pane is removed

Right-Click Split Actions#

Two new entries in the TabBar right-click context menu:

  • Split right — horizontal split, tab moves to the new right pane

  • Split down — vertical split, tab moves to the new bottom pane

Pane Auto-Removal#

  • When a pane’s tab count reaches zero, it calls on_pane_empty on its SplitView

  • The SplitView removes the empty pane and promotes the surviving sibling

Drag-to-Split#

  • Dragging a tab into the outer 25% of any pane’s content area shows a translucent blue overlay indicating the split direction (right, left, down, up)

  • Dragging to the center shows a full-pane overlay; dropping there adds the tab to the pane without splitting

  • If a pane has only one tab, dragging it over its own pane shows the center overlay

  • Tab bar insertion indicator shown alongside center overlay to preview tab placement

  • Parent sash positions preserved during nested splits

Cross-Window Drag-to-Split#

  • Drag-to-split works across Host and DetachedWindow in both directions

  • DetachedWindow is now wrapped in SplitView with full split and focus support

  • SplitView._registry enables cross-window zone detection

  • Z-order aware: overlapping windows only show drop zones for the frontmost window at the cursor position (uses Tk wm stackorder)

  • Target window lifts to the front as the cursor enters its non-overlapping area

Focus-Aware Tab Styling#

  • Active tab in the focused pane shown in brighter grey; unfocused panes are dimmer

  • When a window loses OS focus, all pane focus indicators dim; restore on regain

  • SplitView._global_focused_pane tracks the last-focused pane across all windows

Global Focus Tracking#

  • Clicking any widget inside a pane (buttons, entries, etc.) sets focus to that pane via a toplevel-level <Button-1> binding

  • Host._open_tab() uses the globally focused pane, even from DetachedWindow

  • Host.open() raises the correct window (Host or DetachedWindow)

Host Changes#

  • self.TabManager property returns self._split_view.focused_pane

  • host.open() opens new tabs into the globally focused pane (Host or DetachedWindow)

  • host._get_all_tab_names() walks the full SplitView tree

  • Activate/deactivate/menu/title callbacks wired to all panes

  • _on_tab_split handles within-pane, cross-pane, center, and cross-window drops

DetachedWindow Changes#

  • Content area now wrapped in SplitView (was bare TabManager)

  • tab_manager property returns _split_view.focused_pane

  • _on_tab_split mirrors Host implementation

  • _on_close iterates all panes in the SplitView tree

TabBar Changes#

  • on_tab_split: callable | None — callback (name, direction, target_pane)

  • on_drag_zone: callable | None — drag-to-split zone detection during motion

  • Right-click menu gains “Split right” and “Split down”

  • Focus-aware _tab_bg() returns different colours based on pane focus state

Uninstaller#

  • Release.release() generates an uninstaller executable alongside the installer

  • Reads .VIS/install_log.json to know exactly which files and shortcuts were created

  • Removes all installed binaries, adjacent files, and desktop shortcuts

  • Optionally deregisters from Windows Add/Remove Programs

Install Log#

  • Installer writes .VIS/install_log.json after a successful install

  • Records every extracted file path, every shortcut created, the install location, and a timestamp

  • Used by the uninstaller and the update-in-place installer (0.4.4)

  • Quiet mode (--Quiet) also writes the install log