egui icon indicating copy to clipboard operation
egui copied to clipboard

Double use of widget ID with context menu on draggable area

Open flodiebold opened this issue 1 year ago • 2 comments

Describe the bug I have an Area that is moveable by dragging it, and has a context menu. As soon as it's moved from the starting position, I get a big "Double use of widget ID" warning. This might very well be me doing something wrong, but I don't see what or how I can avoid it. The ID it's complaining about is not the ID of the area, but the ID of the response.

To Reproduce

use eframe::egui::{self, Area, Color32, Frame, Id, Pos2, Vec2};

fn main() -> eframe::Result {
    env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`).

    let options = eframe::NativeOptions {
        viewport: egui::ViewportBuilder::default().with_inner_size([320.0, 240.0]),
        ..Default::default()
    };

    let mut pos = Pos2::new(40., 40.);

    eframe::run_simple_native("My egui App", options, move |ctx, _frame| {
        egui::CentralPanel::default().show(ctx, |ui| {
            let area = Area::new(Id::new("area"));
            let area_response = area.current_pos(pos).show(ui.ctx(), |ui| {
                let frame = Frame::default().fill(Color32::from_rgb(70, 70, 70)); // The frame is just to see better, it's not necessary to reproduce the problem
                frame.show(ui, |ui| {
                    ui.allocate_space(Vec2::new(100., 100.));
                });
            });

            if area_response.response.dragged() {
                let delta = ui.ctx().input(|i| i.pointer.delta());
                pos[0] += delta.x;
                pos[1] += delta.y;
            }
            area_response.response.context_menu(|_ui| {});
        });
    })
}

Click and drag the gray area a bit.

Expected behavior No warning.

Screenshots 2024-08-08-213701_307x254_scrot

Desktop (please complete the following information): OS: Linux. Reproduced under egui 2dac4a4f (current master).

flodiebold avatar Aug 08 '24 19:08 flodiebold

I'm not sure why it tries to use the same ID in this case, as the code that handles that is fairly complex and changing all the time, but for the record you can avoid this problem by putting the context menu inside the Area's UI:

use eframe::egui::{self, Area, Color32, Id, Pos2, Sense};

fn main() -> eframe::Result {
    let options = eframe::NativeOptions {
        viewport: egui::ViewportBuilder::default().with_inner_size([320.0, 240.0]),
        ..Default::default()
    };

    let mut pos = Pos2::new(40., 40.);

    eframe::run_simple_native("My egui App", options, move |ctx, _frame| {
        egui::CentralPanel::default().show(ctx, |ui| {
            let area = Area::new(Id::new("area"));
            let area_response = area
                .current_pos(pos)
                .show(ui.ctx(), |ui| {
                    ui.allocate_response([100.0; 2].into(), Sense::hover())
                        .context_menu(|ui| {
                            ui.menu_button("Menu", |ui| {
                                ui.button("Button1");
                                ui.button("Button2");
                            });
                        });
                    ui.painter().rect_filled(ui.min_rect(), 0.0, Color32::RED);
                })
                .response;
            if area_response.dragged() {
                pos += area_response.drag_delta();
            }
        });
    })
}

https://github.com/user-attachments/assets/1f756b7c-059d-4c21-bf1d-18ac22293e47

YgorSouza avatar Aug 09 '24 06:08 YgorSouza

That works, thanks!

flodiebold avatar Aug 09 '24 07:08 flodiebold