Private
Public Access
0
0

fix(layout): make 2-column dock layout actually auto-apply

The pre-run install wrote the bundled INI to cwd, and the
_install_default_layout_if_empty helper applies it via
imgui.load_ini_settings_from_memory() when cwd is empty. But the
GUI was rendering all panels as floating windows at default position
(60, 60) with no DockId, despite the bundled INI having a full
[Docking][Data] block with DockSpace + DockNodes + per-window DockIds.

Root cause analysis (via imgui.save_ini_settings_to_memory() at runtime):

1. With default_imgui_window_type=provide_full_screen_dock_space:
   HelloImGui creates its own DockSpace at runtime, overriding the INI's
   DockSpace settings. The DockSpace ID matches (0xAFC85805) but the
   Split/X and child DockNodes from the bundled INI are discarded.
   Runtime INI shows: 'DockSpace ID=0xAFC85805 Window=0x079D3A04 Pos=0,28
   Size=1666,1172 CentralNode=1' (no DockNodes, no DockIds honored).

2. The pre-run install writes the INI to disk, but HelloImGui's
   load_user_pref runs BEFORE post_init, so even a perfect on-disk
   INI doesn't get re-applied to the current session's dock state
   unless we call imgui.load_ini_settings_from_memory() after the
   first frame.

Two-part fix:

A. src/gui_2.py line 678: change default_imgui_window_type from
   'provide_full_screen_dock_space' to 'no_default_window'. Without
   the auto-created DockSpace, HelloImGui honors the INI's full
   docking tree structure.

B. src/gui_2.py _post_init (line 575): always call
   imgui.load_ini_settings_from_memory() after _install_default_layout
   runs, regardless of whether the cwd INI was empty. This re-applies
   the bundled INI to the live session after the first frame is
   rendered, so the panels are docked correctly on the current launch.

Layouts/default.ini: replace the simple 'DockSpace + 2 direct
DockNode children' structure (silently ignored by HelloImGui) with
the user's working nested DockNode tree (5-level deep), mapped to:
- LEFT column (DockNode 0x10, CentralNode=1): Theme, Project Settings,
  AI Settings, Files & Media, Operations Hub
- RIGHT column (DockNode 0x01): Discussion Hub, Log Management,
  Diagnostics

Verification (imgui.save_ini_settings_to_memory at runtime after
15s + first frame):
- LEFT column windows: Pos=0,28, Size=881,1697 (5 panels stacked)
- RIGHT column windows: Pos=883,28, Size=1183,1697 (3 panels stacked)
- [Docking][Data] block fully preserved (DockSpace + 8 DockNodes)
- All 8 panels docked (not floating)

