When dragging a node, don't snap its top-left corner to the cursor

Revamp the node dragging implementation, moving it into the GraphView
widget.

When a drag is initiated, the node widget's current position is stored.
Whenever the drag gesture is updated, the node widget's position is set
by adding the relative drag vector to the position at the start of the
drag.

A drag gesture on the node widget rather than the GraphView widget was
considered, but this seems to lead to a weird flickering effect when the
node is moved while the drag gesture on the node is active.

To avoid interfering with the drag handlers on the ports, check if the
GraphView drag gesture targets a port, in which case the handler does
nothing.
This commit is contained in:
Mathias Rav
2021-05-09 21:51:20 +02:00
committed by Ryuukyu
parent 6d60095da8
commit 3cd19f2d1d
2 changed files with 60 additions and 56 deletions

View File

@@ -1,5 +1,3 @@
use super::graph_view::GraphView;
use gtk::{glib, prelude::*, subclass::prelude::*};
use pipewire::spa::Direction;
@@ -34,35 +32,6 @@ mod imp {
grid.attach(&label, 0, 0, 2, 1);
let motion_controller = gtk::EventControllerMotion::new();
motion_controller.connect_enter(|controller, _, _| {
// Tell the graphview that the Node is the target of a drag when the mouse enters its label
let widget = controller
.widget()
.expect("Controller with enter event has no widget")
.ancestor(super::Node::static_type())
.expect("Node label does not have a node ancestor widget");
widget
.ancestor(GraphView::static_type())
.expect("Node with enter event is not on graph")
.dynamic_cast::<GraphView>()
.unwrap()
.set_dragged(Some(widget));
});
motion_controller.connect_leave(|controller| {
// Tell the graphview that the Node is no longer the target of a drag when the mouse leaves.
// FIXME: Check that we are the current target before setting none.
controller
.widget()
.expect("Controller with leave event has no widget")
.ancestor(GraphView::static_type())
.expect("Node with leave event is not on graph")
.dynamic_cast::<GraphView>()
.unwrap()
.set_dragged(None);
});
label.add_controller(&motion_controller);
// Display a grab cursor when the mouse is over the label so the user knows the node can be dragged.
label.set_cursor(gtk::gdk::Cursor::from_name("grab", None).as_ref());