Add left node-library dock (grouped, searchable, drag-and-drop vector symbols), right property dock with type-aware grouped editors (incl. geometry, catalogue single/multi, color, value list), zoom/pan/fit canvas view accepting node drops, flow animator, configuration dialog, and the MainWindow wiring menus/toolbar, undo/redo, delete/duplicate, calculate flow, save/open (JSON), and PNG/SVG export. Includes a demo sample network, entry points, and panel + app integration tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
47 lines
1.3 KiB
Python
47 lines
1.3 KiB
Python
"""Drives the marching-dash flow animation on edge items via a timer."""
|
|
from __future__ import annotations
|
|
|
|
from PyQt6.QtCore import QObject, QTimer
|
|
|
|
|
|
class FlowAnimator(QObject):
|
|
"""Advances an animation phase and pushes it to every edge item."""
|
|
|
|
def __init__(self, scene, config, parent=None):
|
|
super().__init__(parent)
|
|
self._scene = scene
|
|
self._config = config
|
|
self._phase = 0.0
|
|
self._timer = QTimer(self)
|
|
self._timer.setInterval(40) # ~25 fps
|
|
self._timer.timeout.connect(self._tick)
|
|
self.running = False
|
|
|
|
def start(self) -> None:
|
|
if not self.running:
|
|
self.running = True
|
|
self._timer.start()
|
|
|
|
def stop(self) -> None:
|
|
self.running = False
|
|
self._timer.stop()
|
|
|
|
def toggle(self) -> None:
|
|
self.stop() if self.running else self.start()
|
|
|
|
def reset(self) -> None:
|
|
self._phase = 0.0
|
|
self._push()
|
|
|
|
def step(self) -> None:
|
|
"""Advance one frame (used for tests without a running event loop)."""
|
|
self._tick()
|
|
|
|
def _tick(self) -> None:
|
|
self._phase += max(0.1, self._config.animation_speed)
|
|
self._push()
|
|
|
|
def _push(self) -> None:
|
|
for item in self._scene.edge_items.values():
|
|
item.set_phase(self._phase)
|