mirror of
https://github.com/emilk/egui.git
synced 2026-09-02 23:00:04 -04:00
Avoid deadlocks by using lambdas for context lock (#2625)
ctx.input().key_pressed(Key::A) -> ctx.input(|i| i.key_pressed(Key::A))
This commit is contained in:
@@ -79,7 +79,7 @@ impl super::View for CodeEditor {
|
||||
let mut layout_job =
|
||||
crate::syntax_highlighting::highlight(ui.ctx(), &theme, string, language);
|
||||
layout_job.wrap.max_width = wrap_width;
|
||||
ui.fonts().layout_job(layout_job)
|
||||
ui.fonts(|f| f.layout_job(layout_job))
|
||||
};
|
||||
|
||||
egui::ScrollArea::vertical().show(ui, |ui| {
|
||||
|
||||
@@ -103,7 +103,7 @@ impl CodeExample {
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
let font_id = egui::TextStyle::Monospace.resolve(ui.style());
|
||||
let indentation = 8.0 * ui.fonts().glyph_width(&font_id, ' ');
|
||||
let indentation = 8.0 * ui.fonts(|f| f.glyph_width(&font_id, ' '));
|
||||
let item_spacing = ui.spacing_mut().item_spacing;
|
||||
ui.add_space(indentation - item_spacing.x);
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ impl super::View for DancingStrings {
|
||||
|
||||
Frame::canvas(ui.style()).show(ui, |ui| {
|
||||
ui.ctx().request_repaint();
|
||||
let time = ui.input().time;
|
||||
let time = ui.input(|i| i.time);
|
||||
|
||||
let desired_size = ui.available_width() * vec2(1.0, 0.35);
|
||||
let (_id, rect) = ui.allocate_space(desired_size);
|
||||
|
||||
@@ -177,7 +177,7 @@ impl DemoWindows {
|
||||
|
||||
fn mobile_ui(&mut self, ctx: &Context) {
|
||||
if self.about_is_open {
|
||||
let screen_size = ctx.input().screen_rect.size();
|
||||
let screen_size = ctx.input(|i| i.screen_rect.size());
|
||||
let default_width = (screen_size.x - 20.0).min(400.0);
|
||||
|
||||
let mut close = false;
|
||||
@@ -216,7 +216,7 @@ impl DemoWindows {
|
||||
ui.menu_button(egui::RichText::new("⏷ demos").size(font_size), |ui| {
|
||||
ui.set_style(ui.ctx().style()); // ignore the "menu" style set by `menu_button`.
|
||||
self.demo_list_ui(ui);
|
||||
if ui.ui_contains_pointer() && ui.input().pointer.any_click() {
|
||||
if ui.ui_contains_pointer() && ui.input(|i| i.pointer.any_click()) {
|
||||
ui.close_menu();
|
||||
}
|
||||
});
|
||||
@@ -291,7 +291,7 @@ impl DemoWindows {
|
||||
ui.separator();
|
||||
|
||||
if ui.button("Organize windows").clicked() {
|
||||
ui.ctx().memory().reset_areas();
|
||||
ui.ctx().memory_mut(|mem| mem.reset_areas());
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -309,12 +309,12 @@ fn file_menu_button(ui: &mut Ui) {
|
||||
// NOTE: we must check the shortcuts OUTSIDE of the actual "File" menu,
|
||||
// or else they would only be checked if the "File" menu was actually open!
|
||||
|
||||
if ui.input_mut().consume_shortcut(&organize_shortcut) {
|
||||
ui.ctx().memory().reset_areas();
|
||||
if ui.input_mut(|i| i.consume_shortcut(&organize_shortcut)) {
|
||||
ui.ctx().memory_mut(|mem| mem.reset_areas());
|
||||
}
|
||||
|
||||
if ui.input_mut().consume_shortcut(&reset_shortcut) {
|
||||
*ui.ctx().memory() = Default::default();
|
||||
if ui.input_mut(|i| i.consume_shortcut(&reset_shortcut)) {
|
||||
ui.ctx().memory_mut(|mem| *mem = Default::default());
|
||||
}
|
||||
|
||||
ui.menu_button("File", |ui| {
|
||||
@@ -335,7 +335,7 @@ fn file_menu_button(ui: &mut Ui) {
|
||||
)
|
||||
.clicked()
|
||||
{
|
||||
ui.ctx().memory().reset_areas();
|
||||
ui.ctx().memory_mut(|mem| mem.reset_areas());
|
||||
ui.close_menu();
|
||||
}
|
||||
|
||||
@@ -347,7 +347,7 @@ fn file_menu_button(ui: &mut Ui) {
|
||||
.on_hover_text("Forget scroll, positions, sizes etc")
|
||||
.clicked()
|
||||
{
|
||||
*ui.ctx().memory() = Default::default();
|
||||
ui.ctx().memory_mut(|mem| *mem = Default::default());
|
||||
ui.close_menu();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use egui::*;
|
||||
|
||||
pub fn drag_source(ui: &mut Ui, id: Id, body: impl FnOnce(&mut Ui)) {
|
||||
let is_being_dragged = ui.memory().is_being_dragged(id);
|
||||
let is_being_dragged = ui.memory(|mem| mem.is_being_dragged(id));
|
||||
|
||||
if !is_being_dragged {
|
||||
let response = ui.scope(body).response;
|
||||
@@ -9,10 +9,10 @@ pub fn drag_source(ui: &mut Ui, id: Id, body: impl FnOnce(&mut Ui)) {
|
||||
// Check for drags:
|
||||
let response = ui.interact(response.rect, id, Sense::drag());
|
||||
if response.hovered() {
|
||||
ui.output().cursor_icon = CursorIcon::Grab;
|
||||
ui.ctx().set_cursor_icon(CursorIcon::Grab);
|
||||
}
|
||||
} else {
|
||||
ui.output().cursor_icon = CursorIcon::Grabbing;
|
||||
ui.ctx().set_cursor_icon(CursorIcon::Grabbing);
|
||||
|
||||
// Paint the body to a new layer:
|
||||
let layer_id = LayerId::new(Order::Tooltip, id);
|
||||
@@ -37,7 +37,7 @@ pub fn drop_target<R>(
|
||||
can_accept_what_is_being_dragged: bool,
|
||||
body: impl FnOnce(&mut Ui) -> R,
|
||||
) -> InnerResponse<R> {
|
||||
let is_being_dragged = ui.memory().is_anything_being_dragged();
|
||||
let is_being_dragged = ui.memory(|mem| mem.is_anything_being_dragged());
|
||||
|
||||
let margin = Vec2::splat(4.0);
|
||||
|
||||
@@ -139,7 +139,7 @@ impl super::View for DragAndDropDemo {
|
||||
});
|
||||
});
|
||||
|
||||
if ui.memory().is_being_dragged(item_id) {
|
||||
if ui.memory(|mem| mem.is_being_dragged(item_id)) {
|
||||
source_col_row = Some((col_idx, row_idx));
|
||||
}
|
||||
}
|
||||
@@ -153,7 +153,7 @@ impl super::View for DragAndDropDemo {
|
||||
}
|
||||
});
|
||||
|
||||
let is_being_dragged = ui.memory().is_anything_being_dragged();
|
||||
let is_being_dragged = ui.memory(|mem| mem.is_anything_being_dragged());
|
||||
if is_being_dragged && can_accept_what_is_being_dragged && response.hovered() {
|
||||
drop_col = Some(col_idx);
|
||||
}
|
||||
@@ -162,7 +162,7 @@ impl super::View for DragAndDropDemo {
|
||||
|
||||
if let Some((source_col, source_row)) = source_col_row {
|
||||
if let Some(drop_col) = drop_col {
|
||||
if ui.input().pointer.any_released() {
|
||||
if ui.input(|i| i.pointer.any_released()) {
|
||||
// do the drop:
|
||||
let item = self.columns[source_col].remove(source_row);
|
||||
self.columns[drop_col].push(item);
|
||||
|
||||
@@ -93,7 +93,7 @@ impl super::View for FontBook {
|
||||
};
|
||||
|
||||
if ui.add(button).on_hover_ui(tooltip_ui).clicked() {
|
||||
ui.output().copied_text = chr.to_string();
|
||||
ui.output_mut(|o| o.copied_text = chr.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -103,15 +103,16 @@ impl super::View for FontBook {
|
||||
}
|
||||
|
||||
fn available_characters(ui: &egui::Ui, family: egui::FontFamily) -> BTreeMap<char, String> {
|
||||
ui.fonts()
|
||||
.lock()
|
||||
.fonts
|
||||
.font(&egui::FontId::new(10.0, family)) // size is arbitrary for getting the characters
|
||||
.characters()
|
||||
.iter()
|
||||
.filter(|chr| !chr.is_whitespace() && !chr.is_ascii_control())
|
||||
.map(|&chr| (chr, char_name(chr)))
|
||||
.collect()
|
||||
ui.fonts(|f| {
|
||||
f.lock()
|
||||
.fonts
|
||||
.font(&egui::FontId::new(10.0, family)) // size is arbitrary for getting the characters
|
||||
.characters()
|
||||
.iter()
|
||||
.filter(|chr| !chr.is_whitespace() && !chr.is_ascii_control())
|
||||
.map(|&chr| (chr, char_name(chr)))
|
||||
.collect()
|
||||
})
|
||||
}
|
||||
|
||||
fn char_name(chr: char) -> String {
|
||||
|
||||
@@ -202,7 +202,7 @@ impl Widgets {
|
||||
|
||||
ui.horizontal_wrapped(|ui| {
|
||||
// Trick so we don't have to add spaces in the text below:
|
||||
let width = ui.fonts().glyph_width(&TextStyle::Body.resolve(ui.style()), ' ');
|
||||
let width = ui.fonts(|f|f.glyph_width(&TextStyle::Body.resolve(ui.style()), ' '));
|
||||
ui.spacing_mut().item_spacing.x = width;
|
||||
|
||||
ui.label(RichText::new("Text can have").color(Color32::from_rgb(110, 255, 110)));
|
||||
|
||||
@@ -49,7 +49,7 @@ impl super::View for MultiTouch {
|
||||
ui.separator();
|
||||
ui.label("Try touch gestures Pinch/Stretch, Rotation, and Pressure with 2+ fingers.");
|
||||
|
||||
let num_touches = ui.input().multi_touch().map_or(0, |mt| mt.num_touches);
|
||||
let num_touches = ui.input(|i| i.multi_touch().map_or(0, |mt| mt.num_touches));
|
||||
ui.label(format!("Current touches: {}", num_touches));
|
||||
|
||||
let color = if ui.visuals().dark_mode {
|
||||
@@ -93,7 +93,7 @@ impl super::View for MultiTouch {
|
||||
// touch pressure will make the arrow thicker (not all touch devices support this):
|
||||
stroke_width += 10. * multi_touch.force;
|
||||
|
||||
self.last_touch_time = ui.input().time;
|
||||
self.last_touch_time = ui.input(|i| i.time);
|
||||
} else {
|
||||
self.slowly_reset(ui);
|
||||
}
|
||||
@@ -118,7 +118,7 @@ impl MultiTouch {
|
||||
// This has nothing to do with the touch gesture. It just smoothly brings the
|
||||
// painted arrow back into its original position, for a nice visual effect:
|
||||
|
||||
let time_since_last_touch = (ui.input().time - self.last_touch_time) as f32;
|
||||
let time_since_last_touch = (ui.input(|i| i.time) - self.last_touch_time) as f32;
|
||||
|
||||
let delay = 0.5;
|
||||
if time_since_last_touch < delay {
|
||||
@@ -133,7 +133,7 @@ impl MultiTouch {
|
||||
self.rotation = 0.0;
|
||||
self.translation = Vec2::ZERO;
|
||||
} else {
|
||||
let dt = ui.input().unstable_dt;
|
||||
let dt = ui.input(|i| i.unstable_dt);
|
||||
let half_life_factor = (-(2_f32.ln()) / half_life * dt).exp();
|
||||
self.zoom = 1. + ((self.zoom - 1.) * half_life_factor);
|
||||
self.rotation *= half_life_factor;
|
||||
|
||||
@@ -53,11 +53,10 @@ impl PaintBezier {
|
||||
});
|
||||
|
||||
ui.collapsing("Global tessellation options", |ui| {
|
||||
let mut tessellation_options = *(ui.ctx().tessellation_options());
|
||||
let tessellation_options = &mut tessellation_options;
|
||||
let mut tessellation_options = ui.ctx().tessellation_options(|to| *to);
|
||||
tessellation_options.ui(ui);
|
||||
let mut new_tessellation_options = ui.ctx().tessellation_options();
|
||||
*new_tessellation_options = *tessellation_options;
|
||||
ui.ctx()
|
||||
.tessellation_options_mut(|to| *to = tessellation_options);
|
||||
});
|
||||
|
||||
ui.radio_value(&mut self.degree, 3, "Quadratic Bézier");
|
||||
|
||||
@@ -20,7 +20,7 @@ pub fn password_ui(ui: &mut egui::Ui, password: &mut String) -> egui::Response {
|
||||
|
||||
// Get state for this widget.
|
||||
// You should get state by value, not by reference to avoid borrowing of [`Memory`].
|
||||
let mut show_plaintext = ui.data().get_temp::<bool>(state_id).unwrap_or(false);
|
||||
let mut show_plaintext = ui.data_mut(|d| d.get_temp::<bool>(state_id).unwrap_or(false));
|
||||
|
||||
// Process ui, change a local copy of the state
|
||||
// We want TextEdit to fill entire space, and have button after that, so in that case we can
|
||||
@@ -43,7 +43,7 @@ pub fn password_ui(ui: &mut egui::Ui, password: &mut String) -> egui::Response {
|
||||
});
|
||||
|
||||
// Store the (possibly changed) state:
|
||||
ui.data().insert_temp(state_id, show_plaintext);
|
||||
ui.data_mut(|d| d.insert_temp(state_id, show_plaintext));
|
||||
|
||||
// All done! Return the interaction response so the user can check what happened
|
||||
// (hovered, clicked, …) and maybe show a tooltip:
|
||||
|
||||
@@ -270,7 +270,7 @@ impl LineDemo {
|
||||
self.options_ui(ui);
|
||||
if self.animate {
|
||||
ui.ctx().request_repaint();
|
||||
self.time += ui.input().unstable_dt.at_most(1.0 / 30.0) as f64;
|
||||
self.time += ui.input(|i| i.unstable_dt).at_most(1.0 / 30.0) as f64;
|
||||
};
|
||||
let mut plot = Plot::new("lines_demo").legend(Legend::default());
|
||||
if self.square {
|
||||
|
||||
@@ -112,7 +112,7 @@ fn huge_content_painter(ui: &mut egui::Ui) {
|
||||
ui.add_space(4.0);
|
||||
|
||||
let font_id = TextStyle::Body.resolve(ui.style());
|
||||
let row_height = ui.fonts().row_height(&font_id) + ui.spacing().item_spacing.y;
|
||||
let row_height = ui.fonts(|f| f.row_height(&font_id)) + ui.spacing().item_spacing.y;
|
||||
let num_rows = 10_000;
|
||||
|
||||
ScrollArea::vertical()
|
||||
|
||||
@@ -65,10 +65,7 @@ impl super::View for TextEdit {
|
||||
egui::Label::new("Press ctrl+Y to toggle the case of selected text (cmd+Y on Mac)"),
|
||||
);
|
||||
|
||||
if ui
|
||||
.input_mut()
|
||||
.consume_key(egui::Modifiers::COMMAND, egui::Key::Y)
|
||||
{
|
||||
if ui.input_mut(|i| i.consume_key(egui::Modifiers::COMMAND, egui::Key::Y)) {
|
||||
if let Some(text_cursor_range) = output.cursor_range {
|
||||
use egui::TextBuffer as _;
|
||||
let selected_chars = text_cursor_range.as_sorted_char_range();
|
||||
@@ -93,7 +90,7 @@ impl super::View for TextEdit {
|
||||
let ccursor = egui::text::CCursor::new(0);
|
||||
state.set_ccursor_range(Some(egui::text::CCursorRange::one(ccursor)));
|
||||
state.store(ui.ctx(), text_edit_id);
|
||||
ui.ctx().memory().request_focus(text_edit_id); // give focus back to the [`TextEdit`].
|
||||
ui.ctx().memory_mut(|mem| mem.request_focus(text_edit_id)); // give focus back to the [`TextEdit`].
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +100,7 @@ impl super::View for TextEdit {
|
||||
let ccursor = egui::text::CCursor::new(text.chars().count());
|
||||
state.set_ccursor_range(Some(egui::text::CCursorRange::one(ccursor)));
|
||||
state.store(ui.ctx(), text_edit_id);
|
||||
ui.ctx().memory().request_focus(text_edit_id); // give focus back to the [`TextEdit`].
|
||||
ui.ctx().memory_mut(|mem| mem.request_focus(text_edit_id)); // give focus back to the [`TextEdit`].
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -50,7 +50,7 @@ impl super::Demo for WindowOptions {
|
||||
anchor_offset,
|
||||
} = self.clone();
|
||||
|
||||
let enabled = ctx.input().time - disabled_time > 2.0;
|
||||
let enabled = ctx.input(|i| i.time) - disabled_time > 2.0;
|
||||
if !enabled {
|
||||
ctx.request_repaint();
|
||||
}
|
||||
@@ -132,7 +132,7 @@ impl super::View for WindowOptions {
|
||||
|
||||
ui.horizontal(|ui| {
|
||||
if ui.button("Disable for 2 seconds").clicked() {
|
||||
self.disabled_time = ui.input().time;
|
||||
self.disabled_time = ui.input(|i| i.time);
|
||||
}
|
||||
egui::reset_button(ui, self);
|
||||
ui.add(crate::egui_github_link_file!());
|
||||
|
||||
Reference in New Issue
Block a user