"""
Template companion plugin.
Replace every occurrence of ``MyPlugin`` / ``my_plugin`` with your own name,
then implement the methods below.
Rename this directory to match the ``name`` field in ``plugin.toml``
(removing the leading ``_`` so it is auto-discovered).
Recommended structure to keep plugin footprint minimal:
- one Python module containing both the pure business model and the UI
companion adapter,
- one metadata file (``plugin.toml``).
"""
from dataclasses import dataclass
from wolfhece.plugins.abc import (
AbstractCompanionModel,
AbstractUICompanion,
Keys,
MenuItem,
MultiStepSpec,
StepSpec,
StepTransition,
)
from wolfhece._viewer_plugin_handlers import MouseContext, KeyboardSnapshot
@dataclass
[docs]
class MyPluginModel(AbstractCompanionModel):
"""Pure domain state: no viewer/wx/OpenGL dependencies."""
[docs]
def record_click(self) -> None:
self.click_count += 1
[docs]
def reset(self) -> None:
self.click_count = 0
[docs]
class MyPluginCompanion(AbstractUICompanion):
"""Minimal template — replace with your implementation."""
[docs]
def create_model(self) -> MyPluginModel:
return MyPluginModel()
[docs]
def actions_spec(self):
return [
MultiStepSpec(
'run',
primary=True,
start_message='Right-click to interact — Esc to stop',
steps=[
StepSpec(
hint='Right-click to interact — Esc to stop',
rdown=self.step1_rdown,
key=self.key,
paint=self.paint,
),
StepSpec(
hint='Right-click again to finish — Esc to cancel',
rdown=self.step2_rdown,
key=self.key,
paint=self.paint,
),
],
finish_message='Action finished',
),
]
[docs]
def start(self) -> None:
"""Called when the companion is activated programmatically."""
self.proxy.start_action(
'run',
'Right-click to interact — Esc to stop',
)
# -- handlers ------------------------------------------------------------
[docs]
def on_run(self, ctx: MouseContext) -> None:
self.start()
[docs]
def rdown(self, ctx: MouseContext) -> None:
# TODO: replace with your business logic
if isinstance(self.model, MyPluginModel):
self.model.record_click()
self.proxy.set_status(f'Clicks: {self.model.click_count}')
self.proxy.force_redraw()
[docs]
def step1_rdown(self, ctx: MouseContext) -> StepTransition:
self.rdown(ctx)
return StepTransition.NEXT
[docs]
def step2_rdown(self, ctx: MouseContext) -> StepTransition:
self.rdown(ctx)
return StepTransition.FINISH
[docs]
def key(self, kb: KeyboardSnapshot) -> bool | StepTransition:
if kb.key_code == Keys.ESCAPE:
return StepTransition.CANCEL
return False
[docs]
def paintdoc(self) -> None:
# TODO: draw your OpenGL overlay
pass