Add some polish to account edditor list drag and drop

Paint the row that was picked up as the drag icon, dim the actual row
and don't highlight it when dragging over itself.

Icon drawing code courtesy ebassi's tutorial:
https://blog.gtk.org/2017/04/23/drag-and-drop-in-lists/
This commit is contained in:
Michael Gratton 2018-12-02 15:11:15 +11:00 committed by Michael James Gratton
parent 9aab053382
commit f630e03485
2 changed files with 81 additions and 1 deletions

View file

@ -17,6 +17,8 @@ internal class Accounts.EditorRow<PaneType> : Gtk.ListBoxRow {
protected Gtk.Grid layout { get; private set; default = new Gtk.Grid(); }
private Gtk.Container drag_handle;
private bool drag_picked_up = false;
private bool drag_entered = false;
public signal void dropped(EditorRow target);
@ -64,13 +66,21 @@ internal class Accounts.EditorRow<PaneType> : Gtk.ListBoxRow {
Gtk.drag_dest_set(
this,
Gtk.DestDefaults.ALL,
// No highlight, we'll take care of that ourselves so we
// can avoid highlighting the row that was picked up
Gtk.DestDefaults.MOTION | Gtk.DestDefaults.DROP,
DRAG_ENTRIES,
Gdk.DragAction.MOVE
);
this.drag_handle.drag_begin.connect(on_drag_begin);
this.drag_handle.drag_end.connect(on_drag_end);
this.drag_handle.drag_data_get.connect(on_drag_data_get);
this.drag_motion.connect(on_drag_motion);
this.drag_leave.connect(on_drag_leave);
this.drag_data_received.connect(on_drag_data_received);
this.drag_handle.get_style_context().add_class("geary-drag-handle");
this.drag_handle.show();
@ -78,6 +88,66 @@ internal class Accounts.EditorRow<PaneType> : Gtk.ListBoxRow {
}
private void on_drag_begin(Gdk.DragContext context) {
// Draw a nice drag icon
Gtk.Allocation alloc = Gtk.Allocation();
this.get_allocation(out alloc);
Cairo.ImageSurface surface = new Cairo.ImageSurface(
Cairo.Format.ARGB32, alloc.width, alloc.height
);
Cairo.Context paint = new Cairo.Context(surface);
Gtk.StyleContext style = get_style_context();
style.add_class("geary-drag-icon");
draw(paint);
style.remove_class("geary-drag-icon");
int x, y;
this.drag_handle.translate_coordinates(this, 0, 0, out x, out y);
surface.set_device_offset(-x, -y);
Gtk.drag_set_icon_surface(context, surface);
// Set a visual hint that the row is being dragged
style.add_class("geary-drag-source");
this.drag_picked_up = true;
}
private void on_drag_end(Gdk.DragContext context) {
get_style_context().remove_class("geary-drag-source");
this.drag_picked_up = false;
}
private bool on_drag_motion(Gdk.DragContext context,
int x, int y,
uint time_) {
if (!this.drag_entered) {
this.drag_entered = true;
// Don't highlight the same row that was picked up
if (!this.drag_picked_up) {
Gtk.ListBox? parent = get_parent() as Gtk.ListBox;
if (parent != null) {
parent.drag_highlight_row(this);
}
}
}
return true;
}
private void on_drag_leave(Gdk.DragContext context,
uint time_) {
if (!this.drag_picked_up) {
Gtk.ListBox? parent = get_parent() as Gtk.ListBox;
if (parent != null) {
parent.drag_unhighlight_row();
}
}
this.drag_entered = false;
}
private void on_drag_data_get(Gdk.DragContext context,
Gtk.SelectionData selection_data,
uint info, uint time_) {

View file

@ -212,6 +212,16 @@ row.geary-settings image {
padding: 0px 6px;
}
row.geary-settings.geary-drag-source {
color: @insensitive_fg_color;
background-color: @insensitive_bg_color;
}
row.geary-settings.geary-drag-icon {
background-color: @theme_base_color;
border: 1px solid @borders;
}
row.geary-settings > grid > * {
margin: 18px 6px;
}