From b65e6327abb32a95f6aafd238d682d9dfbeb989c Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Sat, 26 Dec 2020 01:38:26 +0100 Subject: [PATCH] ui.allocate_space now returns an (Id, Rect) tuple --- CHANGELOG.md | 1 + egui/src/containers/collapsing_header.rs | 2 +- egui/src/containers/combo_box.rs | 2 +- egui/src/containers/window.rs | 11 +++-- egui/src/demos/app.rs | 9 ++-- egui/src/demos/color_test.rs | 5 +- egui/src/demos/dancing_strings.rs | 2 +- egui/src/demos/demo_window.rs | 34 ++++++-------- egui/src/demos/painting.rs | 3 +- egui/src/demos/toggle_switch.rs | 14 ++---- egui/src/introspection.rs | 49 ++++++++++---------- egui/src/style.rs | 2 +- egui/src/ui.rs | 42 +++++++++++------ egui/src/widgets/button.rs | 3 +- egui/src/widgets/color_picker.rs | 16 +++---- egui/src/widgets/drag_value.rs | 2 +- egui/src/widgets/image.rs | 4 +- egui/src/widgets/mod.rs | 58 +++++++++++------------- egui/src/widgets/slider.rs | 5 +- egui/src/widgets/text_edit.rs | 5 +- 20 files changed, 132 insertions(+), 137 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f21798d..8668897e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Changed 🔧 +* `ui.allocate_space` now returns an `(Id, Rect)` tuple. * `Arc` has been replaced with `CtxRef` everywhere. * Slight tweak of the default `Style` and font sizes. * `SidePanel::left` and `TopPanel::top` now takes `impl Hash` as first argument. diff --git a/egui/src/containers/collapsing_header.rs b/egui/src/containers/collapsing_header.rs index 8c6f6694..0479acab 100644 --- a/egui/src/containers/collapsing_header.rs +++ b/egui/src/containers/collapsing_header.rs @@ -185,7 +185,7 @@ impl CollapsingHeader { galley.size.y + 2.0 * ui.style().spacing.button_padding.y, ); desired_size = desired_size.at_least(ui.style().spacing.interact_size); - let rect = ui.allocate_space(desired_size); + let (_, rect) = ui.allocate_space(desired_size); let header_response = ui.interact(rect, id, Sense::click()); let text_pos = pos2( diff --git a/egui/src/containers/combo_box.rs b/egui/src/containers/combo_box.rs index 248f723f..aa5b9ee7 100644 --- a/egui/src/containers/combo_box.rs +++ b/egui/src/containers/combo_box.rs @@ -40,7 +40,7 @@ pub fn combo_box( let advance = full_minimum_width - icon_width - ui.min_rect().width(); ui.advance_cursor(advance.at_least(0.0)); - let icon_rect = ui.allocate_space(Vec2::splat(icon_width)); + let (_, icon_rect) = ui.allocate_space(Vec2::splat(icon_width)); let button_rect = ui.min_rect().expand2(ui.style().spacing.button_padding); let mut response = ui.interact(button_rect, button_id, Sense::click()); response.active |= button_active; diff --git a/egui/src/containers/window.rs b/egui/src/containers/window.rs index 9ef5bd0a..8e001ef7 100644 --- a/egui/src/containers/window.rs +++ b/egui/src/containers/window.rs @@ -614,6 +614,7 @@ fn paint_frame_interaction( // ---------------------------------------------------------------------------- struct TitleBar { + id: Id, title_label: Label, title_galley: Galley, title_rect: Rect, @@ -637,7 +638,7 @@ fn show_title_bar( if collapsible { ui.advance_cursor(ui.style().spacing.item_spacing.x); - let rect = ui.allocate_space(Vec2::splat(button_size)); + let (_id, rect) = ui.allocate_space(Vec2::splat(button_size)); let collapse_button_response = ui.interact(rect, collapsing_id, Sense::click()); if collapse_button_response.clicked { collapsing.toggle(ui); @@ -647,7 +648,7 @@ fn show_title_bar( } let title_galley = title_label.layout(ui); - let title_rect = ui.allocate_space(title_galley.size); + let (id, title_rect) = ui.allocate_space(title_galley.size); if show_close_button { // Reserve space for close button which will be added later (once we know our full width): @@ -664,6 +665,7 @@ fn show_title_bar( } TitleBar { + id, title_label, title_galley, title_rect, @@ -715,9 +717,8 @@ impl TitleBar { ); } - let title_bar_id = ui.make_position_id().with("title_bar"); if ui - .interact(self.rect, title_bar_id, Sense::click()) + .interact(self.rect, self.id, Sense::click()) .double_clicked && collapsible { @@ -740,7 +741,7 @@ impl TitleBar { } fn close_button(ui: &mut Ui, rect: Rect) -> Response { - let close_id = ui.make_position_id().with("window_close_button"); + let close_id = ui.auto_id_with("window_close_button"); let response = ui.interact(rect, close_id, Sense::click()); ui.expand_to_include_rect(response.rect); diff --git a/egui/src/demos/app.rs b/egui/src/demos/app.rs index 4d83feca..68ebe59a 100644 --- a/egui/src/demos/app.rs +++ b/egui/src/demos/app.rs @@ -1,4 +1,4 @@ -use crate::{app, demos, util::History, CtxRef, Ui}; +use crate::{app, demos, util::History, CtxRef, Response, Ui}; // ---------------------------------------------------------------------------- @@ -99,7 +99,7 @@ impl FrameHistory { }); } - fn graph(&mut self, ui: &mut Ui) { + fn graph(&mut self, ui: &mut Ui) -> Response { use crate::*; let graph_top_cpu_usage = 0.010; @@ -109,7 +109,8 @@ impl FrameHistory { // TODO: we should not use `slider_width` as default graph width. let height = ui.style().spacing.slider_width; - let rect = ui.allocate_space(vec2(ui.available_size_before_wrap_finite().x, height)); + let (id, rect) = ui.allocate_space(vec2(ui.available_size_before_wrap_finite().x, height)); + let response = ui.interact(rect, id, Sense::nothing()); let style = ui.style().noninteractive(); let mut cmds = vec![PaintCmd::Rect { @@ -162,6 +163,8 @@ impl FrameHistory { } ui.painter().extend(cmds); + + response } } diff --git a/egui/src/demos/color_test.rs b/egui/src/demos/color_test.rs index cdb166db..fbff783c 100644 --- a/egui/src/demos/color_test.rs +++ b/egui/src/demos/color_test.rs @@ -267,7 +267,8 @@ impl ColorTest { fn vertex_gradient(ui: &mut Ui, bg_fill: Srgba, gradient: &Gradient) -> Response { use crate::paint::*; - let rect = ui.allocate_space(GRADIENT_SIZE); + let (id, rect) = ui.allocate_space(GRADIENT_SIZE); + let response = ui.interact(rect, id, Sense::nothing()); if bg_fill != Default::default() { let mut triangles = Triangles::default(); triangles.add_colored_rect(rect, bg_fill); @@ -290,7 +291,7 @@ fn vertex_gradient(ui: &mut Ui, bg_fill: Srgba, gradient: &Gradient) -> Response } ui.painter().add(PaintCmd::triangles(triangles)); } - ui.interact_hover(rect) + response } #[derive(Clone, Hash, PartialEq, Eq)] diff --git a/egui/src/demos/dancing_strings.rs b/egui/src/demos/dancing_strings.rs index 4e81c09f..21a9fdd2 100644 --- a/egui/src/demos/dancing_strings.rs +++ b/egui/src/demos/dancing_strings.rs @@ -31,7 +31,7 @@ impl View for DancingStrings { let time = ui.input().time; let desired_size = ui.available_width() * vec2(1.0, 0.35); - let rect = ui.allocate_space(desired_size); + let (_id, rect) = ui.allocate_space(desired_size); let mut cmds = vec![]; diff --git a/egui/src/demos/demo_window.rs b/egui/src/demos/demo_window.rs index ae129e63..4e05c166 100644 --- a/egui/src/demos/demo_window.rs +++ b/egui/src/demos/demo_window.rs @@ -87,7 +87,7 @@ impl DemoWindow { .show(ui, |ui| { ui.horizontal(|ui| { ui.label("You can pretty easily paint your own small icons:"); - let rect = ui.allocate_space(Vec2::splat(16.0)); + let (_id, rect) = ui.allocate_space(Vec2::splat(16.0)); let painter = ui.painter(); let c = rect.center(); let r = rect.width() / 2.0 - 1.0; @@ -188,7 +188,7 @@ struct BoxPainting { impl Default for BoxPainting { fn default() -> Self { Self { - size: vec2(100.0, 50.0), + size: vec2(64.0, 32.0), corner_radius: 5.0, stroke_width: 2.0, num_boxes: 1, @@ -202,25 +202,19 @@ impl BoxPainting { ui.add(Slider::f32(&mut self.size.y, 0.0..=500.0).text("height")); ui.add(Slider::f32(&mut self.corner_radius, 0.0..=50.0).text("corner_radius")); ui.add(Slider::f32(&mut self.stroke_width, 0.0..=10.0).text("stroke_width")); - ui.add(Slider::usize(&mut self.num_boxes, 0..=5).text("num_boxes")); + ui.add(Slider::usize(&mut self.num_boxes, 0..=8).text("num_boxes")); - let pos = ui - .allocate_space(vec2(self.size.x * (self.num_boxes as f32), self.size.y)) - .min; - - let mut cmds = vec![]; - for i in 0..self.num_boxes { - cmds.push(paint::PaintCmd::Rect { - corner_radius: self.corner_radius, - fill: Srgba::gray(64), - rect: Rect::from_min_size( - pos2(10.0 + pos.x + (i as f32) * (self.size.x * 1.1), pos.y), - self.size, - ), - stroke: Stroke::new(self.stroke_width, WHITE), - }); - } - ui.painter().extend(cmds); + ui.horizontal_wrapped(|ui| { + for _ in 0..self.num_boxes { + let (_id, rect) = ui.allocate_space(self.size); + ui.painter().rect( + rect, + self.corner_radius, + Srgba::gray(64), + Stroke::new(self.stroke_width, WHITE), + ); + } + }); } } diff --git a/egui/src/demos/painting.rs b/egui/src/demos/painting.rs index 8152f21c..3ee3c7dd 100644 --- a/egui/src/demos/painting.rs +++ b/egui/src/demos/painting.rs @@ -28,9 +28,8 @@ impl Painting { } pub fn ui_content(&mut self, ui: &mut Ui) { - let painter = ui.allocate_painter(ui.available_size_before_wrap_finite()); + let (id, painter) = ui.allocate_painter(ui.available_size_before_wrap_finite()); let rect = painter.clip_rect(); - let id = ui.make_position_id(); let response = ui.interact(rect, id, Sense::drag()); if self.lines.is_empty() { diff --git a/egui/src/demos/toggle_switch.rs b/egui/src/demos/toggle_switch.rs index d32ee033..25d510f8 100644 --- a/egui/src/demos/toggle_switch.rs +++ b/egui/src/demos/toggle_switch.rs @@ -24,14 +24,11 @@ pub fn toggle(ui: &mut Ui, on: &mut bool) -> Response { // 2. Allocating space: // This is where we get a region (`Rect`) of the screen assigned. - let rect = ui.allocate_space(desired_size); + // We also get an automatically generated `Id` which can be used for interactions and animations. + // (To get an `Id` that is persistent over long time, use `ui.make_persistent_id`). + let (id, rect) = ui.allocate_space(desired_size); - // 3. Interact: Time to check for clicks! - // To do that we need an `Id` for the button. - // Id's are best created from unique identifiers (like fixed labels) - // but since we have no label for the switch we here just generate an `Id` automatically - // (based on a rolling counter in the `Ui`). - let id = ui.make_position_id(); + // 3. Interact: Time to check for clicks!. let response = ui.interact(rect, id, Sense::click()); if response.clicked { *on = !*on; @@ -67,9 +64,8 @@ pub fn toggle(ui: &mut Ui, on: &mut bool) -> Response { #[allow(dead_code)] fn toggle_compact(ui: &mut Ui, on: &mut bool) -> Response { let desired_size = ui.style().spacing.interact_size; - let rect = ui.allocate_space(desired_size); + let (id, rect) = ui.allocate_space(desired_size); - let id = ui.make_position_id(); let response = ui.interact(rect, id, Sense::click()); *on ^= response.clicked; // toggle if clicked diff --git a/egui/src/introspection.rs b/egui/src/introspection.rs index f22b0ff2..f914f576 100644 --- a/egui/src/introspection.rs +++ b/egui/src/introspection.rs @@ -1,6 +1,5 @@ //! uis for egui types. use crate::{ - containers::show_tooltip, math::*, paint::{self, color::WHITE, PaintCmd, Texture, Triangles}, *, @@ -19,38 +18,36 @@ impl Texture { if size.x > ui.available_width() { size *= ui.available_width() / size.x; } - let rect = ui.allocate_space(size); + let (id, rect) = ui.allocate_space(size); + let response = ui.interact(rect, id, Sense::nothing()); let mut triangles = Triangles::default(); triangles.add_rect_with_uv(rect, [pos2(0.0, 0.0), pos2(1.0, 1.0)].into(), WHITE); ui.painter().add(PaintCmd::triangles(triangles)); - let tex_w = self.width as f32; - let tex_h = self.height as f32; + let (tex_w, tex_h) = (self.width as f32, self.height as f32); - if ui.hovered(rect) { - show_tooltip(ui.ctx(), |ui| { - let pos = ui - .input() - .mouse - .pos - .unwrap_or_else(|| ui.min_rect().left_top()); - let zoom_rect = ui.allocate_space(vec2(128.0, 128.0)); - let u = remap_clamp(pos.x, rect.x_range(), 0.0..=tex_w); - let v = remap_clamp(pos.y, rect.y_range(), 0.0..=tex_h); + response.on_hover_ui(|ui| { + let pos = ui + .input() + .mouse + .pos + .unwrap_or_else(|| ui.min_rect().left_top()); + let (_id, zoom_rect) = ui.allocate_space(vec2(128.0, 128.0)); + let u = remap_clamp(pos.x, rect.x_range(), 0.0..=tex_w); + let v = remap_clamp(pos.y, rect.y_range(), 0.0..=tex_h); - let texel_radius = 32.0; - let u = u.at_least(texel_radius).at_most(tex_w - texel_radius); - let v = v.at_least(texel_radius).at_most(tex_h - texel_radius); + let texel_radius = 32.0; + let u = u.at_least(texel_radius).at_most(tex_w - texel_radius); + let v = v.at_least(texel_radius).at_most(tex_h - texel_radius); - let uv_rect = Rect::from_min_max( - pos2((u - texel_radius) / tex_w, (v - texel_radius) / tex_h), - pos2((u + texel_radius) / tex_w, (v + texel_radius) / tex_h), - ); - let mut triangles = Triangles::default(); - triangles.add_rect_with_uv(zoom_rect, uv_rect, WHITE); - ui.painter().add(PaintCmd::triangles(triangles)); - }); - } + let uv_rect = Rect::from_min_max( + pos2((u - texel_radius) / tex_w, (v - texel_radius) / tex_h), + pos2((u + texel_radius) / tex_w, (v + texel_radius) / tex_h), + ); + let mut triangles = Triangles::default(); + triangles.add_rect_with_uv(zoom_rect, uv_rect, WHITE); + ui.painter().add(PaintCmd::triangles(triangles)); + }); } } diff --git a/egui/src/style.rs b/egui/src/style.rs index 957c82ba..3b6e544e 100644 --- a/egui/src/style.rs +++ b/egui/src/style.rs @@ -519,7 +519,7 @@ impl Stroke { ui.label(text); // stroke preview: - let stroke_rect = ui.allocate_space(ui.style().spacing.interact_size); + let (_id, stroke_rect) = ui.allocate_space(ui.style().spacing.interact_size); let left = stroke_rect.left_center(); let right = stroke_rect.right_center(); ui.painter().line_segment([left, right], (*width, *color)); diff --git a/egui/src/ui.rs b/egui/src/ui.rs index 9e8cb486..823aa4bd 100644 --- a/egui/src/ui.rs +++ b/egui/src/ui.rs @@ -365,14 +365,17 @@ impl Ui { self.id.with(&id_source) } - /// Make an Id that is unique to this position. - /// Can be used for widgets that do NOT persist state in Memory - /// but you still need to interact with (e.g. buttons, sliders). - /// Call AFTER allocating new space for your widget. - // TODO: return from `allocate_space` ? + #[deprecated = "This id now returned from ui.allocate_space"] pub fn make_position_id(&self) -> Id { Id::new(self.next_auto_id) } + + pub(crate) fn auto_id_with(&self, id_source: IdSource) -> Id + where + IdSource: Hash + std::fmt::Debug, + { + Id::new(self.next_auto_id).with(id_source) + } } /// # Interaction @@ -430,7 +433,15 @@ impl Ui { /// for justified layouts, like in menus. /// /// You may get LESS space than you asked for if the current layout won't fit what you asked for. - pub fn allocate_space(&mut self, desired_size: Vec2) -> Rect { + /// + /// Returns an automatic `Id` (which you can use for interaction) and the `Rect` of where to put your widget. + /// + /// ``` + /// # let mut ui = egui::Ui::__test(); + /// let (id, rect) = ui.allocate_space(egui::vec2(100.0, 200.0)); + /// let response = ui.interact(rect, id, egui::Sense::click()); + /// ``` + pub fn allocate_space(&mut self, desired_size: Vec2) -> (Id, Rect) { // For debug rendering let original_available = self.available_size_before_wrap(); let too_wide = desired_size.x > original_available.x; @@ -466,7 +477,9 @@ impl Ui { } } - rect + let id = Id::new(self.next_auto_id); // TODO: increment counter here + + (id, rect) } /// Reserve this much space and move the cursor. @@ -533,10 +546,11 @@ impl Ui { } /// Convenience function to get a region to paint on - pub fn allocate_painter(&mut self, desired_size: Vec2) -> Painter { - let rect = self.allocate_space(desired_size); + pub fn allocate_painter(&mut self, desired_size: Vec2) -> (Id, Painter) { + let (id, rect) = self.allocate_space(desired_size); let clip_rect = self.clip_rect().intersect(rect); // Make sure we don't paint out of bounds - Painter::new(self.ctx().clone(), self.layer_id(), clip_rect) + let painter = Painter::new(self.ctx().clone(), self.layer_id(), clip_rect); + (id, painter) } } @@ -772,8 +786,8 @@ impl Ui { let mut child_ui = self.child_ui(child_rect, self.layout); let ret = add_contents(&mut child_ui); let size = child_ui.min_size(); - let rect = self.allocate_space(size); - (ret, self.interact_hover(rect)) + let (id, rect) = self.allocate_space(size); + (ret, self.interact(rect, id, Sense::nothing())) } /// Redirect paint commands to another paint layer. @@ -836,8 +850,8 @@ impl Ui { self.style().visuals.widgets.noninteractive.bg_stroke, ); - let rect = self.allocate_space(indent + size); - (ret, self.interact_hover(rect)) + let (id, rect) = self.allocate_space(indent + size); + (ret, self.interact(rect, id, Sense::nothing())) } #[deprecated] diff --git a/egui/src/widgets/button.rs b/egui/src/widgets/button.rs index d801a73a..fc86db29 100644 --- a/egui/src/widgets/button.rs +++ b/egui/src/widgets/button.rs @@ -62,8 +62,7 @@ impl Widget for ImageButton { let button_padding = ui.style().spacing.button_padding; let desired_size = image.desired_size() + 2.0 * button_padding; - let rect = ui.allocate_space(desired_size); - let id = ui.make_position_id(); + let (id, rect) = ui.allocate_space(desired_size); let response = ui.interact(rect, id, sense); if ui.clip_rect().intersects(rect) { diff --git a/egui/src/widgets/color_picker.rs b/egui/src/widgets/color_picker.rs index 698ce17f..d5350973 100644 --- a/egui/src/widgets/color_picker.rs +++ b/egui/src/widgets/color_picker.rs @@ -43,7 +43,8 @@ pub fn show_color(ui: &mut Ui, color: impl Into, desired_size: Vec2) -> R } fn show_srgba(ui: &mut Ui, srgba: Srgba, desired_size: Vec2) -> Response { - let rect = ui.allocate_space(desired_size); + let (id, rect) = ui.allocate_space(desired_size); + let response = ui.interact(rect, id, Sense::nothing()); background_checkers(ui.painter(), rect); ui.painter().add(PaintCmd::Rect { rect, @@ -51,13 +52,12 @@ fn show_srgba(ui: &mut Ui, srgba: Srgba, desired_size: Vec2) -> Response { fill: srgba, stroke: Stroke::new(3.0, srgba.to_opaque()), }); - ui.interact_hover(rect) + response } fn color_button(ui: &mut Ui, color: Srgba) -> Response { let desired_size = ui.style().spacing.interact_size; - let rect = ui.allocate_space(desired_size); - let id = ui.make_position_id(); + let (id, rect) = ui.allocate_space(desired_size); let response = ui.interact(rect, id, Sense::click()); let visuals = ui.style().interact(&response); background_checkers(ui.painter(), rect); @@ -77,9 +77,8 @@ fn color_slider_1d(ui: &mut Ui, value: &mut f32, color_at: impl Fn(f32) -> Srgba ui.style().spacing.slider_width, ui.style().spacing.interact_size.y * 2.0, ); - let rect = ui.allocate_space(desired_size); + let (id, rect) = ui.allocate_space(desired_size); - let id = ui.make_position_id(); let response = ui.interact(rect, id, Sense::click_and_drag()); if response.active { if let Some(mpos) = ui.input().mouse.pos { @@ -136,9 +135,8 @@ fn color_slider_2d( color_at: impl Fn(f32, f32) -> Srgba, ) -> Response { let desired_size = Vec2::splat(ui.style().spacing.slider_width); - let rect = ui.allocate_space(desired_size); + let (id, rect) = ui.allocate_space(desired_size); - let id = ui.make_position_id(); let response = ui.interact(rect, id, Sense::click_and_drag()); if response.active { if let Some(mpos) = ui.input().mouse.pos { @@ -218,7 +216,7 @@ fn color_picker_hsva_2d(ui: &mut Ui, hsva: &mut Hsva) { } pub fn color_edit_button_hsva(ui: &mut Ui, hsva: &mut Hsva) -> Response { - let pupup_id = ui.make_position_id().with("popup"); + let pupup_id = ui.auto_id_with("popup"); let button_response = color_button(ui, (*hsva).into()).on_hover_text("Click to edit color"); if button_response.clicked { diff --git a/egui/src/widgets/drag_value.rs b/egui/src/widgets/drag_value.rs index b00438c4..ee9acafb 100644 --- a/egui/src/widgets/drag_value.rs +++ b/egui/src/widgets/drag_value.rs @@ -151,7 +151,7 @@ impl<'a> Widget for DragValue<'a> { let auto_decimals = clamp(auto_decimals, min_decimals..=max_decimals); let value_text = format_with_decimals_in_range(value, auto_decimals..=max_decimals); - let kb_edit_id = ui.make_position_id().with("edit"); + let kb_edit_id = ui.auto_id_with("edit"); let is_kb_editing = ui.memory().has_kb_focus(kb_edit_id); if is_kb_editing { diff --git a/egui/src/widgets/image.rs b/egui/src/widgets/image.rs index a8f461ba..511abb96 100644 --- a/egui/src/widgets/image.rs +++ b/egui/src/widgets/image.rs @@ -72,8 +72,8 @@ impl Image { impl Widget for Image { fn ui(self, ui: &mut Ui) -> Response { - let rect = ui.allocate_space(self.desired_size); + let (id, rect) = ui.allocate_space(self.desired_size); self.paint_at(ui, rect); - ui.interact_hover(rect) + ui.interact(rect, id, Sense::nothing()) } } diff --git a/egui/src/widgets/mod.rs b/egui/src/widgets/mod.rs index 6b7d796f..aca6a251 100644 --- a/egui/src/widgets/mod.rs +++ b/egui/src/widgets/mod.rs @@ -160,7 +160,7 @@ impl Widget for Label { let pos = pos2(ui.min_rect().left(), ui.cursor().y); - assert!(!galley.rows.is_empty(), "Gallyes are never empty"); + assert!(!galley.rows.is_empty(), "Galleys are never empty"); let rect = galley.rows[0].rect().translate(vec2(pos.x, pos.y)); ui.advance_cursor_after_rect(rect); let mut total_response = ui.interact_hover(rect); @@ -186,10 +186,11 @@ impl Widget for Label { total_response } else { let galley = self.layout(ui); - let rect = ui.allocate_space(galley.size); + let (id, rect) = ui.allocate_space(galley.size); + let response = ui.interact(rect, id, Sense::nothing()); let rect = ui.layout().align_size_within_rect(galley.size, rect); self.paint_galley(ui, rect.min, galley); - ui.interact_hover(rect) + response } } } @@ -260,9 +261,8 @@ impl Widget for Hyperlink { let text_style = text_style.unwrap_or_else(|| ui.style().body_text_style); let font = &ui.fonts()[text_style]; let galley = font.layout_multiline(text, ui.available_width()); - let rect = ui.allocate_space(galley.size); + let (id, rect) = ui.allocate_space(galley.size); - let id = ui.make_position_id(); let response = ui.interact(rect, id, Sense::click()); if response.hovered { ui.ctx().output().cursor_icon = CursorIcon::PointingHand; @@ -404,9 +404,8 @@ impl Widget for Button { desired_size.y = desired_size.y.at_least(ui.style().spacing.interact_size.y); } - let rect = ui.allocate_space(desired_size); + let (id, rect) = ui.allocate_space(desired_size); - let id = ui.make_position_id(); let response = ui.interact(rect, id, sense); if ui.clip_rect().intersects(rect) { @@ -490,10 +489,9 @@ impl<'a> Widget for Checkbox<'a> { let mut desired_size = total_extra + galley.size; desired_size = desired_size.at_least(spacing.interact_size); desired_size.y = desired_size.y.max(icon_width); - let rect = ui.allocate_space(desired_size); + let (id, rect) = ui.allocate_space(desired_size); let rect = ui.layout().align_size_within_rect(desired_size, rect); - let id = ui.make_position_id(); let response = ui.interact(rect, id, Sense::click()); if response.clicked { *checked = !*checked; @@ -585,10 +583,8 @@ impl Widget for RadioButton { let mut desired_size = total_extra + galley.size; desired_size = desired_size.at_least(ui.style().spacing.interact_size); desired_size.y = desired_size.y.max(icon_width); - let rect = ui.allocate_space(desired_size); + let (id, rect) = ui.allocate_space(desired_size); let rect = ui.layout().align_size_within_rect(desired_size, rect); - - let id = ui.make_position_id(); let response = ui.interact(rect, id, Sense::click()); let text_cursor = pos2( @@ -663,9 +659,8 @@ impl Widget for SelectableLabel { let mut desired_size = total_extra + galley.size; desired_size = desired_size.at_least(ui.style().spacing.interact_size); - let rect = ui.allocate_space(desired_size); + let (id, rect) = ui.allocate_space(desired_size); - let id = ui.make_position_id(); let response = ui.interact(rect, id, Sense::click()); let text_cursor = pos2( @@ -722,27 +717,26 @@ impl Widget for Separator { let available_space = ui.available_size_before_wrap_finite(); - let (points, rect) = if ui.layout().main_dir().is_horizontal() { - let rect = ui.allocate_space(vec2(spacing, available_space.y)); - ( - [ - pos2(rect.center().x, rect.top()), - pos2(rect.center().x, rect.bottom()), - ], - rect, - ) + let size = if ui.layout().main_dir().is_horizontal() { + vec2(spacing, available_space.y) } else { - let rect = ui.allocate_space(vec2(available_space.x, spacing)); - ( - [ - pos2(rect.left(), rect.center().y), - pos2(rect.right(), rect.center().y), - ], - rect, - ) + vec2(available_space.x, spacing) + }; + + let (id, rect) = ui.allocate_space(size); + let points = if ui.layout().main_dir().is_horizontal() { + [ + pos2(rect.center().x, rect.top()), + pos2(rect.center().x, rect.bottom()), + ] + } else { + [ + pos2(rect.left(), rect.center().y), + pos2(rect.right(), rect.center().y), + ] }; let stroke = ui.style().visuals.widgets.noninteractive.bg_stroke; ui.painter().line_segment(points, stroke); - ui.interact_hover(rect) + ui.interact(rect, id, Sense::nothing()) } } diff --git a/egui/src/widgets/slider.rs b/egui/src/widgets/slider.rs index 86b6c660..f32fa133 100644 --- a/egui/src/widgets/slider.rs +++ b/egui/src/widgets/slider.rs @@ -243,8 +243,7 @@ impl<'a> Slider<'a> { /// Just the slider, no text fn allocate_slide_space(&self, ui: &mut Ui, height: f32) -> Response { let desired_size = vec2(ui.style().spacing.slider_width, height); - let rect = ui.allocate_space(desired_size); - let id = ui.make_position_id(); + let (id, rect) = ui.allocate_space(desired_size); ui.interact(rect, id, Sense::click_and_drag()) } @@ -310,7 +309,7 @@ impl<'a> Slider<'a> { } fn value_ui(&mut self, ui: &mut Ui, x_range: RangeInclusive) { - let kb_edit_id = ui.make_position_id().with("edit"); + let kb_edit_id = ui.auto_id_with("edit"); let is_kb_editing = ui.memory().has_kb_focus(kb_edit_id); let aim_radius = ui.input().aim_radius(); diff --git a/egui/src/widgets/text_edit.rs b/egui/src/widgets/text_edit.rs index 621892ae..8158db8f 100644 --- a/egui/src/widgets/text_edit.rs +++ b/egui/src/widgets/text_edit.rs @@ -241,14 +241,13 @@ impl<'t> Widget for TextEdit<'t> { galley.size.x.max(desired_width.min(available_width)), galley.size.y.max(desired_height), ); - let rect = ui.allocate_space(desired_size); + let (auto_id, rect) = ui.allocate_space(desired_size); let id = id.unwrap_or_else(|| { if let Some(id_source) = id_source { ui.make_persistent_id(id_source) } else { - // Since we are only storing cursor, perfect persistence Id not super important - ui.make_position_id() // Must be after allocate_space! + auto_id // Since we are only storing the cursor, perfect persistence Id not super important } }); let mut state = ui.memory().text_edit.get(&id).cloned().unwrap_or_default();