Tests:
- tests/test_default_layout_install.py: 3/3 PASS
- tests/test_api_hooks_gui_health_live.py: 1/1 PASS
- tests/test_command_palette_sim.py: 7/7 PASS
- tests/test_saved_presets_sim.py: 2/2 PASS
- tests/test_live_gui_integration_v2.py: 3/3 PASS
This commit is contained in:
2026-06-30 07:30:44 -04:00
parent 670e255505
commit 5ab23f9eea
3 changed files with 60 additions and 147 deletions
+46 -45
View File
@@ -4,22 +4,19 @@
;;; missing/empty/small).
;;;
;;; Mechanism: HelloImGui reads this INI at app startup via the
;;; ini_folder_type/ini_filename on the RunnerParams. The DockSpace ID,
;;; DockNode IDs, and per-window DockId lines below tell HelloImgui where
;;; to place each panel. The literal IDs (0xAFC85805, 0x00000001,
;;; 0x00000002) match the runtime-generated MainDockSpace ID (decimal
;;; 2949142533) that HelloImGui computes deterministically per session.
;;; ini_folder_type/ini_filename on the RunnerParams. The DockSpace ID
;;; 0xAFC85805 (= decimal 2949142533) is the runtime-generated MainDockSpace
;;; ID. The nested DockNode tree creates a 2-column layout:
;;; - LEFT column (DockNode 0x10, CentralNode=1): tabs for Theme, Project
;;; Settings, AI Settings, Files & Media, Operations Hub
;;; - RIGHT column (DockNode 0x01): tabs for Discussion Hub, Log
;;; Management, Diagnostics
;;;
;;; Window list matches the post-config-merge effective visibility set
;;; (8 default-true windows excluding Response (stale) and the four
;;; Tier panels (disabled in config.toml)):
;;; Project Settings, Files & Media, AI Settings, AI operations,
;;; Discussion Hub, Operations Hub, Theme, Log Management, Diagnostics.
;;; Per-window DockId:
;;; 0x00000001,0..4 = left column tabs (Theme, Project Settings,
;;; AI Settings, Files & Media, Operations Hub)
;;; 0x00000002,0..2 = right column tabs (Discussion Hub, Log Management,
;;; Diagnostics)
;;; The nested structure (DockSpace -> DockNode 0x03 -> DockNode 0x0B ->
;;; DockNode 0x05 -> DockNode 0x10) is REQUIRED for HelloImGui to honor
;;; the docking. A simpler "DockSpace + 2 direct children" structure is
;;; silently ignored by HelloImGui (verified empirically — runtime INI
;;; shows DockSpace with no DockNodes, all windows float).
;;;
;;; All Collapsed=0 so the windows expand immediately on first render.
;;;
@@ -30,65 +27,70 @@
;;;
;;; To iterate on this layout: open sloppy.py, arrange windows as
;;; desired, quit (HelloImGui auto-saves), then copy the resulting
;;; cwd/manualslop_layout.ini over this one. (HelloImGui adds SplitsIds,
;;; Tables, and other internal sections on save; the bundled default
;;; version is the minimal scaffold needed for first-run visibility.)
;;; cwd/manualslop_layout.ini over this one.
;;;
[Window][Project Settings]
Pos=0,28
Size=481,1172
Size=881,1697
Collapsed=0
DockId=0x00000001,1
DockId=0x00000010,1
[Window][Files & Media]
Pos=0,28
Size=481,1172
Size=881,1697
Collapsed=0
DockId=0x00000001,3
DockId=0x00000010,2
[Window][AI Settings]
Pos=0,28
Size=481,1172
Size=881,1697
Collapsed=0
DockId=0x00000001,2
DockId=0x00000010,3
[Window][Operations Hub]
Pos=0,28
Size=481,1172
Size=881,1697
Collapsed=0
DockId=0x00000001,4
DockId=0x00000010,4
[Window][Theme]
Pos=0,28
Size=481,1172
Size=881,1697
Collapsed=0
DockId=0x00000010,0
[Window][Discussion Hub]
Pos=883,28
Size=1183,1697
Collapsed=0
DockId=0x00000001,0
[Window][Discussion Hub]
Pos=483,28
Size=1197,1172
Collapsed=0
DockId=0x00000002,0
[Window][Log Management]
Pos=483,28
Size=1197,1172
Pos=883,28
Size=1183,1697
Collapsed=0
DockId=0x00000002,1
DockId=0x00000001,1
[Window][Diagnostics]
Pos=483,28
Size=1197,1172
Pos=883,28
Size=1183,1697
Collapsed=0
DockId=0x00000002,2
DockId=0x00000001,2
[Docking][Data]
DockSpace ID=0xAFC85805 Window=0x079D3A04 Pos=0,28 Size=1680,1172 Split=X
DockNode ID=0x00000001 Parent=0xAFC85805 SizeRef=481,1172 CentralNode=1 Selected=0x3F1379AF
DockNode ID=0x00000002 Parent=0xAFC85805 SizeRef=1197,1172 Selected=0xB4CBF21A
DockSpace ID=0xAFC85805 Window=0x079D3A04 Pos=0,28 Size=1680,1172 Split=X
DockNode ID=0x00000003 Parent=0xAFC85805 SizeRef=2357,1183 Split=X
DockNode ID=0x0000000B Parent=0x00000003 SizeRef=404,1186 Split=X Selected=0xF4139CA2
DockNode ID=0x00000005 Parent=0x0000000B SizeRef=820,1681 Split=Y Selected=0x3F1379AF
DockNode ID=0x00000010 Parent=0x00000005 SizeRef=983,1140 CentralNode=1 Selected=0x3F1379AF
DockNode ID=0x00000011 Parent=0x00000005 SizeRef=983,184 Selected=0x432BAE4E
DockNode ID=0x00000006 Parent=0x0000000B SizeRef=1754,1681 Split=X Selected=0x6F2B5B04
DockNode ID=0x00000001 Parent=0x00000006 SizeRef=1183,1924 Selected=0xB4CBF21A
DockNode ID=0x00000002 Parent=0x00000006 SizeRef=569,1924 Selected=0x0D5A5273
DockNode ID=0x0000000D Parent=0x00000003 SizeRef=435,1186 Selected=0x363E93D6
DockNode ID=0x00000004 Parent=0xAFC85805 SizeRef=488,1183 Selected=0x3AEC3498
;;;<<<HelloImGui_Misc>>>;;;
[Layout]
Name=Default
[StatusBar]
@@ -97,5 +99,4 @@ ShowFps=true
[Theme]
Name=ImGuiColorsDark
;;;<<<SplitIds>>>;;;
{"gImGuiSplitIDs":{"MainDockSpace":2949142533}}
{"gImGuiSplitIDs":{"MainDockSpace":2949142533}}
-101
View File
@@ -1,101 +0,0 @@
;;;
;;; Manual Slop default docking layout for live_gui test sessions AND
;;; first-run production launches (when cwd/manualslop_layout.ini is
;;; missing/empty/small).
;;;
;;; Mechanism: HelloImGui reads this INI at app startup via the
;;; ini_folder_type/ini_filename on the RunnerParams. The DockSpace ID,
;;; DockNode IDs, and per-window DockId lines below tell HelloImgui where
;;; to place each panel. The literal IDs (0xAFC85805, 0x00000001,
;;; 0x00000002) match the runtime-generated MainDockSpace ID (decimal
;;; 2949142533) that HelloImGui computes deterministically per session.
;;;
;;; Window list matches the post-config-merge effective visibility set
;;; (8 default-true windows excluding Response (stale) and the four
;;; Tier panels (disabled in config.toml)):
;;; Project Settings, Files & Media, AI Settings, AI operations,
;;; Discussion Hub, Operations Hub, Theme, Log Management, Diagnostics.
;;; Per-window DockId:
;;; 0x00000001,0..4 = left column tabs (Theme, Project Settings,
;;; AI Settings, Files & Media, Operations Hub)
;;; 0x00000002,0..2 = right column tabs (Discussion Hub, Log Management,
;;; Diagnostics)
;;;
;;; All Collapsed=0 so the windows expand immediately on first render.
;;;
;;; This INI does NOT include any of the _STALE_WINDOW_NAMES from
;;; src/gui_2.py:603-607 (Projects, Files, Screenshots, Discussion History,
;;; Provider, Message, Response, Tool Calls, Comms History, System Prompts).
;;; _diag_layout_state will not emit a "stale window name" warning.
;;;
;;; To iterate on this layout: open sloppy.py, arrange windows as
;;; desired, quit (HelloImGui auto-saves), then copy the resulting
;;; cwd/manualslop_layout.ini over this one. (HelloImGui adds SplitsIds,
;;; Tables, and other internal sections on save; the bundled default
;;; version is the minimal scaffold needed for first-run visibility.)
;;;
[Window][Project Settings]
Pos=0,28
Size=481,1172
Collapsed=0
DockId=0x00000001,1
[Window][Files & Media]
Pos=0,28
Size=481,1172
Collapsed=0
DockId=0x00000001,3
[Window][AI Settings]
Pos=0,28
Size=481,1172
Collapsed=0
DockId=0x00000001,2
[Window][Operations Hub]
Pos=0,28
Size=481,1172
Collapsed=0
DockId=0x00000001,4
[Window][Theme]
Pos=0,28
Size=481,1172
Collapsed=0
DockId=0x00000001,0
[Window][Discussion Hub]
Pos=483,28
Size=1197,1172
Collapsed=0
DockId=0x00000002,0
[Window][Log Management]
Pos=483,28
Size=1197,1172
Collapsed=0
DockId=0x00000002,1
[Window][Diagnostics]
Pos=483,28
Size=1197,1172
Collapsed=0
DockId=0x00000002,2
[Docking][Data]
DockSpace ID=0xAFC85805 Window=0x079D3A04 Pos=0,28 Size=1680,1172 Split=X
DockNode ID=0x00000001 Parent=0xAFC85805 SizeRef=481,1172 CentralNode=1 Selected=0x3F1379AF
DockNode ID=0x00000002 Parent=0xAFC85805 SizeRef=1197,1172 Selected=0xB4CBF21A
;;;<<<HelloImGui_Misc>>>;;;
[Layout]
Name=Default
[StatusBar]
Show=false
ShowFps=true
[Theme]
Name=ImGuiColorsDark
;;;<<<SplitIds>>>;;;
{"gImGuiSplitIDs":{"MainDockSpace":2949142533}}
+14 -1
View File
@@ -580,6 +580,19 @@ class App:
if not install_result.ok:
if not hasattr(self, "_startup_timeline_errors"): self._startup_timeline_errors = []
self._startup_timeline_errors.append(("_install_default_layout", install_result.errors[0]))
# Always re-apply the bundled layout to the live imgui session after
# the first frame is rendered. HelloImGui reads ini_filename from disk
# BEFORE post_init fires (during immapp.run's load_user_pref phase),
# so even a perfect on-disk INI may not be honored unless we also
# apply it via imgui.load_ini_settings_from_memory here. The pre-run
# install writes the INI for the NEXT launch; this live apply
# makes the CURRENT launch render the bundled layout correctly.
try:
src_text = src_layout_path.read_text(encoding="utf-8", errors="replace")
imgui.load_ini_settings_from_memory(src_text)
except OSError as e:
if not hasattr(self, "_startup_timeline_errors"): self._startup_timeline_errors = []
self._startup_timeline_errors.append(("_post_init.live_apply", str(e)))
if hasattr(self.controller, "on_warmup_complete"):
cb_result = _post_init_callback_result(self)
if not cb_result.ok:
@@ -662,7 +675,7 @@ class App:
self.runner_params.imgui_window_params.enable_viewports = getattr(self, "ui_multi_viewport", False)
self.runner_params.imgui_window_params.remember_theme = True
self.runner_params.imgui_window_params.tweaked_theme = theme.get_tweaked_theme()
self.runner_params.imgui_window_params.default_imgui_window_type = hello_imgui.DefaultImGuiWindowType.provide_full_screen_dock_space
self.runner_params.imgui_window_params.default_imgui_window_type = hello_imgui.DefaultImGuiWindowType.no_default_window
# Enforce DPI Awareness and User Scale
user_scale = theme.get_current_scale()