fix: text input RTL panic

RTL text will want to alight to the right, and will try to use all of an unbounded width in the input. It also tends to be offset in a negative direction.
This commit is contained in:
Ashley Wulber 2025-05-06 13:31:42 -04:00 committed by Ashley Wulber
parent 7151638f51
commit c8c650c041

View file

@ -699,8 +699,7 @@ where
let size = self.size.unwrap_or_else(|| renderer.default_size().0); let size = self.size.unwrap_or_else(|| renderer.default_size().0);
let bounds = limits.max(); let bounds = limits.resolve(Length::Shrink, Length::Fill, Size::INFINITY);
let value_paragraph = &mut state.value; let value_paragraph = &mut state.value;
let v = self.value.to_string(); let v = self.value.to_string();
value_paragraph.update(Text { value_paragraph.update(Text {
@ -716,7 +715,7 @@ where
vertical_alignment: alignment::Vertical::Center, vertical_alignment: alignment::Vertical::Center,
line_height: text::LineHeight::default(), line_height: text::LineHeight::default(),
shaping: text::Shaping::Advanced, shaping: text::Shaping::Advanced,
wrapping: text::Wrapping::default(), wrapping: text::Wrapping::None,
}); });
let Size { width, height } = let Size { width, height } =
@ -760,6 +759,7 @@ where
font, font,
iced::Pixels(size), iced::Pixels(size),
line_height, line_height,
limits,
); );
} }
res res
@ -1141,7 +1141,7 @@ pub fn layout<Message>(
vertical_alignment: alignment::Vertical::Center, vertical_alignment: alignment::Vertical::Center,
line_height, line_height,
shaping: text::Shaping::Advanced, shaping: text::Shaping::Advanced,
wrapping: text::Wrapping::default(), wrapping: text::Wrapping::None,
}); });
let label_size = label_paragraph.min_bounds(); let label_size = label_paragraph.min_bounds();
@ -1194,9 +1194,7 @@ pub fn layout<Message>(
let text_limits = limits let text_limits = limits
.width(width) .width(width)
.height(line_height.to_absolute(text_size.into())); .height(line_height.to_absolute(text_size.into()));
let text_bounds = text_limits.resolve(Length::Shrink, Length::Shrink, Size::INFINITY);
let text_bounds = text_limits.resolve(width, Length::Shrink, Size::INFINITY);
let text_node = layout::Node::new( let text_node = layout::Node::new(
text_bounds - Size::new(leading_icon_width + trailing_icon_width, 0.0), text_bounds - Size::new(leading_icon_width + trailing_icon_width, 0.0),
) )
@ -1250,7 +1248,7 @@ pub fn layout<Message>(
.width(width) .width(width)
.height(text_input_height + padding.vertical()) .height(text_input_height + padding.vertical())
.shrink(padding); .shrink(padding);
let text_bounds = limits.resolve(width, Length::Shrink, Size::INFINITY); let text_bounds = limits.resolve(Length::Shrink, Length::Shrink, Size::INFINITY);
let text = layout::Node::new(text_bounds).move_to(Point::new(padding.left, padding.top)); let text = layout::Node::new(text_bounds).move_to(Point::new(padding.left, padding.top));
@ -1280,7 +1278,7 @@ pub fn layout<Message>(
vertical_alignment: alignment::Vertical::Center, vertical_alignment: alignment::Vertical::Center,
line_height: helper_text_line_height, line_height: helper_text_line_height,
shaping: text::Shaping::Advanced, shaping: text::Shaping::Advanced,
wrapping: text::Wrapping::default(), wrapping: text::Wrapping::None,
}); });
let helper_text_size = helper_text_paragraph.min_bounds(); let helper_text_size = helper_text_paragraph.min_bounds();
let helper_text_node = layout::Node::new(helper_text_size).translate(helper_pos); let helper_text_node = layout::Node::new(helper_text_size).translate(helper_pos);
@ -1339,7 +1337,15 @@ pub fn update<'a, Message: Clone + 'static>(
manage_value: bool, manage_value: bool,
) -> event::Status { ) -> event::Status {
let update_cache = |state, value| { let update_cache = |state, value| {
replace_paragraph(state, layout, value, font, iced::Pixels(size), line_height); replace_paragraph(
state,
layout,
value,
font,
iced::Pixels(size),
line_height,
&Limits::NONE.max_width(text_layout.bounds().width),
);
}; };
let mut secured_value = if is_secure { let mut secured_value = if is_secure {
@ -2208,7 +2214,7 @@ pub fn draw<'a, Message>(
vertical_alignment: alignment::Vertical::Top, vertical_alignment: alignment::Vertical::Top,
line_height, line_height,
shaping: text::Shaping::Advanced, shaping: text::Shaping::Advanced,
wrapping: text::Wrapping::default(), wrapping: text::Wrapping::None,
}, },
label_layout.bounds().position(), label_layout.bounds().position(),
appearance.label_color, appearance.label_color,
@ -2243,6 +2249,8 @@ pub fn draw<'a, Message>(
let text = value.to_string(); let text = value.to_string();
let font = font.unwrap_or_else(|| renderer.default_font()); let font = font.unwrap_or_else(|| renderer.default_font());
let size = size.unwrap_or_else(|| renderer.default_size().0); let size = size.unwrap_or_else(|| renderer.default_size().0);
let text_width = state.value.min_width();
let actual_width = text_width.max(text_bounds.width);
let radius_0 = THEME.lock().unwrap().cosmic().corner_radii.radius_0.into(); let radius_0 = THEME.lock().unwrap().cosmic().corner_radii.radius_0.into();
#[cfg(feature = "wayland")] #[cfg(feature = "wayland")]
@ -2264,7 +2272,6 @@ pub fn draw<'a, Message>(
|| ((focus.now - focus.updated_at).as_millis() / CURSOR_BLINK_INTERVAL_MILLIS) || ((focus.now - focus.updated_at).as_millis() / CURSOR_BLINK_INTERVAL_MILLIS)
% 2 % 2
== 0; == 0;
if is_cursor_visible { if is_cursor_visible {
if dnd_icon { if dnd_icon {
(None, 0.0) (None, 0.0)
@ -2273,7 +2280,12 @@ pub fn draw<'a, Message>(
Some(( Some((
renderer::Quad { renderer::Quad {
bounds: Rectangle { bounds: Rectangle {
x: text_bounds.x + text_value_width - offset, x: text_bounds.x + text_value_width - offset
+ if text_value_width < 0. {
actual_width
} else {
0.
},
y: text_bounds.y, y: text_bounds.y,
width: 1.0, width: 1.0,
height: text_bounds.height, height: text_bounds.height,
@ -2310,7 +2322,6 @@ pub fn draw<'a, Message>(
measure_cursor_and_scroll_offset(value_paragraph.raw(), text_bounds, right); measure_cursor_and_scroll_offset(value_paragraph.raw(), text_bounds, right);
let width = right_position - left_position; let width = right_position - left_position;
if dnd_icon { if dnd_icon {
(None, 0.0) (None, 0.0)
} else { } else {
@ -2318,7 +2329,13 @@ pub fn draw<'a, Message>(
Some(( Some((
renderer::Quad { renderer::Quad {
bounds: Rectangle { bounds: Rectangle {
x: text_bounds.x + left_position, x: text_bounds.x
+ left_position
+ if left_position < 0. || right_position < 0. {
actual_width
} else {
0.
},
y: text_bounds.y, y: text_bounds.y,
width, width,
height: text_bounds.height, height: text_bounds.height,
@ -2349,8 +2366,6 @@ pub fn draw<'a, Message>(
(None, 0.0) (None, 0.0)
}; };
let text_width = state.value.min_width();
let render = |renderer: &mut crate::Renderer| { let render = |renderer: &mut crate::Renderer| {
if let Some((cursor, color)) = cursor { if let Some((cursor, color)) = cursor {
renderer.fill_quad(cursor, color); renderer.fill_quad(cursor, color);
@ -2361,7 +2376,7 @@ pub fn draw<'a, Message>(
let bounds = Rectangle { let bounds = Rectangle {
x: text_bounds.x - offset, x: text_bounds.x - offset,
y: text_bounds.center_y(), y: text_bounds.center_y(),
width: f32::INFINITY, width: actual_width,
..text_bounds ..text_bounds
}; };
let color = if text.is_empty() { let color = if text.is_empty() {
@ -2384,7 +2399,7 @@ pub fn draw<'a, Message>(
vertical_alignment: alignment::Vertical::Center, vertical_alignment: alignment::Vertical::Center,
line_height: text::LineHeight::default(), line_height: text::LineHeight::default(),
shaping: text::Shaping::Advanced, shaping: text::Shaping::Advanced,
wrapping: text::Wrapping::default(), wrapping: text::Wrapping::None,
}, },
bounds.position(), bounds.position(),
color, color,
@ -2432,7 +2447,7 @@ pub fn draw<'a, Message>(
vertical_alignment: alignment::Vertical::Top, vertical_alignment: alignment::Vertical::Top,
line_height: helper_line_height, line_height: helper_line_height,
shaping: text::Shaping::Advanced, shaping: text::Shaping::Advanced,
wrapping: text::Wrapping::default(), wrapping: text::Wrapping::None,
}, },
helper_text_layout.bounds().position(), helper_text_layout.bounds().position(),
text_color, text_color,
@ -2769,20 +2784,26 @@ fn replace_paragraph(
font: <crate::Renderer as iced_core::text::Renderer>::Font, font: <crate::Renderer as iced_core::text::Renderer>::Font,
text_size: Pixels, text_size: Pixels,
line_height: text::LineHeight, line_height: text::LineHeight,
limits: &layout::Limits,
) { ) {
let mut children_layout = layout.children(); let mut children_layout = layout.children();
let text_bounds = children_layout.next().unwrap().bounds(); let text_bounds = children_layout.next().unwrap();
let bounds = limits.resolve(
Length::Shrink,
Length::Fill,
Size::new(0., text_bounds.bounds().height),
);
state.value = crate::Plain::new(Text { state.value = crate::Plain::new(Text {
font, font,
line_height, line_height,
content: &value.to_string(), content: &value.to_string(),
bounds: Size::new(f32::INFINITY, text_bounds.height), bounds,
size: text_size, size: text_size,
horizontal_alignment: alignment::Horizontal::Left, horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Top, vertical_alignment: alignment::Vertical::Top,
shaping: text::Shaping::Advanced, shaping: text::Shaping::Advanced,
wrapping: text::Wrapping::default(), wrapping: text::Wrapping::None,
}); });
} }