ui: the signal badge is the drag handle (to a plot row, or to reorder); the list rows stop dragging

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Martino FerrariandClaude Opus 4.6 committed 2026-11-03 01:30:55 +01:00
1 parent f27925da59
commit ca10dfb323
9 files changed
+230 -109

No files matched your search

+4 -22
View File
@@ -302,7 +302,7 @@ void rebuild_signal_list(App& app, const std::vector<SignalInfo>& signals) {
// One line per *signal*, not per channel. A group's model holds each signal once per event; a list
// that showed both would name one "sine (A)" and the other "sine (B)" as if they were different
// things, and give them different colours. What the row toggles, colours and drags is the signal.
// things, and give them different colours. What the row toggles and colours is the signal.
std::vector<std::size_t> rows;
// The `MATH` divider goes in before the first math row, and once only: `append_math_signals_locked()`
// has already put every math channel in `signals()`, so the boundary is the one thing the deleted
@@ -350,8 +350,8 @@ void rebuild_signal_list(App& app, const std::vector<SignalInfo>& signals) {
g_signal_connect(pick, "pressed",
G_CALLBACK(+[](GtkGestureClick* g, int, double, double, gpointer user) {
App* a = static_cast<App*>(user);
// Claimed, so the row's `GtkDragSource` cannot take the same sequence
// and turn a click on the chip into the start of a drag.
// Claimed, so the same click does not also activate the row (which would open
// the signal's page).
gtk_gesture_set_state(GTK_GESTURE(g), GTK_EVENT_SEQUENCE_CLAIMED);
open_signal_color(*a, static_cast<std::size_t>(GPOINTER_TO_SIZE(
g_object_get_data(G_OBJECT(g),
@@ -466,25 +466,7 @@ void rebuild_signal_list(App& app, const std::vector<SignalInfo>& signals) {
gtk_list_box_row_set_child(GTK_LIST_BOX_ROW(row), box);
// Activating the row opens the signal's page; the row resolves its identity the way its widgets do.
g_object_set_data(G_OBJECT(row), "udpscope-signal", GSIZE_TO_POINTER(i));
DragContext* ctx = new DragContext{&app, i};
GtkDragSource* source = gtk_drag_source_new();
gtk_drag_source_set_actions(source, GDK_ACTION_COPY);
g_signal_connect_data(source, "prepare", G_CALLBACK(on_drag_prepare), ctx,
[](gpointer data, GClosure*) { delete static_cast<DragContext*>(data); },
G_CONNECT_DEFAULT);
// A drag out of an *overlaid* sidebar would have nowhere to land (see `row_drag_sidebar()`), so the
// sidebar steps out of the way for as long as the drag lasts.
g_signal_connect(source, "drag-begin", G_CALLBACK(+[](GtkDragSource*, GdkDrag*, gpointer user) {
row_drag_sidebar(*static_cast<App*>(user), true);
}),
&app);
g_signal_connect(source, "drag-end",
G_CALLBACK(+[](GtkDragSource*, GdkDrag*, gboolean, gpointer user) {
row_drag_sidebar(*static_cast<App*>(user), false);
}),
&app);
gtk_widget_add_controller(row, GTK_EVENT_CONTROLLER(source));
// Dragging a signal onto a plot is the signal badge's job (`make_signal_badge`): the row opens the page.
gtk_list_box_append(GTK_LIST_BOX(list), row);
}