progress on fixing up gui code
This commit is contained in:
@@ -131,7 +131,31 @@ max-locals = 8
|
||||
max-args = 5
|
||||
```
|
||||
|
||||
## 11. Structural Dependency Mapping (SDM)
|
||||
### 11. ImGui Defer Patterns
|
||||
|
||||
To prevent `PopID` or `End` leaks in immediate-mode rendering, and to keep code flat (0-1 levels of nesting) for AI agents, use the following patterns:
|
||||
|
||||
- **The Context Manager Pattern (Mandatory for complex blocks):**
|
||||
Wrap all `Begin/End` blocks in `imscope` context managers (from `src/imgui_scopes.py`).
|
||||
```python
|
||||
with imscope.window("My Window") as (exp, opened):
|
||||
if exp:
|
||||
imgui.text("Hello")
|
||||
|
||||
with imscope.tab_item("My Tab") as (exp, _):
|
||||
if exp:
|
||||
self._render_tab_content()
|
||||
```
|
||||
This adds only 1 space of indentation (project standard) and guarantees the corresponding `End` is called even on early returns or exceptions. **Crucial:** Always check the `exp` (expanded/visible) state before rendering content to avoid ID conflicts and performance overhead.
|
||||
|
||||
- **The Flat Dispatch Pattern (Recommended for the main loop):**
|
||||
To avoid nesting multiple window checks, use a dispatch helper that encapsulates the state check and the scope.
|
||||
```python
|
||||
self._render_window_if_open("My Window", self._render_my_panel)
|
||||
```
|
||||
This keeps the main GUI loop as a flat sequence of declarative calls.
|
||||
|
||||
## 12. Structural Dependency Mapping (SDM)
|
||||
|
||||
To assist AI agents in evaluating refactoring impact across dynamic codebases, all major definitions SHOULD include terse SDM tags at the end of their docstrings.
|
||||
|
||||
|
||||
@@ -54,6 +54,10 @@ This file tracks all major tracks for the project. Each track has its own detail
|
||||
*Link: [./tracks/context_comp_presets_20260510/](./tracks/context_comp_presets_20260510/)*
|
||||
*Goal: Implement Context Preset save/load with validation, and Context Preview before sending to agent.*
|
||||
|
||||
12. [ ] **Track: GUI Architecture Refinement & AI-Friendliness**
|
||||
*Link: [./tracks/gui_architecture_refinement_20260512/](./tracks/gui_architecture_refinement_20260512/)*
|
||||
*Goal: Reduce nesting and compactness of ImGui code in `gui_2.py`, and formalize ImGui Defer patterns.*
|
||||
|
||||
---
|
||||
|
||||
## Hot Reload Feature
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
# Plan: GUI Architecture Refinement & AI-Friendliness
|
||||
|
||||
**Track ID:** gui_architecture_refinement_20260512
|
||||
**Status:** [~] Draft
|
||||
|
||||
## Objective
|
||||
Reduce nesting and improve compactness of ImGui code in `gui_2.py` to make it more AI-friendly. Formalize the "defer/scope" patterns (inspired by Go's `defer` and Ryan Fleury's macros) in the project style guides to prevent `PopID` / `End` leaks.
|
||||
|
||||
## Background & Motivation
|
||||
The main GUI render loop (`_gui_func__abusrd_try_scope`) has grown to over 600 lines with deep nesting. Raw `imgui.begin()` and `imgui.end()` calls are prone to leaks if an early return occurs or if the return value of `begin` is ignored. While `imscope` context managers solve the leak issue, they still introduce nesting. We need a way to keep the code extremely flat (0-1 levels of nesting) while maintaining safety.
|
||||
|
||||
## Proposed Solution
|
||||
|
||||
### 1. Update Style Guides (`python.md` & `workflow.md`)
|
||||
Introduce a new section explicitly defining the "ImGui Defer Patterns":
|
||||
- **The Context Manager Pattern:** Use `with imscope.window("Name"):` to automatically handle `End()`. This adds only 1 space of indentation (per project rules).
|
||||
- **The Flat Dispatch Pattern:** To avoid nesting multiple windows, use dispatch helpers like `self._render_window_if_open(name, render_func)` which encapsulate the state-checking, `Begin`, `End`, and execution logic.
|
||||
|
||||
### 2. Implement Flat Dispatch Helper
|
||||
Create a helper method in `App`:
|
||||
```python
|
||||
def _render_window_if_open(self, name: str, render_func: Callable[[], None], flag_condition: bool = True) -> None:
|
||||
if not flag_condition or not self.show_windows.get(name, False): return
|
||||
with imscope.window(name, self.show_windows[name]) as (exp, opened):
|
||||
self.show_windows[name] = bool(opened)
|
||||
if exp: render_func()
|
||||
```
|
||||
|
||||
### 3. Refactor `gui_2.py`
|
||||
- Extract inline hub definitions (e.g., "Operations Hub", "Discussion Hub", "AI Settings") from `_gui_func__abusrd_try_scope` into dedicated methods (`_render_operations_hub`, etc.).
|
||||
- Replace the massive `if self.show_windows.get...` blocks in `_gui_func__abusrd_try_scope` with a flat sequence of `_render_window_if_open` calls.
|
||||
- Rename `_gui_func__abusrd_try_scope` to a cleaner name (e.g., `_gui_func_body`) once stabilized.
|
||||
|
||||
## Implementation Steps
|
||||
|
||||
1. [x] Edit `conductor/code_styleguides/python.md` to add "ImGui Defer Patterns" under the "AI-Agent Specific Conventions" or "Anti-OOP" section.
|
||||
2. [x] Edit `conductor/workflow.md` to reference the mandatory use of `imscope` or dispatch helpers for ImGui code.
|
||||
3. [x] Add `_render_window_if_open` to `gui_2.py`.
|
||||
4. [x] Extract `_render_operations_hub`, `_render_discussion_hub`, and `_render_ai_settings_hub` in `gui_2.py`.
|
||||
5. [x] Flatten `_gui_func__abusrd_try_scope` using the new helper.
|
||||
|
||||
## Verification & Testing
|
||||
- Ensure the app launches successfully without `PopID` errors.
|
||||
- Verify that toggling windows via the menu still opens and closes them correctly.
|
||||
- Run `uv run pytest tests/test_gui_startup_smoke.py` and `uv run pytest tests/test_gui_window_controls.py`.
|
||||
@@ -9,6 +9,7 @@
|
||||
- Use `./scripts/ai_style_formatter.py` for formatting validation
|
||||
- **NO COMMENTS** unless explicitly requested
|
||||
- Type hints required for all public functions
|
||||
- **ImGui Defer Patterns:** Use `imscope` context managers or `_render_window_if_open` dispatch helpers to prevent resource leaks and keep the main loop flat. See `conductor/code_styleguides/python.md` for details.
|
||||
|
||||
### CRITICAL: Native Edit Tool Destroys Indentation
|
||||
|
||||
|
||||
+91
-182
@@ -653,6 +653,67 @@ class App:
|
||||
imgui.pop_style_var(2)
|
||||
imgui.pop_id()
|
||||
|
||||
def _render_window_if_open(self, name: str, render_func: Callable[[], None], flag_condition: bool = True) -> None:
|
||||
"""Helper to render a window only if its toggle is active."""
|
||||
if not flag_condition or not self.show_windows.get(name, False): return
|
||||
with imscope.window(name, self.show_windows[name]) as (exp, opened):
|
||||
self.show_windows[name] = bool(opened)
|
||||
if exp: render_func()
|
||||
|
||||
def _render_project_settings_hub(self) -> None:
|
||||
with imscope.tab_bar('context_hub_tabs'):
|
||||
with imscope.tab_item('Projects'): self._render_projects_panel()
|
||||
with imscope.tab_item('Paths'): self._render_paths_panel()
|
||||
|
||||
def _render_ai_settings_hub(self) -> None:
|
||||
self._render_persona_selector_panel()
|
||||
if imgui.collapsing_header("Provider & Model"): self._render_provider_panel()
|
||||
if imgui.collapsing_header("System Prompts"): self._render_system_prompts_panel()
|
||||
if imgui.collapsing_header("RAG Settings"): self._render_rag_panel()
|
||||
self._render_agent_tools_panel()
|
||||
|
||||
def _render_discussion_hub(self) -> None:
|
||||
with imscope.tab_bar("discussion_hub_tabs"):
|
||||
with imscope.tab_item("Discussion"): self._render_discussion_tab()
|
||||
with imscope.tab_item("Context Composition"): self._render_context_composition_panel()
|
||||
with imscope.tab_item("Snapshot"): self._render_snapshot_tab()
|
||||
with imscope.tab_item("Takes"): self._render_takes_panel()
|
||||
|
||||
def _render_operations_hub(self) -> None:
|
||||
imgui.push_style_var(imgui.StyleVar_.item_spacing, imgui.ImVec2(10, 4))
|
||||
ch1, self.ui_separate_tool_calls_panel = imgui.checkbox("Pop Out Tool Calls", self.ui_separate_tool_calls_panel)
|
||||
if ch1: self.show_windows["Tool Calls"] = self.ui_separate_tool_calls_panel
|
||||
imgui.same_line()
|
||||
ch2, self.ui_separate_usage_analytics = imgui.checkbox("Pop Out Usage Analytics", self.ui_separate_usage_analytics)
|
||||
if ch2: self.show_windows["Usage Analytics"] = self.ui_separate_usage_analytics
|
||||
imgui.same_line()
|
||||
ch3, self.ui_separate_external_tools = imgui.checkbox('Pop Out External Tools', self.ui_separate_external_tools)
|
||||
if ch3: self.show_windows['External Tools'] = self.ui_separate_external_tools
|
||||
imgui.pop_style_var()
|
||||
show_tc_tab, show_usage_tab = not self.ui_separate_tool_calls_panel, not self.ui_separate_usage_analytics
|
||||
with imscope.tab_bar("ops_tabs"):
|
||||
with imscope.tab_item("Comms History"): self._render_comms_history_panel()
|
||||
if show_tc_tab:
|
||||
with imscope.tab_item("Tool Calls"): self._render_tool_calls_panel()
|
||||
if show_usage_tab:
|
||||
with imscope.tab_item("Usage Analytics"): self._render_usage_analytics_panel()
|
||||
if not self.ui_separate_external_tools:
|
||||
with imscope.tab_item("External Tools"):
|
||||
self._render_external_tools_panel()
|
||||
imgui.separator(); imgui.text("")
|
||||
try: self._render_external_editor_panel()
|
||||
except Exception as e: imgui.text_colored(vec4(1, 0.3, 0.3, 1), f"Error: {str(e)}")
|
||||
with imscope.tab_item("Workspace Layouts"):
|
||||
imgui.text("Experimental: Auto-switch layout by Tier")
|
||||
ch, self.controller.ui_auto_switch_layout = imgui.checkbox("Enable Auto-Switch", self.controller.ui_auto_switch_layout)
|
||||
if self.controller.ui_auto_switch_layout:
|
||||
imgui.separator(); imgui.text("Tier Bindings (select profile for each tier)")
|
||||
profiles = [""] + [p.name for p in self.controller.workspace_profiles.values()]
|
||||
for t in ["Tier 1", "Tier 2", "Tier 3", "Tier 4"]:
|
||||
curr = self.controller.ui_tier_layout_bindings.get(t, ""); idx = profiles.index(curr) if curr in profiles else 0
|
||||
ch_combo, new_idx = imgui.combo(t, idx, profiles)
|
||||
if ch_combo: self.controller.ui_tier_layout_bindings[t] = profiles[new_idx]
|
||||
|
||||
def _show_menus(self) -> None:
|
||||
"""
|
||||
[C: tests/test_gui_window_controls.py:test_gui_window_controls_minimize_maximize_close]
|
||||
@@ -732,16 +793,16 @@ class App:
|
||||
|
||||
if hwnd:
|
||||
btn_w = 40
|
||||
display_w = imgui.get_io().display_size.x
|
||||
right_x = display_w - (btn_w * 3)
|
||||
# Use window width (points) instead of display_size (pixels) for correct scaling
|
||||
window_w = imgui.get_window_width()
|
||||
bar_h = imgui.get_window_height()
|
||||
right_x = window_w - (btn_w * 3)
|
||||
|
||||
# Drag area check using an explicit invisible button spanning the empty space
|
||||
curr_x = imgui.get_cursor_pos_x()
|
||||
drag_w = right_x - curr_x
|
||||
if drag_w > 0:
|
||||
# Use a small positive height to satisfy IM_ASSERT(size_arg.y != 0.0f)
|
||||
# The menu bar naturally constrains the hit box height anyway.
|
||||
imgui.invisible_button("##drag_area", (drag_w, 20.0))
|
||||
imgui.invisible_button("##drag_area", (drag_w, bar_h))
|
||||
if imgui.is_item_active() and imgui.is_mouse_dragging(0):
|
||||
# CRITICAL: We must reset ImGui's mouse_down state BEFORE passing control to Windows.
|
||||
# Otherwise, the Windows modal drag loop swallows the WM_LBUTTONUP event,
|
||||
@@ -757,17 +818,18 @@ class App:
|
||||
except Exception:
|
||||
is_max = False
|
||||
|
||||
imgui.set_cursor_pos_x(right_x)
|
||||
if imgui.button("_", (btn_w, 0)):
|
||||
# Explicitly set Y to 0 and match button height to bar height for perfect alignment
|
||||
imgui.set_cursor_pos((right_x, 0))
|
||||
if imgui.button("_", (btn_w, bar_h)):
|
||||
win32gui.ShowWindow(hwnd, win32con.SW_MINIMIZE)
|
||||
|
||||
imgui.set_cursor_pos_x(right_x + btn_w)
|
||||
if imgui.button("[=]" if is_max else "[]", (btn_w, 0)):
|
||||
imgui.set_cursor_pos((right_x + btn_w, 0))
|
||||
if imgui.button("[=]" if is_max else "[]", (btn_w, bar_h)):
|
||||
win32gui.ShowWindow(hwnd, win32con.SW_RESTORE if is_max else win32con.SW_MAXIMIZE)
|
||||
|
||||
imgui.set_cursor_pos_x(right_x + btn_w * 2)
|
||||
imgui.set_cursor_pos((right_x + btn_w * 2, 0))
|
||||
imgui.push_style_color(imgui.Col_.button_hovered, vec4(200, 50, 50, 255))
|
||||
if imgui.button("X", (btn_w, 0)):
|
||||
if imgui.button("X", (btn_w, bar_h)):
|
||||
win32gui.PostMessage(hwnd, win32con.WM_CLOSE, 0, 0)
|
||||
imgui.pop_style_color()
|
||||
|
||||
@@ -985,182 +1047,29 @@ class App:
|
||||
else: self._tool_log_cache = log_raw
|
||||
self._tool_log_dirty = False
|
||||
|
||||
#region: Project Settings
|
||||
if self.show_windows.get("Project Settings", False):
|
||||
with imscope.window("Project Settings", self.show_windows["Project Settings"]) as (exp, opened):
|
||||
self.show_windows["Project Settings"] = bool(opened)
|
||||
if exp and imscope.tab_bar('context_hub_tabs'):
|
||||
if imscope.tab_item('Projects'): self._render_projects_panel()
|
||||
if imscope.tab_item('Paths'): self._render_paths_panel()
|
||||
#endregion: Project Settings
|
||||
self._render_window_if_open("Project Settings", self._render_project_settings_hub)
|
||||
self._render_window_if_open("Files & Media", self._render_files_and_media)
|
||||
self._render_window_if_open("AI Settings", self._render_ai_settings_hub)
|
||||
self._render_window_if_open("Usage Analytics", self._render_usage_analytics_panel, self.ui_separate_usage_analytics)
|
||||
self._render_window_if_open("MMA Dashboard", self._render_mma_dashboard)
|
||||
self._render_window_if_open("Task DAG", self._render_task_dag_panel, self.ui_separate_task_dag)
|
||||
|
||||
#region: Files & Media window
|
||||
if self.show_windows.get("Files & Media", False):
|
||||
exp, opened = imgui.begin("Files & Media", self.show_windows["Files & Media"])
|
||||
self.show_windows["Files & Media"] = bool(opened)
|
||||
if opened and exp: self._render_files_and_media()
|
||||
imgui.end()
|
||||
#endregion: Files & Media window
|
||||
|
||||
#region: AI Settings
|
||||
if self.show_windows.get("AI Settings", False):
|
||||
with imscope.window("AI Settings", self.show_windows["AI Settings"]) as (exp, opened):
|
||||
self.show_windows["AI Settings"] = bool(opened)
|
||||
if exp:
|
||||
self._render_persona_selector_panel()
|
||||
if imgui.collapsing_header("Provider & Model"): self._render_provider_panel()
|
||||
if imgui.collapsing_header("System Prompts"): self._render_system_prompts_panel()
|
||||
if imgui.collapsing_header("RAG Settings"): self._render_rag_panel()
|
||||
self._render_agent_tools_panel()
|
||||
#endregion: AI Settings
|
||||
|
||||
if self.ui_separate_usage_analytics and self.show_windows.get("Usage Analytics", False):
|
||||
exp, opened = imgui.begin("Usage Analytics", self.show_windows["Usage Analytics"])
|
||||
self.show_windows["Usage Analytics"] = bool(opened)
|
||||
if exp:
|
||||
self._render_usage_analytics_panel()
|
||||
imgui.end()
|
||||
|
||||
if self.show_windows.get("MMA Dashboard", False):
|
||||
exp, opened = imgui.begin("MMA Dashboard", self.show_windows["MMA Dashboard"])
|
||||
self.show_windows["MMA Dashboard"] = bool(opened)
|
||||
if exp:
|
||||
if self.perf_profiling_enabled: self.perf_monitor.start_component("_render_mma_dashboard")
|
||||
self._render_mma_dashboard()
|
||||
if self.perf_profiling_enabled: self.perf_monitor.end_component("_render_mma_dashboard")
|
||||
imgui.end()
|
||||
|
||||
#region: Seprate Task Dag to Tier 4
|
||||
if self.ui_separate_task_dag and self.show_windows.get("Task DAG", False):
|
||||
exp, opened = imgui.begin("Task DAG", self.show_windows["Task DAG"])
|
||||
self.show_windows["Task DAG"] = bool(opened)
|
||||
if exp: self._render_task_dag_panel()
|
||||
imgui.end()
|
||||
|
||||
if self.ui_separate_tier1 and self.show_windows.get("Tier 1: Strategy", False):
|
||||
exp, opened = imgui.begin("Tier 1: Strategy", self.show_windows["Tier 1: Strategy"])
|
||||
self.show_windows["Tier 1: Strategy"] = bool(opened)
|
||||
if exp: self._render_tier_stream_panel("Tier 1", "Tier 1")
|
||||
imgui.end()
|
||||
|
||||
if self.ui_separate_tier2 and self.show_windows.get("Tier 2: Tech Lead", False):
|
||||
exp, opened = imgui.begin("Tier 2: Tech Lead", self.show_windows["Tier 2: Tech Lead"])
|
||||
self.show_windows["Tier 2: Tech Lead"] = bool(opened)
|
||||
if exp: self._render_tier_stream_panel("Tier 2", "Tier 2 (Tech Lead)")
|
||||
imgui.end()
|
||||
|
||||
if self.ui_separate_tier3 and self.show_windows.get("Tier 3: Workers", False):
|
||||
exp, opened = imgui.begin("Tier 3: Workers", self.show_windows["Tier 3: Workers"])
|
||||
self.show_windows["Tier 3: Workers"] = bool(opened)
|
||||
if exp: self._render_tier_stream_panel("Tier 3", None)
|
||||
imgui.end()
|
||||
|
||||
if self.ui_separate_tier4 and self.show_windows.get("Tier 4: QA", False):
|
||||
exp, opened = imgui.begin("Tier 4: QA", self.show_windows["Tier 4: QA"])
|
||||
self.show_windows["Tier 4: QA"] = bool(opened)
|
||||
if exp: self._render_tier_stream_panel("Tier 4", "Tier 4 (QA)")
|
||||
imgui.end()
|
||||
#endregion: Separate Task Dag to Tier 4
|
||||
self._render_window_if_open("Tier 1: Strategy", lambda: self._render_tier_stream_panel("Tier 1", "Tier 1"), self.ui_separate_tier1)
|
||||
self._render_window_if_open("Tier 2: Tech Lead", lambda: self._render_tier_stream_panel("Tier 2", "Tier 2 (Tech Lead)"), self.ui_separate_tier2)
|
||||
self._render_window_if_open("Tier 3: Workers", lambda: self._render_tier_stream_panel("Tier 3", None), self.ui_separate_tier3)
|
||||
self._render_window_if_open("Tier 4: QA", lambda: self._render_tier_stream_panel("Tier 4", "Tier 4 (QA)"), self.ui_separate_tier4)
|
||||
|
||||
if self.show_windows.get("Theme", False): self._render_theme_panel()
|
||||
|
||||
#region: Discussion Hub
|
||||
if self.show_windows.get("Discussion Hub", False):
|
||||
with imscope.window("Discussion Hub", self.show_windows["Discussion Hub"]) as (exp, opened):
|
||||
self.show_windows["Discussion Hub"] = bool(opened)
|
||||
if exp:
|
||||
if imscope.tab_bar("discussion_hub_tabs"):
|
||||
if imscope.tab_item("Discussion"):
|
||||
self._render_discussion_tab()
|
||||
if imscope.tab_item("Context Composition"):
|
||||
self._render_context_composition_panel()
|
||||
if imscope.tab_item("Snapshot"):
|
||||
self._render_snapshot_tab()
|
||||
if imscope.tab_item("Takes"):
|
||||
self._render_takes_panel()
|
||||
#endregion: Discussion Hub
|
||||
self._render_window_if_open("Discussion Hub", self._render_discussion_hub)
|
||||
self._render_window_if_open("Operations Hub", self._render_operations_hub)
|
||||
|
||||
#region: Operations Hub
|
||||
if self.show_windows.get("Operations Hub", False):
|
||||
exp, opened = imgui.begin("Operations Hub", self.show_windows["Operations Hub"])
|
||||
self.show_windows["Operations Hub"] = bool(opened)
|
||||
if exp:
|
||||
imgui.push_style_var(imgui.StyleVar_.item_spacing, imgui.ImVec2(10, 4))
|
||||
ch1, self.ui_separate_tool_calls_panel = imgui.checkbox("Pop Out Tool Calls", self.ui_separate_tool_calls_panel)
|
||||
if ch1: self.show_windows["Tool Calls"] = self.ui_separate_tool_calls_panel
|
||||
imgui.same_line()
|
||||
ch2, self.ui_separate_usage_analytics = imgui.checkbox("Pop Out Usage Analytics", self.ui_separate_usage_analytics)
|
||||
if ch2: self.show_windows["Usage Analytics"] = self.ui_separate_usage_analytics
|
||||
imgui.same_line()
|
||||
ch3, self.ui_separate_external_tools = imgui.checkbox('Pop Out External Tools', self.ui_separate_external_tools)
|
||||
if ch3: self.show_windows['External Tools'] = self.ui_separate_external_tools
|
||||
imgui.pop_style_var()
|
||||
|
||||
show_tc_tab = not self.ui_separate_tool_calls_panel
|
||||
show_usage_tab = not self.ui_separate_usage_analytics
|
||||
|
||||
with imscope.tab_bar("ops_tabs"):
|
||||
with imscope.tab_item("Comms History"): self._render_comms_history_panel()
|
||||
if show_tc_tab:
|
||||
with imscope.tab_item("Tool Calls"): self._render_tool_calls_panel()
|
||||
if show_usage_tab:
|
||||
with imscope.tab_item("Usage Analytics"): self._render_usage_analytics_panel()
|
||||
if not self.ui_separate_external_tools:
|
||||
with imscope.tab_item("External Tools"):
|
||||
self._render_external_tools_panel()
|
||||
imgui.separator()
|
||||
imgui.text("")
|
||||
try:
|
||||
self._render_external_editor_panel()
|
||||
except Exception as e:
|
||||
imgui.text_colored(vec4(1, 0.3, 0.3, 1), f"Error: {str(e)}")
|
||||
with imscope.tab_item("Workspace Layouts"):
|
||||
imgui.text("Experimental: Auto-switch layout by Tier")
|
||||
ch, self.controller.ui_auto_switch_layout = imgui.checkbox("Enable Auto-Switch", self.controller.ui_auto_switch_layout)
|
||||
if self.controller.ui_auto_switch_layout:
|
||||
imgui.separator()
|
||||
imgui.text("Tier Bindings (select profile for each tier)")
|
||||
profiles = [""] + [p.name for p in self.controller.workspace_profiles.values()]
|
||||
for t in ["Tier 1", "Tier 2", "Tier 3", "Tier 4"]:
|
||||
curr = self.controller.ui_tier_layout_bindings.get(t, "")
|
||||
idx = profiles.index(curr) if curr in profiles else 0
|
||||
ch_combo, new_idx = imgui.combo(t, idx, profiles)
|
||||
if ch_combo: self.controller.ui_tier_layout_bindings[t] = profiles[new_idx]
|
||||
imgui.end()
|
||||
#endregion: Operations Hub
|
||||
|
||||
#region: Separate Message, Response, Tool Calls, External Tools
|
||||
if self.ui_separate_message_panel and self.show_windows.get("Message", False):
|
||||
exp, opened = imgui.begin("Message", self.show_windows["Message"])
|
||||
self.show_windows["Message"] = bool(opened)
|
||||
if exp: self._render_message_panel()
|
||||
imgui.end()
|
||||
|
||||
if self.ui_separate_response_panel and self.show_windows.get("Response", False):
|
||||
exp, opened = imgui.begin("Response", self.show_windows["Response"])
|
||||
self.show_windows["Response"] = bool(opened)
|
||||
if exp: self._render_response_panel()
|
||||
imgui.end()
|
||||
|
||||
if self.ui_separate_tool_calls_panel and self.show_windows.get("Tool Calls", False):
|
||||
exp, opened = imgui.begin("Tool Calls", self.show_windows["Tool Calls"])
|
||||
self.show_windows["Tool Calls"] = bool(opened)
|
||||
if exp: self._render_tool_calls_panel()
|
||||
imgui.end()
|
||||
|
||||
if self.ui_separate_external_tools and self.show_windows.get('External Tools', False):
|
||||
exp, opened = imgui.begin('External Tools', self.show_windows['External Tools'])
|
||||
self.show_windows['External Tools'] = bool(opened)
|
||||
if exp: self._render_external_tools_panel()
|
||||
imgui.end()
|
||||
|
||||
if self.show_windows.get("Log Management", False):
|
||||
if self.perf_profiling_enabled: self.perf_monitor.start_component("_render_log_management")
|
||||
self._render_log_management()
|
||||
if self.perf_profiling_enabled: self.perf_monitor.end_component("_render_log_management")
|
||||
#endregion: Separate Message, Response, Tool Calls, External Tools
|
||||
|
||||
if self.show_windows.get("Diagnostics", False): self._render_diagnostics_panel()
|
||||
self._render_window_if_open("Message", self._render_message_panel, self.ui_separate_message_panel)
|
||||
self._render_window_if_open("Response", self._render_response_panel, self.ui_separate_response_panel)
|
||||
self._render_window_if_open("Tool Calls", self._render_tool_calls_panel, self.ui_separate_tool_calls_panel)
|
||||
self._render_window_if_open("External Tools", self._render_external_tools_panel, self.ui_separate_external_tools)
|
||||
self._render_window_if_open("Log Management", self._render_log_management)
|
||||
self._render_window_if_open("Diagnostics", self._render_diagnostics_panel)
|
||||
|
||||
self.perf_monitor.end_frame()
|
||||
|
||||
|
||||
+27
-9
@@ -24,7 +24,8 @@ class _ScopeChild:
|
||||
self._sy = size_y
|
||||
self._flags = flags
|
||||
def __enter__(self):
|
||||
return imgui.begin_child(self._id, self._sx, self._sy, self._flags)
|
||||
res = imgui.begin_child(self._id, self._sx, self._sy, self._flags)
|
||||
return res
|
||||
def __exit__(self, *args):
|
||||
imgui.end_child()
|
||||
return False
|
||||
@@ -35,17 +36,24 @@ class _ScopeTable:
|
||||
self._name = name
|
||||
self._columns = columns
|
||||
self._flags = flags
|
||||
self._active = False
|
||||
def __enter__(self):
|
||||
return imgui.begin_table(self._name, self._columns, self._flags)
|
||||
self._active = imgui.begin_table(self._name, self._columns, self._flags)
|
||||
return self._active
|
||||
def __exit__(self, *args):
|
||||
if self._active:
|
||||
imgui.end_table()
|
||||
return False
|
||||
|
||||
def menu_bar(): return _ScopeMenuBar()
|
||||
class _ScopeMenuBar:
|
||||
def __init__(self):
|
||||
self._active = False
|
||||
def __enter__(self):
|
||||
return imgui.begin_menu_bar()
|
||||
self._active = imgui.begin_menu_bar()
|
||||
return self._active
|
||||
def __exit__(self, *args):
|
||||
if self._active:
|
||||
imgui.end_menu_bar()
|
||||
return False
|
||||
|
||||
@@ -53,9 +61,12 @@ def menu(label: str): return _ScopeMenu(label)
|
||||
class _ScopeMenu:
|
||||
def __init__(self, label: str):
|
||||
self._label = label
|
||||
self._active = False
|
||||
def __enter__(self):
|
||||
return imgui.begin_menu(self._label)
|
||||
self._active = imgui.begin_menu(self._label)
|
||||
return self._active
|
||||
def __exit__(self, *args):
|
||||
if self._active:
|
||||
imgui.end_menu()
|
||||
return False
|
||||
|
||||
@@ -63,9 +74,12 @@ def popup(id_str: str): return _ScopePopup(id_str)
|
||||
class _ScopePopup:
|
||||
def __init__(self, id_str: str):
|
||||
self._id = id_str
|
||||
self._active = False
|
||||
def __enter__(self):
|
||||
return imgui.begin_popup(self._id)
|
||||
self._active = imgui.begin_popup(self._id)
|
||||
return self._active
|
||||
def __exit__(self, *args):
|
||||
if self._active:
|
||||
imgui.end_popup()
|
||||
return False
|
||||
|
||||
@@ -120,9 +134,12 @@ class _ScopeTabBar:
|
||||
def __init__(self, id_str: str, flags: int):
|
||||
self._id = id_str
|
||||
self._flags = flags
|
||||
self._active = False
|
||||
def __enter__(self):
|
||||
return imgui.begin_tab_bar(self._id, self._flags)
|
||||
self._active = imgui.begin_tab_bar(self._id, self._flags)
|
||||
return self._active
|
||||
def __exit__(self, *args):
|
||||
if self._active:
|
||||
imgui.end_tab_bar()
|
||||
return False
|
||||
|
||||
@@ -131,11 +148,12 @@ class _ScopeTabItem:
|
||||
def __init__(self, label: str, flags: int):
|
||||
self._label = label
|
||||
self._flags = flags
|
||||
self._expanded = False
|
||||
self._open = None
|
||||
def __enter__(self):
|
||||
exp, self._open = imgui.begin_tab_item(self._label, None, self._flags)
|
||||
return exp, self._open
|
||||
self._expanded, self._open = imgui.begin_tab_item(self._label, None, self._flags)
|
||||
return self._expanded, self._open
|
||||
def __exit__(self, *args):
|
||||
if self._open:
|
||||
if self._expanded:
|
||||
imgui.end_tab_item()
|
||||
return False
|
||||
|
||||
Reference in New Issue
Block a user