Skip to content

Commit 701baf9

Browse files
committed
Apply context menu to Response
1 parent 330fb62 commit 701baf9

File tree

9 files changed

+99
-78
lines changed

9 files changed

+99
-78
lines changed

egui/src/context.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,8 +300,8 @@ impl CtxRef {
300300
}
301301

302302

303-
pub(crate) fn show_ui_context_menu(&self, ui: &mut Ui, add_contents: impl FnOnce(&mut Ui, &mut MenuState)) {
304-
self.context_menu_system().ui_context_menu(ui, add_contents)
303+
pub(crate) fn show_ui_context_menu(&self, response: &Response, add_contents: impl FnOnce(&mut Ui, &mut MenuState)) {
304+
self.context_menu_system().ui_context_menu(response, add_contents)
305305
}
306306
}
307307

egui/src/context_menu.rs

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,29 +12,23 @@ pub struct ContextMenuSystem {
1212
context_menu: Option<ContextMenuRoot>,
1313
}
1414
impl ContextMenuSystem {
15-
fn response(&mut self, ui: &mut Ui, add_contents: impl FnOnce(&mut Ui, &mut MenuState)) -> MenuResponse {
16-
if let Some(context_menu) = &mut self.context_menu {
17-
if context_menu.ui_id == ui.id() {
18-
let response = context_menu.show(ui.ctx(), add_contents);
19-
context_menu.rect = response.rect;
20-
21-
if context_menu.response.is_close() {
22-
return MenuResponse::Close;
23-
}
24-
}
25-
}
26-
let pointer = &ui.input().pointer;
27-
if let Some(pos) = pointer.interact_pos() {
28-
if pointer.any_pressed() {
15+
fn sense_click(&mut self, response: &Response) -> MenuResponse {
16+
let Response {
17+
id,
18+
ctx,
19+
..
20+
} = response;
21+
let pointer = &ctx.input().pointer;
22+
if pointer.any_pressed() {
23+
if let Some(pos) = pointer.interact_pos() {
2924
let mut destroy = false;
3025
let mut in_old_menu = false;
3126
if let Some(context_menu) = &mut self.context_menu {
3227
in_old_menu = context_menu.area_contains(pos);
33-
destroy = context_menu.ui_id == ui.id();
28+
destroy = context_menu.ui_id == *id;
3429
}
35-
let in_ui = ui.rect_contains_pointer(ui.max_rect_finite());
3630
if !in_old_menu {
37-
if in_ui {
31+
if response.hovered() {
3832
if pointer.button_down(PointerButton::Secondary) {
3933
// todo: adapt to context
4034
return MenuResponse::Create(pos);
@@ -49,15 +43,31 @@ impl ContextMenuSystem {
4943
}
5044
MenuResponse::Stay
5145
}
52-
pub fn ui_context_menu(&mut self, ui: &mut Ui, add_contents: impl FnOnce(&mut Ui, &mut MenuState)) {
53-
match self.response(ui, add_contents) {
46+
fn show(&mut self, response: &Response, add_contents: impl FnOnce(&mut Ui, &mut MenuState)) -> MenuResponse {
47+
if let Some(context_menu) = &mut self.context_menu {
48+
if context_menu.ui_id == response.id {
49+
let response = context_menu.show(&response.ctx, add_contents);
50+
context_menu.rect = response.rect;
51+
52+
if context_menu.response.is_close() {
53+
return MenuResponse::Close;
54+
}
55+
}
56+
}
57+
MenuResponse::Stay
58+
}
59+
pub fn ui_context_menu(&mut self, response: &Response, add_contents: impl FnOnce(&mut Ui, &mut MenuState)) {
60+
match self.sense_click(response) {
5461
MenuResponse::Create(pos) => {
55-
self.context_menu = Some(ContextMenuRoot::new(pos, ui.id()));
62+
self.context_menu = Some(ContextMenuRoot::new(pos, response.id));
5663
},
5764
MenuResponse::Close => {
5865
self.context_menu = None
5966
},
6067
MenuResponse::Stay => {}
68+
};
69+
if let MenuResponse::Close = self.show(response, add_contents) {
70+
self.context_menu = None
6171
}
6272
}
6373
}

egui/src/response.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,11 @@ impl Response {
451451
self.ctx.output().events.push(event);
452452
}
453453
}
454+
455+
pub fn context_menu(&self, add_contents: impl FnOnce(&mut Ui, &mut super::context_menu::MenuState)) -> &Self {
456+
self.ctx.show_ui_context_menu(&self, add_contents);
457+
self
458+
}
454459
}
455460

456461
impl Response {

egui/src/ui.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -327,9 +327,6 @@ impl Ui {
327327
self.painter.set_clip_rect(clip_rect);
328328
}
329329

330-
pub fn context_menu(&mut self, add_contents: impl FnOnce(&mut Ui, &mut MenuState)) {
331-
self.ctx().clone().show_ui_context_menu(self, add_contents)
332-
}
333330
}
334331

335332
// ------------------------------------------------------------------------

egui_demo_lib/src/apps/demo/drag_and_drop.rs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -119,12 +119,6 @@ impl super::View for DragAndDropDemo {
119119
let mut source_col_row = None;
120120
let mut drop_col = None;
121121
ui.columns(self.columns.len(), |uis| {
122-
uis[0].context_menu(|ui, menu_state| {
123-
if ui.button("New Item...").clicked() {
124-
self.columns[0].push("New Item".to_string());
125-
menu_state.close();
126-
}
127-
});
128122
for (col_idx, column) in self.columns.clone().into_iter().enumerate() {
129123
let ui = &mut uis[col_idx];
130124
let can_accept_what_is_being_dragged = true; // We accept anything being dragged (for now) ¯\_(ツ)_/¯
@@ -133,7 +127,13 @@ impl super::View for DragAndDropDemo {
133127
for (row_idx, item) in column.iter().enumerate() {
134128
let item_id = Id::new("item").with(col_idx).with(row_idx);
135129
drag_source(ui, item_id, |ui| {
136-
ui.label(item);
130+
ui.add(Label::new(item).sense(Sense::click()))
131+
.context_menu(|ui, menu_state| {
132+
if ui.button("Remove...").clicked() {
133+
self.columns[col_idx].remove(row_idx);
134+
menu_state.close();
135+
}
136+
});
137137
});
138138

139139
if ui.memory().is_being_dragged(item_id) {
@@ -143,6 +143,15 @@ impl super::View for DragAndDropDemo {
143143
})
144144
.response;
145145

146+
if col_idx == 0 {
147+
response.context_menu(|ui, menu_state| {
148+
if ui.button("New Item...").clicked() {
149+
self.columns[0].push("New Item".to_string());
150+
menu_state.close();
151+
}
152+
});
153+
}
154+
146155
let is_being_dragged = ui.memory().is_anything_being_dragged();
147156
if is_being_dragged && can_accept_what_is_being_dragged && response.hovered() {
148157
drop_col = Some(col_idx);

egui_demo_lib/src/apps/demo/widget_gallery.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,8 @@ impl WidgetGallery {
223223
ui.end_row();
224224

225225
ui.add(doc_link_label("Plot", "plot"));
226-
ui.scope(|ui| {
227-
ui.context_menu(|ui, menu_state| {
226+
ui.add(example_plot(plot))
227+
.context_menu(|ui, menu_state| {
228228
if ui.button("Sin").clicked() {
229229
*plot = Plot::Sin;
230230
menu_state.close();
@@ -236,8 +236,6 @@ impl WidgetGallery {
236236
menu_state.close();
237237
}
238238
});
239-
ui.add(example_plot(plot));
240-
});
241239

242240
ui.end_row();
243241

egui_demo_lib/src/apps/demo/window_options.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,13 @@ impl super::View for WindowOptions {
9090
ui.horizontal(|ui| {
9191
ui.label("title:");
9292
ui.text_edit_singleline(title);
93-
ui.context_menu(|ui, menu_state| {
94-
if ui.button("Clear..").clicked() {
95-
*title = String::new();
96-
menu_state.close();
97-
}
98-
});
93+
})
94+
.response
95+
.context_menu(|ui, menu_state| {
96+
if ui.button("Clear..").clicked() {
97+
*title = String::new();
98+
menu_state.close();
99+
}
99100
});
100101
ui.checkbox(title_bar, "title_bar");
101102
ui.checkbox(closable, "closable");

egui_demo_lib/src/backend_panel.rs

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -103,40 +103,37 @@ impl BackendPanel {
103103
self.egui_windows.windows(ctx);
104104
}
105105

106-
fn context_menu(&mut self, ui: &mut egui::Ui) {
106+
pub fn context_menu(ui: &mut egui::Ui, menu_state: &mut egui::context_menu::MenuState) {
107107
use egui::context_menu::SubMenu;
108-
ui.context_menu(|ui, menu_state| {
109-
if ui.button("Open...").clicked() {
110-
menu_state.close();
111-
}
112-
SubMenu::new("SubMenu")
113-
.show(ui, menu_state, |ui, menu_state| {
114-
if ui.button("Open...").clicked() {
115-
menu_state.close();
116-
}
117-
SubMenu::new("SubMenu")
118-
.show(ui, menu_state, |ui, menu_state| {
119-
if ui.button("Open...").clicked() {
120-
menu_state.close();
121-
}
122-
let _ = ui.button("Item");
123-
});
124-
let _ = ui.button("Item");
125-
});
126-
SubMenu::new("SubMenu")
127-
.show(ui, menu_state, |ui, _menu_state| {
128-
let _ = ui.button("Item1");
129-
let _ = ui.button("Item2");
130-
let _ = ui.button("Item3");
131-
let _ = ui.button("Item4");
132-
});
133-
let _ = ui.button("Item");
134-
});
108+
if ui.button("Open...").clicked() {
109+
menu_state.close();
110+
}
111+
SubMenu::new("SubMenu")
112+
.show(ui, menu_state, |ui, menu_state| {
113+
if ui.button("Open...").clicked() {
114+
menu_state.close();
115+
}
116+
SubMenu::new("SubMenu")
117+
.show(ui, menu_state, |ui, menu_state| {
118+
if ui.button("Open...").clicked() {
119+
menu_state.close();
120+
}
121+
let _ = ui.button("Item");
122+
});
123+
let _ = ui.button("Item");
124+
});
125+
SubMenu::new("SubMenu")
126+
.show(ui, menu_state, |ui, _menu_state| {
127+
let _ = ui.button("Item1");
128+
let _ = ui.button("Item2");
129+
let _ = ui.button("Item3");
130+
let _ = ui.button("Item4");
131+
});
132+
let _ = ui.button("Item");
135133
}
136134

137135
pub fn ui(&mut self, ui: &mut egui::Ui, frame: &mut epi::Frame<'_>) {
138136
egui::trace!(ui);
139-
self.context_menu(ui);
140137
ui.vertical_centered(|ui| {
141138
ui.heading("💻 Backend");
142139
});

egui_demo_lib/src/wrap_app.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use super::backend_panel::BackendPanel;
12
/// All the different demo apps.
23
#[derive(Default)]
34
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
@@ -32,7 +33,7 @@ impl Apps {
3233
pub struct WrapApp {
3334
selected_anchor: String,
3435
apps: Apps,
35-
backend_panel: super::backend_panel::BackendPanel,
36+
backend_panel: BackendPanel,
3637
}
3738

3839
impl epi::App for WrapApp {
@@ -92,7 +93,9 @@ impl epi::App for WrapApp {
9293
if self.backend_panel.open || ctx.memory().everything_is_visible() {
9394
egui::SidePanel::left("backend_panel").show(ctx, |ui| {
9495
self.backend_panel.ui(ui, frame);
95-
});
96+
})
97+
.response
98+
.context_menu(|ui, menu_state| BackendPanel::context_menu(ui, menu_state));
9699
}
97100

98101
for (anchor, app) in self.apps.iter_mut() {
@@ -110,11 +113,6 @@ impl WrapApp {
110113
// A menu-bar is a horizontal layout with some special styles applied.
111114
// egui::menu::bar(ui, |ui| {
112115
ui.horizontal_wrapped(|ui| {
113-
ui.context_menu(|ui, _menu_state| {
114-
if ui.button("Print something").clicked() {
115-
println!("something");
116-
}
117-
});
118116
dark_light_mode_switch(ui);
119117

120118
ui.checkbox(&mut self.backend_panel.open, "💻 Backend");
@@ -147,6 +145,12 @@ impl WrapApp {
147145

148146
egui::warn_if_debug_build(ui);
149147
});
148+
})
149+
.response
150+
.context_menu(|ui, _menu_state| {
151+
if ui.button("Print something").clicked() {
152+
println!("something");
153+
}
150154
});
151155
}
152156
}

0 commit comments

Comments
 (0)