imgui_debugger 0.1.0__tar.gz → 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- imgui_debugger-0.2.0/PKG-INFO +398 -0
- imgui_debugger-0.2.0/README.md +371 -0
- {imgui_debugger-0.1.0 → imgui_debugger-0.2.0}/pyproject.toml +1 -1
- {imgui_debugger-0.1.0 → imgui_debugger-0.2.0}/src/imgui_debugger/__init__.py +132 -88
- {imgui_debugger-0.1.0 → imgui_debugger-0.2.0}/src/imgui_debugger/debugger.py +20 -97
- imgui_debugger-0.2.0/src/imgui_debugger/native.py +200 -0
- imgui_debugger-0.2.0/src/imgui_debugger/panel.py +342 -0
- {imgui_debugger-0.1.0 → imgui_debugger-0.2.0}/src/imgui_debugger/runner.py +132 -66
- imgui_debugger-0.2.0/src/imgui_debugger/style.py +593 -0
- imgui_debugger-0.2.0/src/imgui_debugger/tools.py +254 -0
- imgui_debugger-0.2.0/src/imgui_debugger.egg-info/PKG-INFO +398 -0
- {imgui_debugger-0.1.0 → imgui_debugger-0.2.0}/src/imgui_debugger.egg-info/SOURCES.txt +8 -1
- {imgui_debugger-0.1.0 → imgui_debugger-0.2.0}/tests/test_doctests.py +31 -27
- imgui_debugger-0.2.0/tests/test_headless_render.py +264 -0
- imgui_debugger-0.2.0/tests/test_panel.py +99 -0
- imgui_debugger-0.2.0/tests/test_style.py +88 -0
- imgui_debugger-0.2.0/tests/test_tools.py +89 -0
- imgui_debugger-0.1.0/PKG-INFO +0 -225
- imgui_debugger-0.1.0/README.md +0 -198
- imgui_debugger-0.1.0/src/imgui_debugger.egg-info/PKG-INFO +0 -225
- imgui_debugger-0.1.0/tests/test_headless_render.py +0 -123
- {imgui_debugger-0.1.0 → imgui_debugger-0.2.0}/LICENSE +0 -0
- {imgui_debugger-0.1.0 → imgui_debugger-0.2.0}/setup.cfg +0 -0
- {imgui_debugger-0.1.0 → imgui_debugger-0.2.0}/src/imgui_debugger/_assets.py +0 -0
- {imgui_debugger-0.1.0 → imgui_debugger-0.2.0}/src/imgui_debugger/edit.py +0 -0
- {imgui_debugger-0.1.0 → imgui_debugger-0.2.0}/src/imgui_debugger/format.py +0 -0
- {imgui_debugger-0.1.0 → imgui_debugger-0.2.0}/src/imgui_debugger/py.typed +0 -0
- {imgui_debugger-0.1.0 → imgui_debugger-0.2.0}/src/imgui_debugger/scopes.py +0 -0
- {imgui_debugger-0.1.0 → imgui_debugger-0.2.0}/src/imgui_debugger/search.py +0 -0
- {imgui_debugger-0.1.0 → imgui_debugger-0.2.0}/src/imgui_debugger/theme.py +0 -0
- {imgui_debugger-0.1.0 → imgui_debugger-0.2.0}/src/imgui_debugger/tree.py +0 -0
- {imgui_debugger-0.1.0 → imgui_debugger-0.2.0}/src/imgui_debugger.egg-info/dependency_links.txt +0 -0
- {imgui_debugger-0.1.0 → imgui_debugger-0.2.0}/src/imgui_debugger.egg-info/requires.txt +0 -0
- {imgui_debugger-0.1.0 → imgui_debugger-0.2.0}/src/imgui_debugger.egg-info/top_level.txt +0 -0
- {imgui_debugger-0.1.0 → imgui_debugger-0.2.0}/tests/test_assets.py +0 -0
- {imgui_debugger-0.1.0 → imgui_debugger-0.2.0}/tests/test_debugger.py +0 -0
- {imgui_debugger-0.1.0 → imgui_debugger-0.2.0}/tests/test_edit.py +0 -0
- {imgui_debugger-0.1.0 → imgui_debugger-0.2.0}/tests/test_format.py +0 -0
- {imgui_debugger-0.1.0 → imgui_debugger-0.2.0}/tests/test_scopes.py +0 -0
- {imgui_debugger-0.1.0 → imgui_debugger-0.2.0}/tests/test_search.py +0 -0
- {imgui_debugger-0.1.0 → imgui_debugger-0.2.0}/tests/test_theme.py +0 -0
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: imgui_debugger
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: A live variable inspector you can drop into any imgui-bundle widget.
|
|
5
|
+
Author-email: Flynn OConnell <flynnoconnell@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/FlynnOConnell/imgui_debugger
|
|
8
|
+
Project-URL: Source, https://github.com/FlynnOConnell/imgui_debugger
|
|
9
|
+
Project-URL: Issues, https://github.com/FlynnOConnell/imgui_debugger/issues
|
|
10
|
+
Keywords: imgui,imgui-bundle,hello-imgui,debugger,inspector,gui,widget
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
15
|
+
Classifier: Topic :: Software Development :: Debuggers
|
|
16
|
+
Classifier: Topic :: Software Development :: User Interfaces
|
|
17
|
+
Requires-Python: >=3.10
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
License-File: LICENSE
|
|
20
|
+
Requires-Dist: imgui-bundle<2,>=1.92
|
|
21
|
+
Provides-Extra: dev
|
|
22
|
+
Requires-Dist: pytest>=7; extra == "dev"
|
|
23
|
+
Provides-Extra: docs
|
|
24
|
+
Requires-Dist: pillow>=9; extra == "docs"
|
|
25
|
+
Requires-Dist: numpy>=1.21; extra == "docs"
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
|
|
28
|
+
<h1 align="center">imgui_debugger</h1>
|
|
29
|
+
|
|
30
|
+
<p align="center">
|
|
31
|
+
<a href="https://pypi.org/project/imgui_debugger/"><img src="https://img.shields.io/pypi/v/imgui_debugger.svg" alt="PyPI version"></a>
|
|
32
|
+
<a href="https://pypi.org/project/imgui_debugger/"><img src="https://img.shields.io/badge/python-3.10%2B-blue.svg" alt="Python 3.10+"></a>
|
|
33
|
+
<a href="LICENSE"><img src="https://img.shields.io/pypi/l/imgui_debugger.svg" alt="License: MIT"></a>
|
|
34
|
+
</p>
|
|
35
|
+
|
|
36
|
+
<samp>
|
|
37
|
+
<p align="center">
|
|
38
|
+
Standalone, configurable <b>debug panels</b> for imgui-bundle apps
|
|
39
|
+
<br>
|
|
40
|
+
<br>
|
|
41
|
+
<a href="#install">install</a> ·
|
|
42
|
+
<a href="#the-panels">panels</a> ·
|
|
43
|
+
<a href="#one-menu-for-everything">one menu</a> ·
|
|
44
|
+
<a href="#variable-inspector">inspector</a> ·
|
|
45
|
+
<a href="#style-editor">style editor</a> ·
|
|
46
|
+
<a href="#examples">examples</a> ·
|
|
47
|
+
<a href="#configuration-reference">configuration</a> ·
|
|
48
|
+
<a href="https://github.com/FlynnOConnell/imgui_debugger/issues">issues</a>
|
|
49
|
+
</p>
|
|
50
|
+
</samp>
|
|
51
|
+
|
|
52
|
+
## About
|
|
53
|
+
|
|
54
|
+
Every debugging tool imgui offers normally hangs off the demo window's Tools
|
|
55
|
+
menu. This package unbundles them: each tool is an independent, configurable
|
|
56
|
+
panel you can drop into your own app, on your own menu, with your own
|
|
57
|
+
shortcuts — plus a live variable inspector and a style editor whose Save and
|
|
58
|
+
Load are yours.
|
|
59
|
+
|
|
60
|
+
Nothing here needs the demo window, and nothing here depends on anything else
|
|
61
|
+
here: import one panel, or take the whole set.
|
|
62
|
+
|
|
63
|
+
| panel | what it shows | comes from |
|
|
64
|
+
|-------|---------------|------------|
|
|
65
|
+
| `Debugger` | every variable your widget can see, by scope, live | this package |
|
|
66
|
+
| `StyleEditor` | sizes, colors, rendering, with pluggable Save / Load | this package |
|
|
67
|
+
| `MetricsPanel` | windows, draw lists, viewports, internal state | imgui |
|
|
68
|
+
| `DebugLogPanel` | focus, nav, docking and IO events as they happen | imgui |
|
|
69
|
+
| `IdStackPanel` | what an item's id is built from, for id collisions | imgui |
|
|
70
|
+
| `AboutPanel` | version and the build's enabled features | imgui |
|
|
71
|
+
| `UserGuidePanel` | imgui's built-in control reference | imgui |
|
|
72
|
+
| `DemoPanel` | the demo window, if you ever want it — opt-in only | imgui |
|
|
73
|
+
|
|
74
|
+
Built for widgets like the ones in
|
|
75
|
+
[mbo_utilities](https://github.com/MillerBrainObservatory/mbo_utilities) and
|
|
76
|
+
[masknmf-toolbox](https://github.com/apasarkar/masknmf-toolbox), but it knows
|
|
77
|
+
nothing about them — a target is any Python object.
|
|
78
|
+
|
|
79
|
+
## Install
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
pip install imgui_debugger
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The only dependency is `imgui-bundle` (which provides imgui, hello_imgui,
|
|
86
|
+
immapp and the FontAwesome icon font).
|
|
87
|
+
|
|
88
|
+
## The panels
|
|
89
|
+
|
|
90
|
+
Every panel — including ones you write — has the same four-part surface:
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
panel.visible # bool you can set, bind, or persist
|
|
94
|
+
panel.menu_item() # a checked menu entry bound to visible
|
|
95
|
+
panel.render() # the body, at the current cursor, no window
|
|
96
|
+
panel.render_window() # the body in its own window; polls the hotkey
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
so wiring one into a host app is two lines:
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
def draw_menu(self):
|
|
103
|
+
if imgui.begin_menu("View"):
|
|
104
|
+
self.editor.menu_item() # or menu_item("Theme", "Ctrl+T")
|
|
105
|
+
imgui.end_menu()
|
|
106
|
+
|
|
107
|
+
def draw(self):
|
|
108
|
+
...
|
|
109
|
+
self.editor.render_window()
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`render()` is there for when you would rather host the body yourself — in a tab,
|
|
113
|
+
a dock node, or a sidebar you already own. imgui's own windows (`MetricsPanel`
|
|
114
|
+
and friends) are window-only and say so by raising from `render()`.
|
|
115
|
+
|
|
116
|
+
Configuration is a dataclass per panel, all sharing `PanelConfig`:
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
from imgui_bundle import imgui
|
|
120
|
+
from imgui_debugger import Hotkey, StyleEditor, StyleEditorConfig
|
|
121
|
+
|
|
122
|
+
editor = StyleEditor(StyleEditorConfig(
|
|
123
|
+
title="Theme", # window title + menu label
|
|
124
|
+
visible=False, # starts closed
|
|
125
|
+
hotkey=Hotkey(imgui.Key.t, ctrl=True), # Ctrl+T toggles it; the menu says so
|
|
126
|
+
window_size=(520, 700),
|
|
127
|
+
show_sizes=False, # StyleEditor's own knobs
|
|
128
|
+
on_save=my_app.save_style,
|
|
129
|
+
))
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
To show one on its own, with no host app at all:
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
from imgui_debugger import run_panel
|
|
136
|
+
run_panel(StyleEditor())
|
|
137
|
+
run_panel(MetricsPanel())
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Writing your own panel is a subclass and a `render`:
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
from imgui_debugger import Panel, PanelConfig
|
|
144
|
+
|
|
145
|
+
class Timings(Panel):
|
|
146
|
+
config_class = PanelConfig
|
|
147
|
+
|
|
148
|
+
def render(self):
|
|
149
|
+
imgui.text(f"{imgui.get_io().framerate:.0f} fps")
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## One menu for everything
|
|
153
|
+
|
|
154
|
+
`DebugTools` is an ordered set of panels with one menu and one per-frame call:
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
from imgui_debugger import DebugTools, Hotkey
|
|
158
|
+
|
|
159
|
+
self.tools = DebugTools.default(self, menu_label="Debug")
|
|
160
|
+
self.tools["Debugger"].config.hotkey = Hotkey(imgui.Key.f12)
|
|
161
|
+
|
|
162
|
+
def draw_menu(self):
|
|
163
|
+
self.tools.draw_menu() # or draw_menu_items() inside your own menu
|
|
164
|
+
|
|
165
|
+
def draw(self):
|
|
166
|
+
...
|
|
167
|
+
self.tools.render() # every open panel, every hotkey
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
`DebugTools.default()` gives the inspector, the style editor, metrics, the debug
|
|
171
|
+
log and the ID stack tool, all starting closed. The demo window is deliberately
|
|
172
|
+
left out. The set is editable — `add`, `remove`, `tools["title"]`, `show_all`,
|
|
173
|
+
`hide_all`, `visible()` — so you can swap the style editor for one configured
|
|
174
|
+
your way, or register a panel of your own beside them.
|
|
175
|
+
|
|
176
|
+
## Variable inspector
|
|
177
|
+
|
|
178
|
+
Point it at a widget and it draws every variable that widget can see, grouped by
|
|
179
|
+
scope, in a collapsible tree that re-reads its values every frame:
|
|
180
|
+
|
|
181
|
+
- **instance** — the object's own `__dict__` and `__slots__`
|
|
182
|
+
- **properties** — `property` descriptors, evaluated live; one that raises shows
|
|
183
|
+
the exception instead of blanking the panel
|
|
184
|
+
- **class** — class attributes from the whole MRO
|
|
185
|
+
- **locals / globals** — the call frame you captured, so you can follow a draw
|
|
186
|
+
method's own variables
|
|
187
|
+
- **imgui** — io, mouse, keyboard, the window rect and the style metrics that
|
|
188
|
+
explain most layout bugs
|
|
189
|
+
- **watches** — anything else you promote to a top-level scope
|
|
190
|
+
|
|
191
|
+
Leaves that are a bool, number, string or color tuple get an inline editor that
|
|
192
|
+
writes straight back onto the object.
|
|
193
|
+
|
|
194
|
+
```python
|
|
195
|
+
from imgui_debugger import attach
|
|
196
|
+
|
|
197
|
+
class RoiWidget:
|
|
198
|
+
def __init__(self):
|
|
199
|
+
self.threshold = 0.4
|
|
200
|
+
self.debugger = attach(self, title="ROIs widget")
|
|
201
|
+
|
|
202
|
+
def update(self): # your per-frame draw
|
|
203
|
+
...
|
|
204
|
+
self.debugger.capture() # follow this method's locals
|
|
205
|
+
self.debugger.render_window()
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Or inspect one object with no host app:
|
|
209
|
+
|
|
210
|
+
```python
|
|
211
|
+
from imgui_debugger import run_debugger
|
|
212
|
+
run_debugger({"fs": 9.6, "dz": 5.0, "planes": [1, 2, 3]})
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Scopes
|
|
216
|
+
|
|
217
|
+
`Debugger.scopes()` returns them in display order: the target's
|
|
218
|
+
`instance` / `properties` / `class`, then your watches, then `locals` /
|
|
219
|
+
`globals`, then `imgui`.
|
|
220
|
+
|
|
221
|
+
| scope | source | writable |
|
|
222
|
+
|-------|--------|----------|
|
|
223
|
+
| `instance` | `vars(obj)` + `__slots__` | yes |
|
|
224
|
+
| `properties` | `property` / `cached_property` on the MRO | only with an `fset` |
|
|
225
|
+
| `class` | class attributes, no methods or descriptors | yes |
|
|
226
|
+
| `locals` | the captured frame's `f_locals` | no (writes do not stick) |
|
|
227
|
+
| `globals` | the captured frame's `f_globals` | yes |
|
|
228
|
+
| `imgui` | `io`, `mouse`, `keyboard`, `window`, `style` | no |
|
|
229
|
+
| watches | `watch(name, value_or_callable)` | depends on the value |
|
|
230
|
+
|
|
231
|
+
A watch takes a value or a zero-argument callable; the callable is re-read every
|
|
232
|
+
frame, so it survives the attribute being reassigned:
|
|
233
|
+
|
|
234
|
+
```python
|
|
235
|
+
dbg.watch("metadata", lambda: self.metadata, role="prop")
|
|
236
|
+
dbg.watch("fps", lambda: {"now": imgui.get_io().framerate}, role="runtime")
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
`watch_all(obj, ["metadata", "indices"])` does the same for several attributes
|
|
240
|
+
in one call.
|
|
241
|
+
|
|
242
|
+
### Toolbar
|
|
243
|
+
|
|
244
|
+
| control | what it does |
|
|
245
|
+
|---------|--------------|
|
|
246
|
+
| filter | case-insensitive match over names and leaf values, recursing into children (bounded to 6 levels and 64 items per container, memoized per filter string) |
|
|
247
|
+
| expand / collapse | force every node open or shut for one frame |
|
|
248
|
+
| private | include `_name` attributes |
|
|
249
|
+
| edit | turn the inline editors off and read only |
|
|
250
|
+
|
|
251
|
+
## Style editor
|
|
252
|
+
|
|
253
|
+
`StyleEditor` is the imgui demo's style editor with its Save Ref / Revert Ref /
|
|
254
|
+
Export buttons replaced by two of yours. `imgui.show_style_editor()` cannot be
|
|
255
|
+
drawn without those buttons, and they only manage an in-memory reference style —
|
|
256
|
+
nothing they do touches disk — so this draws the tabs itself.
|
|
257
|
+
|
|
258
|
+
```python
|
|
259
|
+
from imgui_debugger import StyleEditor, StyleEditorConfig
|
|
260
|
+
|
|
261
|
+
editor = StyleEditor(StyleEditorConfig(
|
|
262
|
+
title="Theme",
|
|
263
|
+
visible=False,
|
|
264
|
+
save_label="Save to settings",
|
|
265
|
+
load_label="Load from settings",
|
|
266
|
+
on_save=my_app.save_style, # on_save(data: dict)
|
|
267
|
+
on_load=my_app.load_style, # on_load() -> dict | None
|
|
268
|
+
))
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
With no `on_save` / `on_load`, the buttons fall back to reading and writing
|
|
272
|
+
`config.path` as JSON (`~/.imgui_debugger/style.json` when that is unset too).
|
|
273
|
+
`on_load` returning `None` is a cancel — that is how a native file dialog the
|
|
274
|
+
user dismissed reports back. Errors from either hook land on the editor's status
|
|
275
|
+
line instead of raising inside a frame.
|
|
276
|
+
|
|
277
|
+
The body is configurable: `show_sizes`, `show_colors` and `show_rendering` pick
|
|
278
|
+
the tabs (one tab alone is drawn without a tab bar), `show_font_selector` and
|
|
279
|
+
`show_style_selector` add imgui's own pickers, `size_groups` replaces the Sizes
|
|
280
|
+
tab's fields entirely, and `extra_draw(editor)` slots your own controls under the
|
|
281
|
+
toolbar. Presets apply `style_colors_dark` / `_light` / `_classic`; Revert
|
|
282
|
+
restores the style as it was when the editor was constructed.
|
|
283
|
+
|
|
284
|
+
The serialization is usable on its own:
|
|
285
|
+
|
|
286
|
+
| function | does |
|
|
287
|
+
|----------|------|
|
|
288
|
+
| `style_to_dict(style=None)` | `{"sizes": {...}, "colors": {name: [r,g,b,a]}}` |
|
|
289
|
+
| `apply_style_dict(data, style=None)` | writes it back, returns how many fields landed |
|
|
290
|
+
| `save_style(path=None, style=None)` | `style_to_dict` to JSON |
|
|
291
|
+
| `load_style(path=None, style=None)` | JSON to `apply_style_dict` |
|
|
292
|
+
|
|
293
|
+
Colors are keyed by imgui's own names (`Text`, `FrameBg`, ...), and unknown keys
|
|
294
|
+
are ignored, so a file written against an older imgui still loads. Two fields are
|
|
295
|
+
deliberately not serialized: `font_scale_dpi` and `font_size_base` are derived
|
|
296
|
+
from the screen at runtime, and restoring another machine's values resizes every
|
|
297
|
+
font for the wrong display.
|
|
298
|
+
|
|
299
|
+
## Examples
|
|
300
|
+
|
|
301
|
+
See all examples in [`examples/`](examples/).
|
|
302
|
+
|
|
303
|
+
| name | file | what it shows |
|
|
304
|
+
|------|------|---------------|
|
|
305
|
+
| debug_minimal | [`debug_minimal.py`](examples/debug_minimal.py) | one-shot window over a settings dataclass |
|
|
306
|
+
| debug_widget | [`debug_widget.py`](examples/debug_widget.py) | a widget that owns its inspector, captures its own locals, and toggles it with F12 |
|
|
307
|
+
| debug_edge_window | [`debug_edge_window.py`](examples/debug_edge_window.py) | a fastplotlib `EdgeWindow`, the widget shape pml_utilities and masknmf-toolbox use |
|
|
308
|
+
| style_editor_menu | [`style_editor_menu.py`](examples/style_editor_menu.py) | the style editor alone, on a menu, saving into the app's own settings file |
|
|
309
|
+
| debug_tools_menu | [`debug_tools_menu.py`](examples/debug_tools_menu.py) | the whole set behind one menu, with hotkeys and a replaced style editor |
|
|
310
|
+
|
|
311
|
+
## Configuration reference
|
|
312
|
+
|
|
313
|
+
### `PanelConfig` — every panel takes these
|
|
314
|
+
|
|
315
|
+
| field | default | purpose |
|
|
316
|
+
|-------|---------|---------|
|
|
317
|
+
| `title` | per panel | window title and default menu label |
|
|
318
|
+
| `visible` | `True` | whether it starts open |
|
|
319
|
+
| `window_id` | `""` | stable imgui id suffix; the class name when empty, so renaming the title keeps the saved layout |
|
|
320
|
+
| `window_size` | `(0, 0)` | first-use size; `(0, 0)` sizes to content |
|
|
321
|
+
| `window_pos` | `None` | first-use position |
|
|
322
|
+
| `window_flags` | `0` | `imgui.WindowFlags_` bits |
|
|
323
|
+
| `closable` | `True` | draw the close button and clear `visible` with it |
|
|
324
|
+
| `shortcut` | `""` | menu shortcut text; the hotkey's text when empty |
|
|
325
|
+
| `hotkey` | `None` | `Hotkey(key, ctrl=, shift=, alt=)` that toggles the panel |
|
|
326
|
+
| `theme` | `Theme.dark()` | palette for what the panel draws itself |
|
|
327
|
+
|
|
328
|
+
### `DebuggerConfig` — plus the above
|
|
329
|
+
|
|
330
|
+
| field | default | purpose |
|
|
331
|
+
|-------|---------|---------|
|
|
332
|
+
| `target` | `None` | the object whose scopes come first |
|
|
333
|
+
| `private` | `False` | show `_name` attributes |
|
|
334
|
+
| `properties` | `True` | show the `properties` scope and expand nested properties |
|
|
335
|
+
| `class_attrs` | `True` | show the `class` scope |
|
|
336
|
+
| `editable` | `True` | inline editors for writable leaves |
|
|
337
|
+
| `show_frame` | `True` | show `locals` / `globals` |
|
|
338
|
+
| `show_runtime` | `True` | show the live `imgui` scope |
|
|
339
|
+
| `max_depth` | `8` | deepest level the tree expands |
|
|
340
|
+
| `max_items` | `200` | rows per container before "+N more" |
|
|
341
|
+
| `value_col` | `0.0` | pixel column values align at; `0` packs them after the name |
|
|
342
|
+
| `show_toolbar` | `True` | draw the filter box and toggles |
|
|
343
|
+
| `show_title` | `True` | draw the title line inside the body |
|
|
344
|
+
| `os_window_title`, `resizable`, `ini_path`, `assets_folder` | — | one-shot `run_debugger` only |
|
|
345
|
+
|
|
346
|
+
### `StyleEditorConfig` — plus `PanelConfig`
|
|
347
|
+
|
|
348
|
+
| field | default | purpose |
|
|
349
|
+
|-------|---------|---------|
|
|
350
|
+
| `on_save` | `None` | `on_save(data)`; falls back to writing `path` |
|
|
351
|
+
| `on_load` | `None` | `on_load() -> dict \| None`; falls back to reading `path` |
|
|
352
|
+
| `path` | `None` | file used by the fallback Save / Load |
|
|
353
|
+
| `save_label`, `load_label` | `"Save"`, `"Load"` | button text |
|
|
354
|
+
| `show_presets`, `show_revert` | `True` | the preset buttons and Revert |
|
|
355
|
+
| `show_sizes`, `show_colors`, `show_rendering` | `True` | which tabs to draw |
|
|
356
|
+
| `show_font_selector`, `show_style_selector` | `False` | imgui's own pickers above the tabs |
|
|
357
|
+
| `size_groups` | `None` | replace the Sizes tab's field groups |
|
|
358
|
+
| `extra_draw` | `None` | `extra_draw(editor)` under the toolbar |
|
|
359
|
+
|
|
360
|
+
`attach(target, **kwargs)` and `run_debugger(target, **kwargs)` take any
|
|
361
|
+
`DebuggerConfig` field as a keyword argument.
|
|
362
|
+
|
|
363
|
+
## Files on disk
|
|
364
|
+
|
|
365
|
+
Everything the library writes lives under `~/.imgui_debugger/` (override with
|
|
366
|
+
the `IMGUI_DEBUGGER_HOME` env var):
|
|
367
|
+
|
|
368
|
+
| path | written by | purpose |
|
|
369
|
+
|------|-----------|---------|
|
|
370
|
+
| `~/.imgui_debugger/debugger.ini`, `panel.ini` | `run_debugger`, `run_panel` | hello_imgui window layout. Override per call; an embedding app's own `ini_filename` always wins. |
|
|
371
|
+
| `~/.imgui_debugger/style.json` | `save_style` with no path | the fallback style file |
|
|
372
|
+
| `~/.imgui_debugger/assets/` | you (optional) | user assets folder, added to hello_imgui's search path when the icon font cannot be resolved |
|
|
373
|
+
|
|
374
|
+
Embedded use writes nothing: `render()` and `render_window()` only draw.
|
|
375
|
+
|
|
376
|
+
## Notes
|
|
377
|
+
|
|
378
|
+
- Reads are guarded. A property that raises, a `__repr__` that raises, and a
|
|
379
|
+
container that changes size mid-frame all render as a row rather than crashing
|
|
380
|
+
the frame.
|
|
381
|
+
- Big containers are capped, not truncated silently: a "+N more" line says how
|
|
382
|
+
many rows were left out.
|
|
383
|
+
- Editing writes through the same setter the row was built from — `setattr` for
|
|
384
|
+
an attribute, `__setitem__` for a dict or list entry, the property's `fset` for
|
|
385
|
+
a property.
|
|
386
|
+
|
|
387
|
+
## Acknowledgements
|
|
388
|
+
|
|
389
|
+
The tree rendering, the bounded memoized filter and the value formatting come
|
|
390
|
+
from the metadata inspector in
|
|
391
|
+
[mbo_utilities](https://github.com/MillerBrainObservatory/mbo_utilities) at the
|
|
392
|
+
[Miller Brain Observatory](https://github.com/MillerBrainObservatory). The
|
|
393
|
+
packaging, theming and one-shot harness follow
|
|
394
|
+
[imgui_data_loader](https://github.com/FlynnOConnell/imgui_data_loader).
|
|
395
|
+
|
|
396
|
+
## License
|
|
397
|
+
|
|
398
|
+
MIT
|