Refactor: Setup Drag Source and Drop Targets in UI files

This commit is contained in:
June 2023-01-22 20:06:02 +01:00
commit 596c8d3cdc
No known key found for this signature in database
GPG key ID: 094C2AC34192FA11
4 changed files with 129 additions and 118 deletions

View file

@ -23,95 +23,6 @@ var PrefsBoxOrderItemRow = GObject.registerClass({
this._associateItem(item);
this._configureMenu();
// Make `this` draggable by creating a drag source and adding it to
// `this`.
let dragSource = new Gtk.DragSource();
dragSource.set_actions(Gdk.DragAction.MOVE);
dragSource.connect("prepare", (source, x, y) => {
this._drag_starting_point_x = x;
this._drag_starting_point_y = y;
return Gdk.ContentProvider.new_for_value(this);
});
// Stop all scrolling, which is due to this DND operation.
dragSource.connect("drag-end", () => {
scrollManager.stopScrollAll();
});
dragSource.connect("drag-begin", (source, drag) => {
let dragWidget = new Gtk.ListBox();
let allocation = this.get_allocation();
dragWidget.set_size_request(allocation.width, allocation.height);
let dragPrefsBoxOrderItemRow = new PrefsBoxOrderItemRow({}, this.item)
dragWidget.append(dragPrefsBoxOrderItemRow);
dragWidget.drag_highlight_row(dragPrefsBoxOrderItemRow);
let currentDragIcon = Gtk.DragIcon.get_for_drag(drag);
currentDragIcon.set_child(dragWidget);
drag.set_hotspot(this._drag_starting_point_x, this._drag_starting_point_y);
});
this.add_controller(dragSource);
/// Make `this` accept drops by creating a drop target and adding it to
/// `this`.
let dropTarget = new Gtk.DropTarget();
dropTarget.set_gtypes([this.constructor.$gtype]);
dropTarget.set_actions(Gdk.DragAction.MOVE);
// Handle a new drop on `this` properly.
// `value` is the thing getting dropped.
dropTarget.connect("drop", (target, value) => {
// If `this` got dropped onto itself, do nothing.
if (value === this) {
return;
}
// Get the GtkListBoxes of `this` and the drop value.
const ownListBox = this.get_parent();
const valueListBox = value.get_parent();
// Get the position of `this` and the drop value.
const ownPosition = this.get_index();
const valuePosition = value.get_index();
// Remove the drop value from its list box.
valueListBox.remove(value);
// Since an element got potentially removed from the list of `this`,
// get the position of `this` again.
const updatedOwnPosition = this.get_index();
if (ownListBox !== valueListBox) {
// First handle the case where `this` and the drop value are in
// different list boxes.
if ((ownListBox.boxOrder === "right-box-order" && valueListBox.boxOrder === "left-box-order")
|| (ownListBox.boxOrder === "right-box-order" && valueListBox.boxOrder === "center-box-order")
|| (ownListBox.boxOrder === "center-box-order" && valueListBox.boxOrder === "left-box-order")) {
// If the list box of the drop value comes before the list
// box of `this`, add the drop value after `this`.
ownListBox.insert(value, updatedOwnPosition + 1);
} else {
// Otherwise, add the drop value where `this` currently is.
ownListBox.insert(value, updatedOwnPosition);
}
} else {
if (valuePosition < ownPosition) {
// If the drop value was before `this`, add the drop value
// after `this`.
ownListBox.insert(value, updatedOwnPosition + 1);
} else {
// Otherwise, add the drop value where `this` currently is.
ownListBox.insert(value, updatedOwnPosition);
}
}
/// Finally save the box order(/s) to settings.
ownListBox.saveBoxOrderToSettings();
// If the list boxes of `this` and the drop value were different,
// save an updated box order for the list were the drop value was in
// as well.
if (ownListBox !== valueListBox) valueListBox.saveBoxOrderToSettings();
});
this.add_controller(dropTarget);
}
/**
@ -147,4 +58,88 @@ var PrefsBoxOrderItemRow = GObject.registerClass({
actionGroup.add_action(forgetAction);
this.insert_action_group(`prefsBoxOrderItemRow-${this.item}`, actionGroup);
}
onDragPrepare(_source, x, y) {
const value = new GObject.Value();
value.init(PrefsBoxOrderItemRow);
value.set_object(this);
this._drag_starting_point_x = x;
this._drag_starting_point_y = y;
return Gdk.ContentProvider.new_for_value(value);
}
onDragBegin(_source, drag) {
let dragWidget = new Gtk.ListBox();
let allocation = this.get_allocation();
dragWidget.set_size_request(allocation.width, allocation.height);
let dragPrefsBoxOrderItemRow = new PrefsBoxOrderItemRow({}, this.item)
dragWidget.append(dragPrefsBoxOrderItemRow);
dragWidget.drag_highlight_row(dragPrefsBoxOrderItemRow);
let currentDragIcon = Gtk.DragIcon.get_for_drag(drag);
currentDragIcon.set_child(dragWidget);
drag.set_hotspot(this._drag_starting_point_x, this._drag_starting_point_y);
}
onDragEnd() {
// Stop all scrolling, which is due to this DND operation.
scrollManager.stopScrollAll();
}
// Handle a new drop on `this` properly.
// `value` is the thing getting dropped.
onDrop(_target, value, _x, _y) {
// If `this` got dropped onto itself, do nothing.
if (value === this) {
return;
}
// Get the GtkListBoxes of `this` and the drop value.
const ownListBox = this.get_parent();
const valueListBox = value.get_parent();
// Get the position of `this` and the drop value.
const ownPosition = this.get_index();
const valuePosition = value.get_index();
// Remove the drop value from its list box.
valueListBox.remove(value);
// Since an element got potentially removed from the list of `this`,
// get the position of `this` again.
const updatedOwnPosition = this.get_index();
if (ownListBox !== valueListBox) {
// First handle the case where `this` and the drop value are in
// different list boxes.
if ((ownListBox.boxOrder === "right-box-order" && valueListBox.boxOrder === "left-box-order")
|| (ownListBox.boxOrder === "right-box-order" && valueListBox.boxOrder === "center-box-order")
|| (ownListBox.boxOrder === "center-box-order" && valueListBox.boxOrder === "left-box-order")) {
// If the list box of the drop value comes before the list
// box of `this`, add the drop value after `this`.
ownListBox.insert(value, updatedOwnPosition + 1);
} else {
// Otherwise, add the drop value where `this` currently is.
ownListBox.insert(value, updatedOwnPosition);
}
} else {
if (valuePosition < ownPosition) {
// If the drop value was before `this`, add the drop value
// after `this`.
ownListBox.insert(value, updatedOwnPosition + 1);
} else {
// Otherwise, add the drop value where `this` currently is.
ownListBox.insert(value, updatedOwnPosition);
}
}
/// Finally save the box order(/s) to settings.
ownListBox.saveBoxOrderToSettings();
// If the list boxes of `this` and the drop value were different,
// save an updated box order for the list were the drop value was in
// as well.
if (ownListBox !== valueListBox) valueListBox.saveBoxOrderToSettings();
}
});