feat(2.0): inset axes — qv.Inset as a structural element + pane [D152]–[D154] - #9
Merged
Conversation
qv.Inset(child, rect=, label=, indicate=) composes into an overlay like an annotation (parent * Inset(...)). Element gains the declared STRUCTURAL_CHILD marker ([D124] discipline): resolve_node/node_is_lazy recurse into the child, _elements_of yields through it (negotiation's intersect-first rule covers inset contents), and series_index_map treats structural elements as chrome. Depth-1 and rect validation at construction. Freeze triple: FROZEN_2_0 + api.md + CHANGELOG. Design: design/inset-axes.md Part II (I1).
…bengine warn-skip Interception is the surface loop (where the y2 branch lives), not the renderer registry — supports()/honored_options gain a structural clause. matplotlib: ax.inset_axes + _render_cell re-entry (theming, surface apply, events, PaneBus stamping all inherited). pyqtgraph: _render_cell splits into _surface_target/_populate_plot shared by grid cells and insets; a child PlotItem parents onto the parent plot, placed from rect (mpl bottom-origin semantics, Qt y-down conversion) on the parent ViewBox's sigResized (spiked offscreen). webengine: the figure builder warns and skips insets until I5; supports() accepts so negotiation proceeds. Labels thread as a deque in traversal order, matching flat_pane_labels' depth-first walk (which now includes insets). negotiate/auto_negotiate recurse into structural children — same-surface ⇒ same-backend enforced. mpl [D146] leader lookup gains a child→surface index map (insets shift the surfaces list). Element census 28→29 (CLAUDE.md + vocabulary test). Design: design/inset-axes.md Part II (I2).
No production changes needed beyond I2: flat_pane_labels already walks insets and the backends append inset surfaces in depth-first order, so the pane protocol carries them. Pins: pane lists ['0','zoom']; per-pane element scoping; the inset window surviving pg⇄mpl backend switches via label-keyed LayoutState; RangeEvent(pane='zoom') + view.on(pane=) scoping; per-pane export of just the inset.
…es a Rect indicate=True draws the parent-side rectangle at the child surface's declared x/y lims — the synthesized wave-1 Rect annotation rendered through the parent's element path, so it lowers everywhere with zero new drawing code. Both lims required; missing lims warn-and-skip (the live follow-the-pan indicator is a gated follow-on, design/inset-axes.md I4b). Design: design/inset-axes.md Part II (I4).
…ed palette The parent's curves/grid showed through the inset's margins (ViewBox background covers only the data area). autoFillBackground over the whole PlotItem rect matches matplotlib's opaque inset (spiked visually).
examples/38_inset_zoom.py: an overview curve with a labeled zoom inset and the indicator rectangle; main() demos the pane-scoped RangeEvent subscription. Wired into the capture tool, the gallery, and the example-mains regression list. design/inset-axes.md Part II gains the I1-I4-shipped status note (I5 webengine domain axes stays gated).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements I1–I4 of
design/inset-axes.mdPart II — matplotlib-style inset axes, done the qtviz way:What landed
qv.Inset(child, rect=, label=, indicate=), composed into an overlay like an annotation. NewElement.STRUCTURAL_CHILDdeclared marker ([D124] discipline):resolve_node/node_is_lazyrecurse into the child,_elements_ofyields through it, and both negotiation paths enforce same-surface ⇒ same-backend (explicitnegotiaterecursion + auto intersect). Depth-1 + rect validation. Freeze triple in one commit (FROZEN_2_0+ api.md + CHANGELOG); element census 28 → 29.ax.inset_axes+_render_cellre-entry (~15 lines — theming, surface config, events, PaneBus all inherited). pyqtgraph:_render_cellsplit into_surface_target/_populate_plotshared by grid cells and insets; a childPlotItemplaced fromrect(mpl bottom-origin semantics) on the parent ViewBox'ssigResized(spiked offscreen first), opaque viaautoFillBackground+ themed palette. webengine: warns-and-skips insets until I5 (headless-tested via the figure dict);supports()accepts so negotiation proceeds. Labels thread as a deque in traversal order, matchingflat_pane_labels' depth-first walk. Also fixes a latent [D146] interaction: the mplsharexleader lookup now maps child→surface index (insets shift the surfaces list).LayoutState,RangeEvent(pane="zoom")+view.on(pane=), per-pane export of just the inset.indicate=Truesynthesizes the existingRectannotation at the child's declared x/y lims — zero new drawing code on any backend; missing lims warn-and-skip.38_inset_zoom.py+ screenshot; CLAUDE.md element census updated.Not in this PR
I5 — webengine domain-axes support (replaces the warn-skip); the live follow-the-pan indicator (I4b). Both gated per the design doc.
Verification
+16 tests in
test_inset.py(tier-1 node/pipeline/negotiation + tier-2 across both native backends). Suite 1074 green; ruff/mypy/mkdocs --strict clean; both backends visually verified (opaque panels, correct indicator placement).🤖 Generated with Claude Code