Some checks failed
Build and Test / build (pull_request) Failing after 1m40s
Add mods/sdk/ with the kindred_sdk Python package providing a stable API layer for addon integration with Kindred Create platform features. Modules: - context: editing context/overlay registration wrappers - theme: YAML-driven palette system (Catppuccin Mocha) - origin: FileOrigin registration helpers - dock: deferred dock panel registration - compat: version detection utilities The SDK loads at priority 0 (before all other addons) via the existing manifest-driven loader. Theme colors are defined in a single YAML palette file instead of hardcoded Python dicts, enabling future theme support and eliminating color duplication across addons. Closes #249
153 lines
4.9 KiB
Python
153 lines
4.9 KiB
Python
"""Editing context and overlay registration wrappers.
|
|
|
|
Thin wrappers around FreeCADGui editing context bindings. If the
|
|
underlying C++ API changes during an upstream rebase, only this module
|
|
needs to be updated.
|
|
"""
|
|
|
|
import FreeCAD
|
|
|
|
|
|
def _gui():
|
|
"""Lazy import of FreeCADGui (not available in console mode)."""
|
|
import FreeCADGui
|
|
|
|
return FreeCADGui
|
|
|
|
|
|
def register_context(context_id, label, color, toolbars, match, priority=50):
|
|
"""Register an editing context.
|
|
|
|
Parameters
|
|
----------
|
|
context_id : str
|
|
Unique identifier (e.g. ``"myaddon.edit"``).
|
|
label : str
|
|
Display label template. Supports ``{name}`` placeholder.
|
|
color : str
|
|
Hex color for the breadcrumb (e.g. ``"#f38ba8"``).
|
|
toolbars : list[str]
|
|
Toolbar names to show when this context is active.
|
|
match : callable
|
|
Zero-argument callable returning *True* when this context is active.
|
|
priority : int, optional
|
|
Higher values are checked first. Default 50.
|
|
"""
|
|
if not isinstance(context_id, str):
|
|
raise TypeError(f"context_id must be str, got {type(context_id).__name__}")
|
|
if not isinstance(toolbars, list):
|
|
raise TypeError(f"toolbars must be list, got {type(toolbars).__name__}")
|
|
if not callable(match):
|
|
raise TypeError("match must be callable")
|
|
|
|
try:
|
|
_gui().registerEditingContext(context_id, label, color, toolbars, match, priority)
|
|
except Exception as e:
|
|
FreeCAD.Console.PrintWarning(
|
|
f"kindred_sdk: Failed to register context '{context_id}': {e}\n"
|
|
)
|
|
|
|
|
|
def unregister_context(context_id):
|
|
"""Remove a previously registered editing context."""
|
|
if not isinstance(context_id, str):
|
|
raise TypeError(f"context_id must be str, got {type(context_id).__name__}")
|
|
|
|
try:
|
|
_gui().unregisterEditingContext(context_id)
|
|
except Exception as e:
|
|
FreeCAD.Console.PrintWarning(
|
|
f"kindred_sdk: Failed to unregister context '{context_id}': {e}\n"
|
|
)
|
|
|
|
|
|
def register_overlay(overlay_id, toolbars, match):
|
|
"""Register an editing overlay.
|
|
|
|
Overlays add toolbars to whatever context is currently active when
|
|
*match* returns True.
|
|
|
|
Parameters
|
|
----------
|
|
overlay_id : str
|
|
Unique overlay identifier.
|
|
toolbars : list[str]
|
|
Toolbar names to append.
|
|
match : callable
|
|
Zero-argument callable returning *True* when the overlay applies.
|
|
"""
|
|
if not isinstance(overlay_id, str):
|
|
raise TypeError(f"overlay_id must be str, got {type(overlay_id).__name__}")
|
|
if not isinstance(toolbars, list):
|
|
raise TypeError(f"toolbars must be list, got {type(toolbars).__name__}")
|
|
if not callable(match):
|
|
raise TypeError("match must be callable")
|
|
|
|
try:
|
|
_gui().registerEditingOverlay(overlay_id, toolbars, match)
|
|
except Exception as e:
|
|
FreeCAD.Console.PrintWarning(
|
|
f"kindred_sdk: Failed to register overlay '{overlay_id}': {e}\n"
|
|
)
|
|
|
|
|
|
def unregister_overlay(overlay_id):
|
|
"""Remove a previously registered editing overlay."""
|
|
if not isinstance(overlay_id, str):
|
|
raise TypeError(f"overlay_id must be str, got {type(overlay_id).__name__}")
|
|
|
|
try:
|
|
_gui().unregisterEditingOverlay(overlay_id)
|
|
except Exception as e:
|
|
FreeCAD.Console.PrintWarning(
|
|
f"kindred_sdk: Failed to unregister overlay '{overlay_id}': {e}\n"
|
|
)
|
|
|
|
|
|
def inject_commands(context_id, toolbar_name, commands):
|
|
"""Inject commands into a context's toolbar.
|
|
|
|
Parameters
|
|
----------
|
|
context_id : str
|
|
Target context identifier.
|
|
toolbar_name : str
|
|
Toolbar within that context.
|
|
commands : list[str]
|
|
Command names to add.
|
|
"""
|
|
if not isinstance(context_id, str):
|
|
raise TypeError(f"context_id must be str, got {type(context_id).__name__}")
|
|
if not isinstance(toolbar_name, str):
|
|
raise TypeError(f"toolbar_name must be str, got {type(toolbar_name).__name__}")
|
|
if not isinstance(commands, list):
|
|
raise TypeError(f"commands must be list, got {type(commands).__name__}")
|
|
|
|
try:
|
|
_gui().injectEditingCommands(context_id, toolbar_name, commands)
|
|
except Exception as e:
|
|
FreeCAD.Console.PrintWarning(
|
|
f"kindred_sdk: Failed to inject commands into '{context_id}': {e}\n"
|
|
)
|
|
|
|
|
|
def current_context():
|
|
"""Return the current editing context as a dict.
|
|
|
|
Keys: ``id``, ``label``, ``color``, ``toolbars``, ``breadcrumb``,
|
|
``breadcrumbColors``. Returns ``None`` if no context is active.
|
|
"""
|
|
try:
|
|
return _gui().currentEditingContext()
|
|
except Exception as e:
|
|
FreeCAD.Console.PrintWarning(f"kindred_sdk: Failed to get current context: {e}\n")
|
|
return None
|
|
|
|
|
|
def refresh_context():
|
|
"""Force re-resolution and update of the editing context."""
|
|
try:
|
|
_gui().refreshEditingContext()
|
|
except Exception as e:
|
|
FreeCAD.Console.PrintWarning(f"kindred_sdk: Failed to refresh context: {e}\n")
|