lucasmerlin / hello_egui

A collection of useful crates for egui
https://lucasmerlin.github.io/hello_egui/
MIT License
272 stars 24 forks source link

Weird snap animation on drop when using indices as an Id #14

Closed juh9870 closed 11 months ago

juh9870 commented 11 months ago

When indices (enumerate) is used as ID for a list with duplicate items, there is a weird snapping animation when dropping an item on a different position.

Here is a modified update_on_drop example to illustrate the issue.

use eframe::egui;
use egui::CentralPanel;
use egui_dnd::{dnd, DragDropItem};
use egui::Id;

struct DragWrapper<T>(usize, T);
impl<T> DragDropItem for DragWrapper<T> {
    fn id(&self) -> Id {
        Id::new(self.0)
    }
}

pub fn main() -> eframe::Result<()> {
    let mut items = vec!["alfred", "bernhard", "christian", "christian", "christian"];

    eframe::run_simple_native(
        "DnD Simple Example",
        Default::default(),
        move |ctx, _frame| {
            CentralPanel::default().show(ctx, |ui| {
                ui.label("Drag and drop the items below");
                ui.style_mut().animation_time = 0.5;

                let response =
                    dnd(ui, "dnd_example").show(items.iter().enumerate().map(|(i,e)| DragWrapper(i,e)), |ui, item, handle, state| {
                        handle.ui(ui, |ui| {
                            if state.dragged {
                                ui.label("dragging");
                            } else {
                                ui.label("drag");
                            }
                        });
                        ui.label(*item.1);
                    });

                if response.is_drag_finished() {
                    response.update_vec(&mut items);
                }

                ui.label("Another label");
            });
        },
    )
}

Unlike this example, in my actual app, there is no sane way to pre-index the Vec, like what is done in sort_words example. I only get &mut Vec<T> and I can't ensure that T is unique in any way.

lucasmerlin commented 11 months ago

I think the problem is that I use the items Id to track which item should be animated after the drag finishes, and since the id's change since you use the items index as id this now animates the wrong item. I haven't found a good solution to work around this. I tried using the index instead of the id but couldn't make that work.

I've just released egui_dnd 0.5.1 which adds the option to configure the animation duration for the swap and return animations, so you could now use dnd(..).with_return_animation_time(0.0) to completely disable the return animation.

juh9870 commented 11 months ago

Thanks, good enough for me!

lucasmerlin commented 11 months ago

Awesome! It's not really fixed but I'll still close the issue since I'm not sure if this is possible to be fixed. If someone stumbles over this in the future, feel free to reopen!