Rust egui minimal Drag-n-Drop example using egui-dnd

The following example demonstrates a simple Drag-n-Drop usecase.

This is how it looks initially

egui dnd initial

You can grab the icons by the dots on the left and drag them to reorder the blocks:

egui dnd dragging dropping

src/main.rs
use eframe::egui::{self, CornerRadius, FontDefinitions, Margin, RichText};
use egui_dnd::dnd;
use egui_phosphor::{add_to_fonts, regular, Variant};

struct MyApp {
    blocks: Vec<Block>,
}

#[derive(Clone, Hash, PartialEq, Eq)]
struct Block {
    id: usize,
    text: String,
}

impl Default for MyApp {
    fn default() -> Self {
        Self {
            blocks: vec![
                Block {
                    id: 0,
                    text: "Block 1".to_owned(),
                },
                Block {
                    id: 1,
                    text: "Block 2".to_owned(),
                },
                Block {
                    id: 2,
                    text: "Block 3".to_owned(),
                },
            ],
        }
    }
}

impl eframe::App for MyApp {
    fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
        egui::CentralPanel::default().show(ctx, |ui| {
            ui.heading("Draggable Blocks");

            ui.spacing_mut().item_spacing = egui::vec2(8.0, 12.0);

            let response = dnd(ui, "block_list").with_animation_time(0.2).show_vec(
                &mut self.blocks,
                |ui, block, handle, state| {
                    ui.add_space(6.0);

                    let base_frame = egui::Frame::default()
                        .corner_radius(CornerRadius::same(8))
                        .inner_margin(Margin::symmetric(12, 8));

                    let frame = if state.dragged {
                        base_frame
                            .stroke(egui::Stroke::new(
                                2.0,
                                egui::Color32::from_rgb(50, 130, 220),
                            ))
                            .fill(egui::Color32::from_rgb(235, 245, 255))
                    } else {
                        base_frame
                            .stroke(egui::Stroke::new(1.0, egui::Color32::from_gray(150)))
                            .fill(egui::Color32::from_rgb(250, 250, 248))
                    };

                    frame.show(ui, |ui| {
                        ui.horizontal(|ui| {
                            handle.ui(ui, |ui| {
                                ui.label(RichText::new(regular::DOTS_SIX_VERTICAL).size(22.0));
                            });

                            let mut text = RichText::new(&block.text).size(16.0);
                            if state.dragged {
                                text = text.strong();
                            }
                            ui.label(text);
                        });
                    });
                },
            );

            if response.is_dragging() || response.is_evaluating_drag() {
                ctx.request_repaint();
            }
        });
    }
}

fn main() -> eframe::Result<()> {
    let options = eframe::NativeOptions::default();
    eframe::run_native(
        "rust_egui_drag_drop",
        options,
        Box::new(|cc| {
            let mut fonts = FontDefinitions::default();
            add_to_fonts(&mut fonts, Variant::Regular);
            cc.egui_ctx.set_fonts(fonts);
            Ok(Box::<MyApp>::default())
        }),
    )
}
Cargo.toml
[package]
name = "rust_egui_drag_drop"
version = "0.1.0"
edition = "2021"

[dependencies]
eframe = "0.32"
egui = "0.32"
egui_dnd = "0.13"
egui-phosphor = "0.10"

How to run

run_egui_drag_drop.sh
cargo run

Check out similar posts by category: Rust, GUI