Plotly.react resets any scene attribute the incoming layout omits, so every
selection change snapped the camera back to the default and re-fit the
ranges - the pinned framing was meaningless. Data-only pushes now pass
preserveView and html.py merges the live camera and axis ranges into the
incoming layout; only an explicit re-frame sends computed framing.
Also fixes the ordering bug where the framing flag was consumed before the
not-ready early return, which dropped the very first framing on the floor
(show_project runs before loadFinished).
Verified in the browser: user orbit + zoom survive selection and working
plane updates, while reset_camera re-frames. Regression-tested headlessly
by asserting the emitted preserveView flag.
Adds a table-driven dialog over RenderStyle.STYLE_FIELDS (colour swatches,
an opacity spin and a label font size), reachable from Options. Edits
preview immediately on every canvas, Cancel restores the style the dialog
opened with, and only OK persists — as JSON under QSettings plot/props,
reloaded on the next launch. Both canvases gain set_style(); the dialog
deliberately exposes plot_style() rather than style() so QWidget.style()
keeps its Qt meaning.
opstool v1.0.26 (GPL-3.0) is cloned read-only under
.slim/clonedeps/repos/ to inspect its PyVista/Plotly visualization
settings. GPLv3 section 13 permits combining it with this AGPL-3.0
project. The clone itself is git-ignored; the manifest and the AGENTS.md
pointer are committed.
Both backends share one SelectionState owned by MainWindow and live
side by side in a QStackedWidget — switching is setCurrentWidget, so
no widget is destroyed mid-session (tearing a VTK window down leaves
dangling make-current callbacks). The choice persists in QSettings.
CanvasCapabilities declares per-backend gaps (force diagrams and
video export stay PyVista-only, both are documented and greyed out)
and the UI gates on capabilities rather than the backend name. The
architecture gate now allows the canvas_plotly package.