Skip to content

Commit

Permalink
Implement reordering records with drag-and-drop
Browse files Browse the repository at this point in the history
  • Loading branch information
andy128k committed Nov 20, 2023
1 parent d0b8374 commit 20adb96
Show file tree
Hide file tree
Showing 8 changed files with 398 additions and 75 deletions.
27 changes: 27 additions & 0 deletions src/ui/file_pane.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ mod imp {
use crate::model::record::RECORD_TYPES;
use crate::primary_accel;
use crate::ui::record_type_popover::RecordTypePopoverBuilder;
use crate::ui::record_view::item::DropOption;
use crate::utils::typed_list_store::TypedListStore;
use crate::utils::ui::{action_button, action_popover_button};
use std::cell::RefCell;
Expand Down Expand Up @@ -154,6 +155,7 @@ mod imp {
imp.go_up().await
});
}));
self.view.connect_move_record(glib::clone!(@weak self as imp => move |_, src, dst, opt| imp.move_record(src, dst, opt)));

self.set_view_model(&self.file.borrow().records);

Expand Down Expand Up @@ -254,6 +256,31 @@ mod imp {
self.obj().emit_edit_record(position, &record);
}
}

fn move_record(&self, src: &RecordNode, dst: &RecordNode, option: DropOption) {
let Some(src_pos) = self.current_records.borrow().iter().position(|r| r == *src) else {
return;
};
self.current_records.borrow().remove(src_pos as u32);

let dst_pos = self.current_records.borrow().iter().position(|r| r == *dst);
match option {
DropOption::Above => {
self.current_records
.borrow()
.insert(dst_pos.unwrap_or(0), src);
}
DropOption::Below => {
self.current_records
.borrow()
.insert(dst_pos.map(|p| p + 1), src);
}
DropOption::Into => {
self.obj().append_records_to(Some(dst), &[src.clone()]);
}
}
self.obj().emit_file_changed();
}
}
}

Expand Down
60 changes: 60 additions & 0 deletions src/ui/record_view/compose_paintable.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
use gtk::{gdk, glib, graphene, prelude::*, subclass::prelude::*};

mod imp {
use super::*;
use std::cell::OnceCell;

#[derive(Default)]
pub struct PSBackgroundPaintable {
pub next: OnceCell<gdk::Paintable>,
}

#[glib::object_subclass]
impl ObjectSubclass for PSBackgroundPaintable {
const NAME: &'static str = "PSBackgroundPaintable";
type Type = super::PSBackgroundPaintable;
type ParentType = glib::Object;
type Interfaces = (gdk::Paintable,);
}

impl ObjectImpl for PSBackgroundPaintable {}

impl PaintableImpl for PSBackgroundPaintable {
fn intrinsic_width(&self) -> i32 {
match self.next.get() {
Some(next) => next.intrinsic_width(),
None => self.parent_intrinsic_width(),
}
}

fn intrinsic_height(&self) -> i32 {
match self.next.get() {
Some(next) => next.intrinsic_height(),
None => self.parent_intrinsic_height(),
}
}

fn snapshot(&self, snapshot: &gdk::Snapshot, width: f64, height: f64) {
snapshot.append_color(
&gdk::RGBA::new(0.5, 0.5, 0.8, 1.0),
&graphene::Rect::new(0.0, 0.0, width as f32, height as f32),
);
if let Some(next) = self.next.get() {
next.snapshot(snapshot, width, height);
}
}
}
}

glib::wrapper! {
pub struct PSBackgroundPaintable(ObjectSubclass<imp::PSBackgroundPaintable>)
@implements gdk::Paintable;
}

impl PSBackgroundPaintable {
pub fn new(next: impl glib::IsA<gdk::Paintable>) -> Self {
let obj: Self = glib::Object::builder().build();
obj.imp().next.set(next.upcast()).unwrap();
obj
}
}
10 changes: 10 additions & 0 deletions src/ui/record_view/item.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.ps-list-item.drop-above:drop(active) {
box-shadow: inset 0 2px 0 0 #08c;
}
.ps-list-item.drop-into:drop(active) {
box-shadow: inset 0 0 0 0 #08c;
background-color: #5ac;
}
.ps-list-item.drop-below:drop(active) {
box-shadow: inset 0 -2px 0 0 #08c;
}
Loading

0 comments on commit 20adb96

Please sign in to comment.