layout editor: split a row into cells, resize cells by drag

Add cell `+` buttons (n+1 per figure row), column resize handles with
drag, and update the `x` handler to call remove_cell instead of
remove_row. Fix row_weights_ misalignment in insert_row/remove_row.
Split probe steps 9-15 exercise content movement, column drag clamp,
row-weight tracking, and sensitivity at caps.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Martino FerrariandClaude Opus 4.6 committed 2026-11-03 17:33:29 +01:00
1 parent 62ceb69278
commit 645cb6f4fa
5 files changed
+389 -57

No files matched your search

+15
View File
@@ -208,6 +208,12 @@ struct App {
/// began, so the beginning has to be kept -- reading the weights while dragging would compound.
int layout_drag_row = -1;
std::vector<float> layout_drag_start;
/// Column drag state: which plot (right-hand cell), the two starting widths in logical px,
/// and the cell weights snapshot at drag begin.
int layout_col_drag_plot = -1;
double layout_col_drag_left0 = 0.0;
double layout_col_drag_right0 = 0.0;
std::vector<float> layout_col_drag_start;
/// The editor's way out: one `Done` button in the plot area's top-right corner while
/// the editor is up. Not part of `layout_buttons`, which is one button per row and per
/// boundary -- the count the layout probe asserts.
@@ -1610,6 +1616,12 @@ constexpr const char* kLayoutKindKey = "udpscope-layout-insert";
/// The ↕ handles' own key: what they are is *not* what the `+` is, and `sync_layout_editor()`
/// places them differently -- one boundary, two controls.
constexpr const char* kLayoutResizeKey = "udpscope-layout-resize";
/// Cell `+` buttons carry this key (fr * 8 + pos + 1) so `layout_button()` never matches them.
constexpr const char* kLayoutCellKey = "udpscope-layout-cell";
/// Column resize handles carry the plot index of the right-hand cell.
constexpr const char* kLayoutColKey = "udpscope-layout-col";
/// The minimum width a cell may be dragged to, in logical pixels.
constexpr double kMinCellPx = 96.0;
constexpr gint64 kMeasureRefreshUs = 100 * 1000;
constexpr gint64 kMeasureHeavyUs = 5 * 1000;
constexpr const char* kCursorModeNames[] = {"vertical", "horizontal", "both", "mix"};
@@ -2096,6 +2108,9 @@ gboolean search_probe_run(gpointer user);
gboolean search_probe(gpointer user);
gboolean window_probe(gpointer user);
GtkWidget* layout_button(App& a, bool insert, int index);
GtkWidget* layout_cell_button(App& a, int fr, int pos);
GtkWidget* layout_col_handle(App& a, int plot);
void layout_col_apply(App& app, int plot, double offset_px);
void layout_probe_report(App& a, const char* what);
void layout_click(GtkWidget* b);
void layout_probe_next(App& a, int step, guint delay_ms);