feat(gui): Add imgui_scopes with per-type context managers for begin/end pairs

This commit is contained in:
2026-05-12 00:13:22 -04:00
parent b9c1b63f8d
commit aed3ebe063
2 changed files with 146 additions and 81 deletions
+118 -49
View File
@@ -3,76 +3,145 @@ from imgui_bundle import imgui
from imgui_bundle import imgui_node_editor
class ImGuiScope:
_entered: bool
_opened: bool | tuple
_begin_fn: object
_end_fn: object
_args: tuple[object, ...]
_kwargs: dict[str, object]
def imgui_begin(name: str, visible: bool = True, flags: int = 0):
return _ImguiBegin(name, visible, flags)
def __init__(self, begin_fn: object, end_fn: object, *args: object, **kwargs: object) -> None:
self._begin_fn = begin_fn
self._end_fn = end_fn
self._args = args
self._kwargs = kwargs
self._opened = False
self._entered = False
def __enter__(self) -> bool | tuple:
self._opened = self._begin_fn(*self._args, **self._kwargs)
if isinstance(self._opened, tuple):
self._entered = bool(self._opened[0])
return self._opened
else:
self._entered = bool(self._opened)
return self._opened
class _ImguiBegin:
def __init__(self, name: str, visible: bool, flags: int):
self._name = name
self._visible = visible
self._flags = flags
self._result = None
def __exit__(self, *args: object) -> bool:
if self._entered:
self._end_fn()
def __enter__(self):
self._result = imgui.begin(self._name, self._visible, self._flags)
return self._result
def __exit__(self, *args):
imgui.end()
return False
def imgui_window(name: str, visible: bool = True, flags: int = 0) -> ImGuiScope:
return ImGuiScope(imgui.begin, imgui.end, name, visible, flags)
def imgui_begin_child(id_str: str, size_x: float = 0, size_y: float = 0, flags: int = 0):
return _ImguiBeginChild(id_str, size_x, size_y, flags)
def imgui_table(name: str, columns: int, flags: int = 0) -> ImGuiScope:
return ImGuiScope(imgui.begin_table, imgui.end_table, name, columns, flags)
class _ImguiBeginChild:
def __init__(self, id_str: str, size_x: float, size_y: float, flags: int):
self._id = id_str
self._sx = size_x
self._sy = size_y
self._flags = flags
def __enter__(self):
return imgui.begin_child(self._id, self._sx, self._sy, self._flags)
def __exit__(self, *args):
imgui.end_child()
return False
def imgui_menu_bar() -> ImGuiScope:
return ImGuiScope(imgui.begin_menu_bar, imgui.end_menu_bar)
def imgui_begin_table(name: str, columns: int, flags: int = 0):
return _ImguiBeginTable(name, columns, flags)
def imgui_menu(label: str) -> ImGuiScope:
return ImGuiScope(imgui.begin_menu, imgui.end_menu, label)
class _ImguiBeginTable:
def __init__(self, name: str, columns: int, flags: int):
self._name = name
self._columns = columns
self._flags = flags
def __enter__(self):
return imgui.begin_table(self._name, self._columns, self._flags)
def __exit__(self, *args):
imgui.end_table()
return False
def imgui_child(id_str: str, width: float = 0, height: float = 0, flags: int = 0) -> ImGuiScope:
return ImGuiScope(imgui.begin_child, imgui.end_child, id_str, width, height, flags)
def imgui_begin_menu_bar():
return _ImguiBeginMenuBar()
def imgui_group() -> ImGuiScope:
return ImGuiScope(imgui.begin_group, imgui.end_group)
class _ImguiBeginMenuBar:
def __enter__(self):
return imgui.begin_menu_bar()
def __exit__(self, *args):
imgui.end_menu_bar()
return False
def imgui_popup(id_str: str) -> ImGuiScope:
return ImGuiScope(imgui.begin_popup, imgui.end_popup, id_str)
def imgui_begin_menu(label: str):
return _ImguiBeginMenu(label)
def imgui_tooltip() -> ImGuiScope:
return ImGuiScope(imgui.begin_tooltip, imgui.end_tooltip)
class _ImguiBeginMenu:
def __init__(self, label: str):
self._label = label
def __enter__(self):
return imgui.begin_menu(self._label)
def __exit__(self, *args):
imgui.end_menu()
return False
def imgui_clipper(count: int) -> ImGuiScope:
return ImGuiScope(
lambda n: imgui.listing_builder.begin_clipper(n, -1),
imgui.listing_builder.end_clipper,
count
)
def imgui_begin_popup(id_str: str):
return _ImguiBeginPopup(id_str)
def node_editor_scope(name: str) -> ImGuiScope:
return ImGuiScope(imgui_node_editor.begin, imgui_node_editor.end, name)
class _ImguiBeginPopup:
def __init__(self, id_str: str):
self._id = id_str
def __enter__(self):
return imgui.begin_popup(self._id)
def __exit__(self, *args):
imgui.end_popup()
return False
def imgui_begin_tooltip():
return _ImguiBeginTooltip()
class _ImguiBeginTooltip:
def __enter__(self):
return imgui.begin_tooltip()
def __exit__(self, *args):
imgui.end_tooltip()
return False
def imgui_begin_group():
return _ImguiBeginGroup()
class _ImguiBeginGroup:
def __enter__(self):
return imgui.begin_group()
def __exit__(self, *args):
imgui.end_group()
return False
def node_begin(name: str):
return _NodeBegin(name)
class _NodeBegin:
def __init__(self, name: str):
self._name = name
def __enter__(self):
return imgui_node_editor.begin(self._name)
def __exit__(self, *args):
imgui_node_editor.end()
return False