96 lines
3.1 KiB
Markdown
96 lines
3.1 KiB
Markdown
# ImGui Context Manager Suite Design
|
|
|
|
## Status
|
|
|
|
Proposed — 2026-05-11
|
|
|
|
## Context
|
|
|
|
The `src/gui_2.py` file contains ~50 `imgui.begin()` / `imgui.end()` pairs scattered across 5900+ lines. Dear PyGui (and ImGui) uses a procedural API where every `begin_X()` requires a matching `end_X()`. This creates two problems:
|
|
|
|
1. **Error-prone for AI agents** — forgetting an `end()` call causes UI nesting bugs that are hard to trace
|
|
2. **Visual sprawl** — the begin/end pairing is separated by potentially hundreds of lines, making scope boundaries unclear
|
|
|
|
## Decision
|
|
|
|
Implement a context manager suite that pairs `begin` and `end` calls on the same line using Python's `with` statement.
|
|
|
|
## Implementation
|
|
|
|
### Core Base Class
|
|
|
|
```python
|
|
class ImGuiScope:
|
|
def __init__(self, begin_fn, end_fn, *args, **kwargs):
|
|
self._begin_fn = begin_fn
|
|
self._end_fn = end_fn
|
|
self._args = args
|
|
self._kwargs = kwargs
|
|
self._opened = None
|
|
self._entered = False
|
|
|
|
def __enter__(self):
|
|
result = self._begin_fn(*self._args, **self._kwargs)
|
|
if isinstance(result, tuple):
|
|
self._opened = result[0]
|
|
else:
|
|
self._opened = result
|
|
self._entered = bool(self._opened)
|
|
return self._opened
|
|
|
|
def __exit__(self, *args):
|
|
if self._entered:
|
|
self._end_fn()
|
|
return False
|
|
```
|
|
|
|
### Scope Helpers
|
|
|
|
| Function | Wraps | Signature |
|
|
|----------|-------|-----------|
|
|
| `imgui_window(name, visible=True, flags=0)` | `imgui.begin` | `__enter__` returns `opened` bool |
|
|
| `imgui_table(name, columns, flags=0)` | `imgui.begin_table` | `__enter__` returns `opened` bool |
|
|
| `imgui_menu_bar()` | `imgui.begin_menu_bar` | No args |
|
|
| `imgui_menu(label)` | `imgui.begin_menu` | `__enter__` returns `opened` bool |
|
|
| `imgui_child(id, width=0, height=0, flags=0)` | `imgui.begin_child` | `__enter__` returns `opened` bool |
|
|
| `imgui_group()` | `imgui.begin_group` | No args |
|
|
| `imgui_popup(id)` | `imgui.begin_popup` | `__enter__` returns `opened` bool |
|
|
| `imgui_tooltip()` | `imgui.begin_tooltip` | No args |
|
|
| `imgui_clipper(count)` | `clipper.begin` | `__enter__` returns `opened` count |
|
|
| `node_editor_scope(name)` | `ed.begin` | `__enter__` returns `opened` bool |
|
|
|
|
### Usage Pattern
|
|
|
|
```python
|
|
# Before
|
|
exp, opened = imgui.begin("AI Settings", self.show_windows["AI Settings"])
|
|
if exp:
|
|
imgui.text("Settings")
|
|
imgui.separator()
|
|
# ... 50 more lines ...
|
|
imgui.end()
|
|
|
|
# After
|
|
if imgui_window("AI Settings", self.show_windows["AI Settings"], flags):
|
|
imgui.text("Settings")
|
|
imgui.separator()
|
|
# ... 50 more lines ...
|
|
# imgui.end() called automatically
|
|
```
|
|
|
|
## File Location
|
|
|
|
`src/imgui_scopes.py`
|
|
|
|
## Migration Strategy
|
|
|
|
1. New code MUST use context managers
|
|
2. Existing code migrates incrementally during bug fixes and feature work
|
|
3. No强制性 — old `begin()`/`end()` calls remain valid
|
|
|
|
## Consequences
|
|
|
|
- **Reduced** scope pairing errors
|
|
- **Improved** code legibility for AI agents
|
|
- **Slight** line count reduction (one `imgui.end()` line saved per scope)
|
|
- **No** runtime performance impact (imperceptible nanoseconds vs C++ binding calls) |