feat(plot): Figure with stacked rows and a synchronised x axis

This commit is contained in:
Martino Ferrari committed 2026-09-28 14:42:17 +02:00
1 parent 7cc06f07f5
commit 8f1e60a105
11 files changed
+1665 -24

No files matched your search

+12 -2
View File
@@ -661,6 +661,12 @@ const PlotLayout& Plot::layout() {
y_width = y_axes_.empty() ? 0.0f : 2.0f * pad;
x_height = text_->height() + 2.0f * pad;
}
// A row of a `Figure` gives its x strip to the figure's one shared axis, so it
// reserves none: the seed and the fixed point below both start from zero, and
// `axes` then reaches the viewport's bottom edge. Set here rather than in the
// loop, because the loop's `need_x` is what the strip wants and this overrides
// the want, not the measurement.
if (!x_label_strip_) x_height = 0.0f;
// The title strips, though, are needed before the loop and never change, unlike
// the label strips: a strip holds exactly one text line per titled axis and no
// tick label can change that. Nothing at all is reserved without a text backend
@@ -670,7 +676,7 @@ const PlotLayout& Plot::layout() {
// per titled y axis *wide*, because the y title is drawn rotated and so spends
// its length along the axes' height and takes a column, not a row, per titled
// axis (see y_title_strip_width).
const u32 x_titles = titled_x_axis_count();
const u32 x_titles = x_label_strip_ ? titled_x_axis_count() : 0u;
const f32 y_title_w = text_ != nullptr ? y_title_strip_width() : 0.0f;
const f32 x_title_h = text_ != nullptr && x_titles != 0u
? static_cast<f32>(x_titles) * text_->height() + 2.0f * pad
@@ -710,8 +716,12 @@ const PlotLayout& Plot::layout() {
// The same caps as above, so this compares like with like and the loop still
// reaches its fixed point on the second pass.
const f32 need_y = std::min(std::clamp(y_label_width(), 0.0f, viewport_.w), y_budget);
// Overridden, not merely unmeasured: the strip is not reserved, so the fixed
// point has to be zero for a row that gave its strip away.
const f32 need_x =
std::min(std::clamp(text_->height() + 2.0f * pad, 0.0f, viewport_.h), x_budget);
x_label_strip_
? std::min(std::clamp(text_->height() + 2.0f * pad, 0.0f, viewport_.h), x_budget)
: 0.0f;
if (need_y == y_width && need_x == x_height) break; // strips are a fixed point
y_width = need_y;
x_height = need_x;