Merge pull request #2535 from bungoboingo/text-input-alignment

Implement `align_x` for `TextInput`
This commit is contained in:
Héctor Ramón 2024-08-24 02:44:55 +02:00 committed by GitHub
commit 043f030214
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 71 additions and 11 deletions

View file

@ -202,7 +202,8 @@ impl Todos {
.on_input(Message::InputChanged)
.on_submit(Message::CreateTask)
.padding(15)
.size(30);
.size(30)
.align_x(Center);
let controls = view_controls(tasks, *filter);
let filtered_tasks =

View file

@ -19,7 +19,7 @@ use crate::core::keyboard::key;
use crate::core::layout;
use crate::core::mouse::{self, click};
use crate::core::renderer;
use crate::core::text::paragraph;
use crate::core::text::paragraph::{self, Paragraph as _};
use crate::core::text::{self, Text};
use crate::core::time::{Duration, Instant};
use crate::core::touch;
@ -74,6 +74,7 @@ pub struct TextInput<
padding: Padding,
size: Option<Pixels>,
line_height: text::LineHeight,
alignment: alignment::Horizontal,
on_input: Option<Box<dyn Fn(String) -> Message + 'a>>,
on_paste: Option<Box<dyn Fn(String) -> Message + 'a>>,
on_submit: Option<Message>,
@ -103,6 +104,7 @@ where
padding: DEFAULT_PADDING,
size: None,
line_height: text::LineHeight::default(),
alignment: alignment::Horizontal::Left,
on_input: None,
on_paste: None,
on_submit: None,
@ -193,6 +195,15 @@ where
self
}
/// Sets the horizontal alignment of the [`TextInput`].
pub fn align_x(
mut self,
alignment: impl Into<alignment::Horizontal>,
) -> Self {
self.alignment = alignment.into();
self
}
/// Sets the style of the [`TextInput`].
#[must_use]
pub fn style(mut self, style: impl Fn(&Theme, Status) -> Style + 'a) -> Self
@ -457,9 +468,21 @@ where
};
let draw = |renderer: &mut Renderer, viewport| {
let paragraph = if text.is_empty() {
state.placeholder.raw()
} else {
state.value.raw()
};
let alignment_offset = alignment_offset(
text_bounds.width,
paragraph.min_width(),
self.alignment,
);
if let Some((cursor, color)) = cursor {
renderer.with_translation(
Vector::new(-offset, 0.0),
Vector::new(alignment_offset - offset, 0.0),
|renderer| {
renderer.fill_quad(cursor, color);
},
@ -469,13 +492,9 @@ where
}
renderer.fill_paragraph(
if text.is_empty() {
state.placeholder.raw()
} else {
state.value.raw()
},
paragraph,
Point::new(text_bounds.x, text_bounds.center_y())
- Vector::new(offset, 0.0),
+ Vector::new(alignment_offset - offset, 0.0),
if text.is_empty() {
style.placeholder
} else {
@ -600,7 +619,18 @@ where
if let Some(cursor_position) = click_position {
let text_layout = layout.children().next().unwrap();
let target = cursor_position.x - text_layout.bounds().x;
let target = {
let text_bounds = text_layout.bounds();
let alignment_offset = alignment_offset(
text_bounds.width,
state.value.raw().min_width(),
self.alignment,
);
cursor_position.x - text_bounds.x - alignment_offset
};
let click =
mouse::Click::new(cursor_position, state.last_click);
@ -677,7 +707,18 @@ where
if state.is_dragging {
let text_layout = layout.children().next().unwrap();
let target = position.x - text_layout.bounds().x;
let target = {
let text_bounds = text_layout.bounds();
let alignment_offset = alignment_offset(
text_bounds.width,
state.value.raw().min_width(),
self.alignment,
);
position.x - text_bounds.x - alignment_offset
};
let value = if self.is_secure {
self.value.secure()
@ -1486,3 +1527,21 @@ pub fn default(theme: &Theme, status: Status) -> Style {
},
}
}
fn alignment_offset(
text_bounds_width: f32,
text_min_width: f32,
alignment: alignment::Horizontal,
) -> f32 {
if text_min_width > text_bounds_width {
0.0
} else {
match alignment {
alignment::Horizontal::Left => 0.0,
alignment::Horizontal::Center => {
(text_bounds_width - text_min_width) / 2.0
}
alignment::Horizontal::Right => text_bounds_width - text_min_width,
}
}
}