fix(plot): a figure row's strip shows labels and title independently, and the shared axis is the bottom row's strip
This commit is contained in:
1 parent
8f1e60a105
commit
770da4c2b2
9 files changed
+415
-175
No files matched your search
+26
-34
@@ -364,27 +364,22 @@ void Renderer::draw(Figure& figure) {
|
||||
for (u32 row = 0; row < rows; ++row) prepare_plot(figure.plot(row));
|
||||
|
||||
// The figure's one layout for the frame. It hands every row its rect and its
|
||||
// x-label policy, advances the link groups, and lays every row out against its own
|
||||
// x-strip mode, advances the link groups, and lays every row out against its own
|
||||
// rect -- which is why the rows below are drawn with the layout it produced rather
|
||||
// than laying each row out a second time. Nothing draws before this: a row's
|
||||
// viewport is the figure's to set.
|
||||
const FigureLayout& layout = figure.layout();
|
||||
//
|
||||
// The figure's one x axis needs no pass of its own: it is the bottom row's own, so
|
||||
// that row stages it in its own strip through `draw_tick_labels()` like any other
|
||||
// plot's axis -- and every row above it reserved no x chrome, which is what keeps
|
||||
// the labels from appearing once per row without a second staging here.
|
||||
figure.layout();
|
||||
for (u32 row = 0; row < rows; ++row) {
|
||||
Plot& plot = figure.plot(row);
|
||||
// The layout the figure just computed, read through the non-recomputing
|
||||
// overload -- the one layout of this frame, not a second derivation of it.
|
||||
draw_plot(plot, static_cast<const Plot&>(plot).layout());
|
||||
}
|
||||
|
||||
// The figure's one shared x axis, staged last so it joins the frame's single text
|
||||
// flush: the labels of the last row's x axes, in the strip the figure measured
|
||||
// under it. The rows reserved no strip of their own for them (see
|
||||
// `Plot::set_x_label_strip()`), which is what keeps one set of labels from being
|
||||
// drawn once per row; with the figure set to label every row, there is no shared
|
||||
// strip and each row drew its own above.
|
||||
if (rows != 0u && figure.x_labels_only_on_bottom() && layout.x_axis_strip.h > 0.0f) {
|
||||
draw_x_tick_labels(figure.plot(rows - 1u), layout.x_axis_strip);
|
||||
}
|
||||
flush_text();
|
||||
}
|
||||
|
||||
@@ -654,32 +649,29 @@ void Renderer::draw_axis_lines(const Plot& plot) {
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::draw_x_tick_labels(const Plot& plot, const Rect& strip) {
|
||||
// Centred under their tick, on the strip's single text line -- the one rule for a
|
||||
// plot's own label strip and for the strip a figure shares out under its last row.
|
||||
// A plot that reserved no strip of its own hands its labels to the figure, which
|
||||
// is why this takes the rect rather than reading the layout it came from.
|
||||
const f32 line_h = font_backend_.height();
|
||||
for (u32 i = 0; i < plot.x_axis_count(); ++i) {
|
||||
const Transform transform = plot.x_transform(i);
|
||||
for (const Tick& tick : plot.x_axis(i).ticks) {
|
||||
if (!tick.major || tick.label.empty()) continue;
|
||||
const f32 width = font_backend_.measure(tick.label.c_str());
|
||||
stage_text({static_cast<f32>(transform.to_screen_x(tick.value)) - 0.5f * width,
|
||||
strip.y + 0.5f * (strip.h - line_h)},
|
||||
tick.label.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::draw_tick_labels(const Plot& plot, const PlotLayout& layout) {
|
||||
const f32 line_h = font_backend_.height();
|
||||
|
||||
// X labels: unless the plot gave its x label strip away -- a row of a `Figure`
|
||||
// whose figure drew one shared axis instead -- in which case it has no strip to
|
||||
// put them in and their absence is the point. A plot with no strip would otherwise
|
||||
// stage its labels just above `axes`' bottom edge, i.e. over its own data.
|
||||
if (plot.x_label_strip()) draw_x_tick_labels(plot, layout.x_label_area);
|
||||
// that reserves no x chrome, because the figure draws one shared axis in the bottom
|
||||
// row's own strip instead -- in which case it has no strip to put them in and their
|
||||
// absence is the point. A plot with no strip would otherwise stage its labels just
|
||||
// above `axes`' bottom edge, i.e. over its own data. Centred under their tick on the
|
||||
// strip's single text line, which is the one rule for a plot's labels and a figure's
|
||||
// shared axis alike -- the figure's axis is drawn by this same pass, in the bottom
|
||||
// row's own `x_label_area`.
|
||||
if (x_strip_has_labels(plot.x_strip_mode())) {
|
||||
for (u32 i = 0; i < plot.x_axis_count(); ++i) {
|
||||
const Transform transform = plot.x_transform(i);
|
||||
for (const Tick& tick : plot.x_axis(i).ticks) {
|
||||
if (!tick.major || tick.label.empty()) continue;
|
||||
const f32 width = font_backend_.measure(tick.label.c_str());
|
||||
stage_text({static_cast<f32>(transform.to_screen_x(tick.value)) - 0.5f * width,
|
||||
layout.x_label_area.y + 0.5f * (layout.x_label_area.h - line_h)},
|
||||
tick.label.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Y labels: right-aligned in their strip, centred on the tick and pulled back
|
||||
// inside the strip at the two extremes (a label centred on the top tick would
|
||||
|
||||
Reference in new issue
Block a user