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`).*
This commit is contained in:
MStarha 2025-03-20 10:40:22 +01:00 committed by GitHub
parent 93c06c3405
commit f408ccafbc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 31 additions and 17 deletions

View File

@ -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 {

View File

@ -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),
);

View File

@ -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(