fix drag and drop
This commit is contained in:
parent
930430d5ec
commit
b5fadce142
4 changed files with 71 additions and 23 deletions
|
@ -3,10 +3,10 @@ using Gtk 4.0;
|
||||||
template $AudreyUiPlayQueueSong: Box {
|
template $AudreyUiPlayQueueSong: Box {
|
||||||
height-request: 48;
|
height-request: 48;
|
||||||
spacing: 12;
|
spacing: 12;
|
||||||
margin-start: 6;
|
|
||||||
margin-end: 6;
|
|
||||||
|
|
||||||
Box {
|
Box {
|
||||||
|
margin-start: 6;
|
||||||
|
|
||||||
width-request: 36;
|
width-request: 36;
|
||||||
focusable: false;
|
focusable: false;
|
||||||
homogeneous: true;
|
homogeneous: true;
|
||||||
|
@ -116,6 +116,7 @@ template $AudreyUiPlayQueueSong: Box {
|
||||||
valign: center;
|
valign: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Box {
|
||||||
MenuButton {
|
MenuButton {
|
||||||
// visible: false;
|
// visible: false;
|
||||||
focusable: true;
|
focusable: true;
|
||||||
|
@ -132,6 +133,9 @@ template $AudreyUiPlayQueueSong: Box {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
margin-end: 6;
|
||||||
|
}
|
||||||
|
|
||||||
DragSource {
|
DragSource {
|
||||||
actions: move;
|
actions: move;
|
||||||
propagation-phase: capture;
|
propagation-phase: capture;
|
||||||
|
|
|
@ -19,6 +19,11 @@
|
||||||
min-height: 15px;
|
min-height: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* make drag and drop indicator take up entire perimeter */
|
||||||
|
#play-queue listview row {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
#play-queue .playing label.title {
|
#play-queue .playing label.title {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,8 +112,7 @@ mod imp {
|
||||||
fn on_drag_prepare(&self, x: f64, y: f64) -> Option<gdk::ContentProvider> {
|
fn on_drag_prepare(&self, x: f64, y: f64) -> Option<gdk::ContentProvider> {
|
||||||
if self.draggable.get() {
|
if self.draggable.get() {
|
||||||
self.drag_pos.replace((x as i32, y as i32));
|
self.drag_pos.replace((x as i32, y as i32));
|
||||||
let value = self.obj().to_value();
|
Some(gdk::ContentProvider::for_value(&self.obj().to_value()))
|
||||||
Some(gdk::ContentProvider::for_value(&value))
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -122,6 +121,7 @@ mod imp {
|
||||||
#[template_callback]
|
#[template_callback]
|
||||||
fn on_drag_begin(&self, drag: &gdk::Drag) {
|
fn on_drag_begin(&self, drag: &gdk::Drag) {
|
||||||
let drag_widget = gtk::ListBox::new();
|
let drag_widget = gtk::ListBox::new();
|
||||||
|
drag_widget.add_css_class("boxed-list");
|
||||||
|
|
||||||
let drag_row: super::Song = glib::Object::new();
|
let drag_row: super::Song = glib::Object::new();
|
||||||
drag_row.set_draggable(false);
|
drag_row.set_draggable(false);
|
||||||
|
@ -148,19 +148,23 @@ mod imp {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[template_callback]
|
#[template_callback]
|
||||||
fn on_drop(&self, _value: glib::Value, _x: f64, _y: f64) -> bool {
|
// why BoxedValue? see https://discourse.gnome.org/t/gtk-rs-passing-widget-as-gvalue-through-drag-and-drop-with-composite-template/16449/2
|
||||||
/* FIXME: WrongValueType(ValueTypeMismatchError { actual: GValue, requested: AudreyUiPlayQueueSong })
|
fn on_drop(&self, value: glib::BoxedValue, _x: f64, _y: f64) -> bool {
|
||||||
let source: super::Song = value.get().unwrap();
|
let source: super::Song = value.get().unwrap();
|
||||||
|
|
||||||
source.imp().drag_widget.set(None);
|
source.imp().drag_widget.set(None);
|
||||||
|
|
||||||
self.obj().playbin().move_track(
|
let from = source.position();
|
||||||
source.displayed_position() - 1,
|
let to = self.obj().position();
|
||||||
self.obj().displayed_position() - 1,
|
|
||||||
);
|
|
||||||
|
|
||||||
true */
|
// see playlist_move for justification
|
||||||
false
|
if from < to {
|
||||||
|
self.obj().window().playlist_move(from, to + 1);
|
||||||
|
} else {
|
||||||
|
self.obj().window().playlist_move(from, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_playlist_pos(&self, playlist_pos: i32) {
|
fn set_playlist_pos(&self, playlist_pos: i32) {
|
||||||
|
|
|
@ -627,4 +627,39 @@ impl Window {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn playlist_move(&self, from: u32, to: u32) {
|
||||||
|
// NOTE: for mpv, to refers to the "gap" right before i
|
||||||
|
// so playlist-move i 0 makes a track the first
|
||||||
|
// playlist-move i 1 makes a track the second
|
||||||
|
// and playlist-move i playlist-count makes a track the last
|
||||||
|
// (so if to is the position of another track, from is left behind to)
|
||||||
|
self.imp()
|
||||||
|
.mpv
|
||||||
|
.command(["playlist-move", &from.to_string(), &to.to_string()])
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
if from < to {
|
||||||
|
// F1234T -> 1234FT
|
||||||
|
let mut spliced = Vec::with_capacity((to - from) as usize);
|
||||||
|
for i in from + 1..to {
|
||||||
|
spliced.push(self.playlist_model().item(i).unwrap());
|
||||||
|
}
|
||||||
|
spliced.push(self.playlist_model().item(from).unwrap());
|
||||||
|
|
||||||
|
self.playlist_model()
|
||||||
|
.splice(from, spliced.len() as u32, &spliced);
|
||||||
|
} else if to < from {
|
||||||
|
// T1234F -> FT1234
|
||||||
|
let mut spliced = Vec::with_capacity((from - to + 1) as usize);
|
||||||
|
spliced.push(self.playlist_model().item(from).unwrap());
|
||||||
|
spliced.push(self.playlist_model().item(to).unwrap());
|
||||||
|
for i in to + 1..from {
|
||||||
|
spliced.push(self.playlist_model().item(i).unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
self.playlist_model()
|
||||||
|
.splice(to, spliced.len() as u32, &spliced);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue