wip(plot): region layout, hot handles and draggable handles (build restored)

This commit is contained in:
Martino Ferrari committed 2026-09-28 13:28:51 +02:00
1 parent 7d2349555d
commit e4d48cc6c3
9 files changed
+915 -37

No files matched your search

+26 -2
View File
@@ -106,8 +106,17 @@ class Renderer {
/// physical size on a 1x panel and a 2x one.
///
/// `Plot::layout()` is computed exactly once, here, and handed to every helper:
/// it runs the auto scale, the strip fixed-point loop and the grid build, so
/// re-deriving it per helper would rebuild the ticks and the grid per helper.
/// it runs the auto scale, the strip fixed-point loop, the grid build and the
/// region geometry, so re-deriving it per helper would rebuild all of that per
/// helper.
///
/// The handles a pointer is on are drawn highlighted -- a cursor marker is widened
/// into a tab, a region bound is drawn in the style's cursor colour at the width
/// `PlotLayout` sized its handle at -- and what is hot comes from
/// `Plot::hot_handles()`, which the input layer publishes. The renderer therefore
/// never sees a pointer, a button or a gesture: it draws what the plot says is
/// being manipulated, and only when a host drives the plot with a controller is
/// anything ever hot.
///
/// A legend the plot has is part of the frame: the panel and its swatches are
/// line geometry staged with everything else, the names are glyphs on the text
@@ -115,6 +124,11 @@ class Renderer {
/// line batch, so the legend cannot be drawn under a trace, and it leaves no GL
/// state of its own -- the frame's blend and its neighbours' scissor already say
/// everything a fill and a hairline border need (see end_frame's residue list).
///
/// Regions are part of that same evidence: the fill is one instance of the line
/// pipeline (`fill_pixels()`, the primitive the legend panel uses), the bounds are
/// vertical strokes and the label is a staged glyph run, so a frame with regions
/// leaves behind exactly what a frame without them does.
void draw(Plot& plot);
/// Ends the frame, draining `glGetError()` in a loop so a stale error cannot be
@@ -316,6 +330,16 @@ class Renderer {
/// pins.
void draw_traces(const Plot& plot, const PlotLayout& layout);
void draw_cursors(const Plot& plot, const PlotLayout& layout);
/// The regions: the fill, one bound per edge, the optional label. Every rect comes
/// from `PlotLayout::regions` -- the same geometry the controller hit-tests -- so
/// a region is drawn where it can be grabbed, and neither side derives the other's
/// rects.
void draw_regions(const Plot& plot, const PlotLayout& layout);
/// One region bound: a vertical stroke of `width` down the tab's own column, in
/// `color`. The column is `handle_column()` of the tab -- the bound the layout
/// placed -- and a bound outside the axes' columns is skipped, exactly as a cursor
/// marker out of the visible window is.
void draw_region_edge(const Rect& tab, const Rect& axes, Color color, f32 width);
void draw_measures(const Plot& plot, const PlotLayout& layout);
void draw_annotations(const Plot& plot);
/// The legend: the panel and its swatches as line geometry, the names on the text
+7
View File
@@ -68,6 +68,13 @@ struct Style {
bool grid_minor_visible = true; ///< stage the minor grid at all.
f32 line_width_px = 1.5f; ///< logical width of the strokes framing the data
///< (axis lines, cursor markers).
/// Logical width of a *draggable handle* drawn highlighted: the tab a hovered or
/// grabbed cursor marker is widened to, and the tab a region's hot bound is drawn
/// as -- the latter sized by `Plot::layout()` with this same metric, so the two
/// kinds of handle are one width. Wider than `line_width_px` on purpose: the cue
/// for "this marker will follow your drag" has to be visible on a marker whose
/// own colour may already be the accent.
f32 handle_width_px = 5.0f;
f32 tick_min_px = 60.0f; ///< logical minimum spacing between major ticks, so
///< a 2x display gets the same tick *count*.