From f408ccafbce72c2e32afc9d17e1c16ba04e7f09e Mon Sep 17 00:00:00 2001 From: MStarha <59487310+MStarha@users.noreply.github.com> Date: Thu, 20 Mar 2025 10:40:22 +0100 Subject: [PATCH] Fix `DragValue` expansion when editing (#5809) * [x] I have followed the instructions in the PR template This PR fixes an issue, where `DragValue` would expand when it enters editing state. There were 3 contributing problems: - A workaround introduced in #4276 caused the `DragValue` to report incorrect outer size. - The `DragValue` uses `TextEdit` internally and sets both `min_size` and `desired_width` to the same value - desired width is used **before** padding is applied - this is in contrast to `Button` (also used internally by `DragValue`), which only uses `min_size`. This caused the `DragValue` to expand horizontally by the size of button padding. - The height of the `TextEdit` is (among other things) determined by the height of the row, which was not present in `Button`. This caused a small vertical expansion, when the contents (including padding) were larger than the `min_size`. ![egui_drag_value_expansion](https://github.com/user-attachments/assets/b6fe9bd8-5755-4a43-8b61-a7e5b24e678d) Here the dimensions set in code are: - padding: 20 x 20 pt - interact size: 80 x 30 pt *Note: I do not know what's up with the tests. When I ran the check script, they were failing because of 3 UI missmatches, so I updated the snapshots. Now, the updated snapshots cause the same failure in CI, that appeared locally before the update. Now the locally run tests fail with `The platform you're compiling for is not supported by winit` and couple more following errors coming from the same source (`winit 0.30.7`).* --- crates/egui/src/widgets/button.rs | 33 +++++++++++++++----- crates/egui/src/widgets/drag_value.rs | 4 ++- crates/egui/src/widgets/text_edit/builder.rs | 11 ++----- 3 files changed, 31 insertions(+), 17 deletions(-) diff --git a/crates/egui/src/widgets/button.rs b/crates/egui/src/widgets/button.rs index dcf37d20..c0701c19 100644 --- a/crates/egui/src/widgets/button.rs +++ b/crates/egui/src/widgets/button.rs @@ -1,6 +1,6 @@ use crate::{ - widgets, Align, Color32, CornerRadius, Image, NumExt, Rect, Response, Sense, Stroke, TextStyle, - TextWrapMode, Ui, Vec2, Widget, WidgetInfo, WidgetText, WidgetType, + widgets, Align, Color32, CornerRadius, FontSelection, Image, NumExt, Rect, Response, Sense, + Stroke, TextStyle, TextWrapMode, Ui, Vec2, Widget, WidgetInfo, WidgetText, WidgetType, }; /// Clickable button with text. @@ -224,6 +224,16 @@ impl Widget for Button<'_> { let frame = frame.unwrap_or_else(|| ui.visuals().button_frame); + let default_font_height = || { + let font_selection = FontSelection::default(); + let font_id = font_selection.resolve(ui.style()); + ui.fonts(|f| f.row_height(&font_id)) + }; + + let text_font_height = ui + .fonts(|fonts| text.as_ref().map(|wt| wt.font_height(fonts, ui.style()))) + .unwrap_or_else(default_font_height); + let mut button_padding = if frame { ui.spacing().button_padding } else { @@ -233,11 +243,17 @@ impl Widget for Button<'_> { button_padding.y = 0.0; } - let space_available_for_image = if let Some(text) = &text { + let (space_available_for_image, right_text_font_height) = if let Some(text) = &text { let font_height = ui.fonts(|fonts| text.font_height(fonts, ui.style())); - Vec2::splat(font_height) // Reasonable? + ( + Vec2::splat(font_height), // Reasonable? + font_height, + ) } else { - ui.available_size() - 2.0 * button_padding + ( + ui.available_size() - 2.0 * button_padding, + default_font_height(), + ) }; let image_size = if let Some(image) = &image { @@ -283,11 +299,14 @@ impl Widget for Button<'_> { } if let Some(galley) = &galley { desired_size.x += galley.size().x; - desired_size.y = desired_size.y.max(galley.size().y); + desired_size.y = desired_size.y.max(galley.size().y).max(text_font_height); } if let Some(right_galley) = &right_galley { desired_size.x += gap_before_right_text + right_galley.size().x; - desired_size.y = desired_size.y.max(right_galley.size().y); + desired_size.y = desired_size + .y + .max(right_galley.size().y) + .max(right_text_font_height); } desired_size += 2.0 * button_padding; if !small { diff --git a/crates/egui/src/widgets/drag_value.rs b/crates/egui/src/widgets/drag_value.rs index 846ab72f..1cf5ba7b 100644 --- a/crates/egui/src/widgets/drag_value.rs +++ b/crates/egui/src/widgets/drag_value.rs @@ -562,7 +562,9 @@ impl Widget for DragValue<'_> { .margin(ui.spacing().button_padding) .min_size(ui.spacing().interact_size) .id(id) - .desired_width(ui.spacing().interact_size.x) + .desired_width( + ui.spacing().interact_size.x - 2.0 * ui.spacing().button_padding.x, + ) .font(text_style), ); diff --git a/crates/egui/src/widgets/text_edit/builder.rs b/crates/egui/src/widgets/text_edit/builder.rs index 6350b202..7d5c23f6 100644 --- a/crates/egui/src/widgets/text_edit/builder.rs +++ b/crates/egui/src/widgets/text_edit/builder.rs @@ -426,18 +426,11 @@ impl TextEdit<'_> { let background_color = self .background_color .unwrap_or(ui.visuals().extreme_bg_color); - let margin = self.margin; - let mut output = self.show_content(ui); - - // TODO(emilk): return full outer_rect in `TextEditOutput`. - // Can't do it now because this fix is ging into a patch release. - let outer_rect = output.response.rect; - let inner_rect = outer_rect - margin; - output.response.rect = inner_rect; + let output = self.show_content(ui); if frame { let visuals = ui.style().interact(&output.response); - let frame_rect = outer_rect.expand(visuals.expansion); + let frame_rect = output.response.rect.expand(visuals.expansion); let shape = if is_mutable { if output.response.has_focus() { epaint::RectShape::new(