layout editor: column drag follows the pointer through the cell floor

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Martino FerrariandClaude Opus 4.6 committed 2026-11-03 19:18:18 +01:00
1 parent 2183317953
commit 4fab14949c
5 files changed
+127 -52

No files matched your search

+24 -10
View File
@@ -758,30 +758,37 @@ void layout_col_apply(App& app, int plot, double offset_px) {
const int fr = rs.figure_row_of(plot);
const int k = rs.cell_of(plot);
if (fr < 0 || k < 1) return;
// The weights the drag began with: a drag is relative to its start, so reading the live weights here
// would compound with every update.
if (app.layout_col_drag_start.size() != static_cast<std::size_t>(rs.cells_in_row(fr))) return;
const double scale =
app.area != nullptr && app.area->device_scale() > 0.0f ? app.area->device_scale() : 1.0;
const double pair = app.layout_col_drag_left0 + app.layout_col_drag_right0;
const double floor = std::min(kMinCellPx, pair * 0.5);
const double want_left = std::clamp(app.layout_col_drag_left0 + offset_px / scale,
floor, pair - floor);
std::vector<float> w = rs.cell_weights(fr);
w.resize(static_cast<std::size_t>(rs.cells_in_row(fr)), 1.0f);
// The plotter lays a cell out as `floor + extra * weight / total`, so a width is *not* proportional to
// its weight: the pair's `pair` px are `2 * floor` plus `(pair - 2 * floor)` shared by the two weights.
// Solve for the share that puts the left cell at `want_left`; the pair's weight sum stays what it was,
// which keeps the pair's total width (and every other cell) where it was.
const double spare = pair - 2.0 * kPlotterMinCellPx;
const double frac = spare > 0.0
? std::clamp((want_left - kPlotterMinCellPx) / spare, 0.001, 0.999)
: 0.5;
std::vector<float> w = app.layout_col_drag_start;
const float sum = w[static_cast<std::size_t>(k - 1)] + w[static_cast<std::size_t>(k)];
w[static_cast<std::size_t>(k - 1)] = static_cast<float>(sum * want_left / pair);
w[static_cast<std::size_t>(k - 1)] = static_cast<float>(sum * frac);
w[static_cast<std::size_t>(k)] = sum - w[static_cast<std::size_t>(k - 1)];
rs.set_cell_weights(fr, w);
if (app.area_widget != nullptr) gtk_gl_area_queue_render(GTK_GL_AREA(app.area_widget));
}
void on_layout_col_begin(GtkGestureDrag* gesture, double, double, gpointer user) {
App& app = *static_cast<App*>(user);
app.layout_col_drag_plot =
GPOINTER_TO_INT(g_object_get_data(G_OBJECT(gesture), "udpscope-layout-col-drag"));
const int plot = app.layout_col_drag_plot;
if (plot < 0 || plot >= app.rows->row_count()) return;
bool layout_col_drag_begin(App& app, int plot) {
app.layout_col_drag_plot = plot;
if (app.rows == nullptr || plot < 1 || plot >= app.rows->row_count()) return false;
const int fr = app.rows->figure_row_of(plot);
const int k = app.rows->cell_of(plot);
if (fr < 0 || k < 1) return;
if (fr < 0 || k < 1) return false;
const plot::FigureLayout& fl = app.rows->figure().layout();
const double scale =
app.area != nullptr && app.area->device_scale() > 0.0f ? app.area->device_scale() : 1.0;
@@ -789,6 +796,13 @@ void on_layout_col_begin(GtkGestureDrag* gesture, double, double, gpointer user)
app.layout_col_drag_right0 = static_cast<double>(fl.cells[static_cast<std::size_t>(plot)].w) / scale;
app.layout_col_drag_start = app.rows->cell_weights(fr);
app.layout_col_drag_start.resize(static_cast<std::size_t>(app.rows->cells_in_row(fr)), 1.0f);
return true;
}
void on_layout_col_begin(GtkGestureDrag* gesture, double, double, gpointer user) {
App& app = *static_cast<App*>(user);
layout_col_drag_begin(
app, GPOINTER_TO_INT(g_object_get_data(G_OBJECT(gesture), "udpscope-layout-col-drag")));
}
void on_layout_col_update(GtkGestureDrag*, double offset_x, double, gpointer user) {