"""
Control Registry
Dict-like registry of parameter -> widget, owned by SynthBase (or one per partial).
Supports get(param) with optional name fallback so param identity matches across
partials. Use register(param, widget) or registry[param] = widget; lookup via
registry.get(param) or registry[param].
"""
from typing import Any, Iterator, Protocol, runtime_checkable
from PySide6.QtWidgets import QWidget
@runtime_checkable
[docs]
class ControlResolver(Protocol):
[docs]
def get(self, param, default: QWidget | None = None) -> QWidget | None: ...
[docs]
class ControlRegistry:
"""Registry of parameter -> control widget. Dict-like; singleton instance shared across all partials."""
[docs]
_instance: "ControlRegistry | None" = None
[docs]
_initialized: bool = False
def __new__(cls) -> "ControlRegistry":
"""Singleton pattern: return the same instance on every instantiation."""
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self) -> None:
"""Initialize the registry only once."""
if not ControlRegistry._initialized:
self._controls: dict[Any, QWidget] = {}
ControlRegistry._initialized = True
[docs]
def register(self, param: Any, widget: QWidget) -> None:
self._controls[param] = widget
[docs]
def get(self, param: Any, default: QWidget | None = None) -> QWidget | None:
if param in self._controls:
return self._controls[param]
name = getattr(param, "name", None)
if name:
for k, w in self._controls.items():
if getattr(k, "name", None) == name:
return w
return default
[docs]
def __setitem__(self, param: Any, widget: QWidget) -> None:
self.register(param, widget)
[docs]
def __getitem__(self, param: Any) -> QWidget:
w = self.get(param)
if w is None:
raise KeyError(param)
return w
[docs]
def __contains__(self, param: Any) -> bool:
if param in self._controls:
return True
name = getattr(param, "name", None)
if name:
for k in self._controls:
if getattr(k, "name", None) == name:
return True
return False
[docs]
def __len__(self) -> int:
return len(self._controls)
[docs]
def __iter__(self) -> Iterator[Any]:
return iter(self._controls)
[docs]
def items(self) -> Iterator[tuple[Any, QWidget]]:
return iter(self._controls.items())
[docs]
def keys(self) -> Iterator[Any]:
return iter(self._controls.keys())
[docs]
def values(self) -> Iterator[QWidget]:
return iter(self._controls.values())
[docs]
def pop(self, param: Any, default: QWidget | None = None) -> QWidget | None:
return self._controls.pop(param, default)
[docs]
def update(self, other: Any = (), /, **kwargs: Any) -> None:
"""Update registry from another mapping (e.g. dict or ControlRegistry) or iterable of (param, widget)."""
if hasattr(other, "items"):
for k, v in other.items():
self._controls[k] = v
else:
for k, v in other:
self._controls[k] = v
for k, v in kwargs.items():
self._controls[k] = v