Implement Widget::operate for TextInput
This commit is contained in:
parent
80688689aa
commit
52f84e51e9
12 changed files with 178 additions and 22 deletions
|
|
@ -3,6 +3,7 @@ use crate::layout;
|
|||
use crate::mouse;
|
||||
use crate::overlay;
|
||||
use crate::renderer;
|
||||
use crate::widget;
|
||||
use crate::widget::tree::{self, Tree};
|
||||
use crate::{Clipboard, Layout, Length, Point, Rectangle, Shell, Widget};
|
||||
|
||||
|
|
@ -248,6 +249,42 @@ where
|
|||
self.widget.layout(renderer, limits)
|
||||
}
|
||||
|
||||
fn operate(
|
||||
&self,
|
||||
tree: &mut Tree,
|
||||
layout: Layout<'_>,
|
||||
operation: &mut dyn widget::Operation<B>,
|
||||
) {
|
||||
struct MapOperation<'a, B> {
|
||||
operation: &'a mut dyn widget::Operation<B>,
|
||||
}
|
||||
|
||||
impl<'a, T, B> widget::Operation<T> for MapOperation<'a, B> {
|
||||
fn container(
|
||||
&mut self,
|
||||
id: Option<&widget::Id>,
|
||||
operate_on_children: &mut dyn FnMut(
|
||||
&mut dyn widget::Operation<T>,
|
||||
),
|
||||
) {
|
||||
self.operation.container(id, &mut |operation| {
|
||||
operate_on_children(&mut MapOperation { operation });
|
||||
});
|
||||
}
|
||||
|
||||
fn focusable(
|
||||
&mut self,
|
||||
state: &mut dyn widget::state::Focusable,
|
||||
id: Option<&widget::Id>,
|
||||
) {
|
||||
self.operation.focusable(state, id);
|
||||
}
|
||||
}
|
||||
|
||||
self.widget
|
||||
.operate(tree, layout, &mut MapOperation { operation });
|
||||
}
|
||||
|
||||
fn on_event(
|
||||
&mut self,
|
||||
tree: &mut Tree,
|
||||
|
|
|
|||
|
|
@ -485,9 +485,11 @@ where
|
|||
renderer: &Renderer,
|
||||
operation: &mut dyn widget::Operation<Message>,
|
||||
) {
|
||||
self.root
|
||||
.as_widget()
|
||||
.operate(Layout::new(&self.base), operation);
|
||||
self.root.as_widget().operate(
|
||||
&mut self.state,
|
||||
Layout::new(&self.base),
|
||||
operation,
|
||||
);
|
||||
|
||||
if let Some(layout) = self.overlay.as_ref() {
|
||||
if let Some(overlay) = self.root.as_widget().overlay(
|
||||
|
|
|
|||
|
|
@ -171,6 +171,7 @@ where
|
|||
/// Applies an [`Operation`] to the [`Widget`].
|
||||
fn operate(
|
||||
&self,
|
||||
_state: &mut Tree,
|
||||
_layout: Layout<'_>,
|
||||
_operation: &mut dyn Operation<Message>,
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ where
|
|||
fn container(
|
||||
&mut self,
|
||||
id: Option<&Id>,
|
||||
operate_on_children: &dyn Fn(&mut dyn Operation<B>),
|
||||
operate_on_children: &mut dyn FnMut(&mut dyn Operation<B>),
|
||||
) {
|
||||
struct MapRef<'a, A, B> {
|
||||
operation: &'a mut dyn Operation<A>,
|
||||
|
|
@ -53,11 +53,11 @@ where
|
|||
fn container(
|
||||
&mut self,
|
||||
id: Option<&Id>,
|
||||
operate_on_children: &dyn Fn(&mut dyn Operation<B>),
|
||||
operate_on_children: &mut dyn FnMut(&mut dyn Operation<B>),
|
||||
) {
|
||||
let Self { operation, f } = self;
|
||||
|
||||
operation.container(id, &|operation| {
|
||||
operation.container(id, &mut |operation| {
|
||||
operate_on_children(&mut MapRef { operation, f });
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ use crate::overlay;
|
|||
use crate::renderer;
|
||||
use crate::touch;
|
||||
use crate::widget::tree::{self, Tree};
|
||||
use crate::widget::Operation;
|
||||
use crate::{
|
||||
Background, Clipboard, Color, Element, Layout, Length, Padding, Point,
|
||||
Rectangle, Shell, Vector, Widget,
|
||||
|
|
@ -164,6 +165,21 @@ where
|
|||
)
|
||||
}
|
||||
|
||||
fn operate(
|
||||
&self,
|
||||
tree: &mut Tree,
|
||||
layout: Layout<'_>,
|
||||
operation: &mut dyn Operation<Message>,
|
||||
) {
|
||||
operation.container(None, &mut |operation| {
|
||||
self.content.as_widget().operate(
|
||||
&mut tree.children[0],
|
||||
layout.children().next().unwrap(),
|
||||
operation,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
fn on_event(
|
||||
&mut self,
|
||||
tree: &mut Tree,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use crate::layout;
|
|||
use crate::mouse;
|
||||
use crate::overlay;
|
||||
use crate::renderer;
|
||||
use crate::widget::Tree;
|
||||
use crate::widget::{Operation, Tree};
|
||||
use crate::{
|
||||
Alignment, Clipboard, Element, Layout, Length, Padding, Point, Rectangle,
|
||||
Shell, Widget,
|
||||
|
|
@ -143,6 +143,23 @@ where
|
|||
)
|
||||
}
|
||||
|
||||
fn operate(
|
||||
&self,
|
||||
tree: &mut Tree,
|
||||
layout: Layout<'_>,
|
||||
operation: &mut dyn Operation<Message>,
|
||||
) {
|
||||
operation.container(None, &mut |operation| {
|
||||
self.children
|
||||
.iter()
|
||||
.zip(&mut tree.children)
|
||||
.zip(layout.children())
|
||||
.for_each(|((child, state), layout)| {
|
||||
child.as_widget().operate(state, layout, operation);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn on_event(
|
||||
&mut self,
|
||||
tree: &mut Tree,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use crate::layout;
|
|||
use crate::mouse;
|
||||
use crate::overlay;
|
||||
use crate::renderer;
|
||||
use crate::widget::Tree;
|
||||
use crate::widget::{Operation, Tree};
|
||||
use crate::{
|
||||
Background, Clipboard, Color, Element, Layout, Length, Padding, Point,
|
||||
Rectangle, Shell, Widget,
|
||||
|
|
@ -165,6 +165,21 @@ where
|
|||
)
|
||||
}
|
||||
|
||||
fn operate(
|
||||
&self,
|
||||
tree: &mut Tree,
|
||||
layout: Layout<'_>,
|
||||
operation: &mut dyn Operation<Message>,
|
||||
) {
|
||||
operation.container(None, &mut |operation| {
|
||||
self.content.as_widget().operate(
|
||||
&mut tree.children[0],
|
||||
layout.children().next().unwrap(),
|
||||
operation,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
fn on_event(
|
||||
&mut self,
|
||||
tree: &mut Tree,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ pub trait Operation<T> {
|
|||
fn container(
|
||||
&mut self,
|
||||
id: Option<&Id>,
|
||||
operate_on_children: &dyn Fn(&mut dyn Operation<T>),
|
||||
operate_on_children: &mut dyn FnMut(&mut dyn Operation<T>),
|
||||
);
|
||||
|
||||
fn focusable(
|
||||
|
|
@ -37,14 +37,12 @@ pub fn focus<T>(target: Id) -> impl Operation<T> {
|
|||
state: &mut dyn state::Focusable,
|
||||
id: Option<&Id>,
|
||||
) {
|
||||
if state.is_focused() {
|
||||
match id {
|
||||
Some(id) if id == &self.target => {
|
||||
state.focus();
|
||||
}
|
||||
_ => {
|
||||
state.unfocus();
|
||||
}
|
||||
match id {
|
||||
Some(id) if id == &self.target => {
|
||||
state.focus();
|
||||
}
|
||||
_ => {
|
||||
state.unfocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -52,7 +50,7 @@ pub fn focus<T>(target: Id) -> impl Operation<T> {
|
|||
fn container(
|
||||
&mut self,
|
||||
_id: Option<&Id>,
|
||||
operate_on_children: &dyn Fn(&mut dyn Operation<T>),
|
||||
operate_on_children: &mut dyn FnMut(&mut dyn Operation<T>),
|
||||
) {
|
||||
operate_on_children(self)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use crate::layout::{self, Layout};
|
|||
use crate::mouse;
|
||||
use crate::overlay;
|
||||
use crate::renderer;
|
||||
use crate::widget::Tree;
|
||||
use crate::widget::{Operation, Tree};
|
||||
use crate::{
|
||||
Alignment, Clipboard, Element, Length, Padding, Point, Rectangle, Shell,
|
||||
Widget,
|
||||
|
|
@ -130,6 +130,23 @@ where
|
|||
)
|
||||
}
|
||||
|
||||
fn operate(
|
||||
&self,
|
||||
tree: &mut Tree,
|
||||
layout: Layout<'_>,
|
||||
operation: &mut dyn Operation<Message>,
|
||||
) {
|
||||
operation.container(None, &mut |operation| {
|
||||
self.children
|
||||
.iter()
|
||||
.zip(&mut tree.children)
|
||||
.zip(layout.children())
|
||||
.for_each(|((child, state), layout)| {
|
||||
child.as_widget().operate(state, layout, operation);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn on_event(
|
||||
&mut self,
|
||||
tree: &mut Tree,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use crate::overlay;
|
|||
use crate::renderer;
|
||||
use crate::touch;
|
||||
use crate::widget::tree::{self, Tree};
|
||||
use crate::widget::Operation;
|
||||
use crate::{
|
||||
Background, Clipboard, Color, Element, Layout, Length, Point, Rectangle,
|
||||
Shell, Size, Vector, Widget,
|
||||
|
|
@ -150,6 +151,21 @@ where
|
|||
)
|
||||
}
|
||||
|
||||
fn operate(
|
||||
&self,
|
||||
tree: &mut Tree,
|
||||
layout: Layout<'_>,
|
||||
operation: &mut dyn Operation<Message>,
|
||||
) {
|
||||
operation.container(None, &mut |operation| {
|
||||
self.content.as_widget().operate(
|
||||
&mut tree.children[0],
|
||||
layout.children().next().unwrap(),
|
||||
operation,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
fn on_event(
|
||||
&mut self,
|
||||
tree: &mut Tree,
|
||||
|
|
|
|||
|
|
@ -19,11 +19,13 @@ use crate::mouse::{self, click};
|
|||
use crate::renderer;
|
||||
use crate::text::{self, Text};
|
||||
use crate::touch;
|
||||
use crate::widget;
|
||||
use crate::widget::operation::{self, Operation};
|
||||
use crate::widget::state;
|
||||
use crate::widget::tree::{self, Tree};
|
||||
use crate::{
|
||||
Clipboard, Color, Element, Layout, Length, Padding, Point, Rectangle,
|
||||
Shell, Size, Vector, Widget,
|
||||
Clipboard, Color, Command, Element, Layout, Length, Padding, Point,
|
||||
Rectangle, Shell, Size, Vector, Widget,
|
||||
};
|
||||
|
||||
pub use iced_style::text_input::{Appearance, StyleSheet};
|
||||
|
|
@ -54,6 +56,7 @@ where
|
|||
Renderer: text::Renderer,
|
||||
Renderer::Theme: StyleSheet,
|
||||
{
|
||||
id: Option<Id>,
|
||||
placeholder: String,
|
||||
value: Value,
|
||||
is_secure: bool,
|
||||
|
|
@ -84,6 +87,7 @@ where
|
|||
F: 'a + Fn(String) -> Message,
|
||||
{
|
||||
TextInput {
|
||||
id: None,
|
||||
placeholder: String::from(placeholder),
|
||||
value: Value::new(value),
|
||||
is_secure: false,
|
||||
|
|
@ -98,6 +102,12 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// Sets the [`Id`] of the [`TextInput`].
|
||||
pub fn id(mut self, id: Id) -> Self {
|
||||
self.id = Some(id);
|
||||
self
|
||||
}
|
||||
|
||||
/// Converts the [`TextInput`] into a secure password input.
|
||||
pub fn password(mut self) -> Self {
|
||||
self.is_secure = true;
|
||||
|
|
@ -215,6 +225,17 @@ where
|
|||
layout(renderer, limits, self.width, self.padding, self.size)
|
||||
}
|
||||
|
||||
fn operate(
|
||||
&self,
|
||||
tree: &mut Tree,
|
||||
_layout: Layout<'_>,
|
||||
operation: &mut dyn Operation<Message>,
|
||||
) {
|
||||
let state = tree.state.downcast_mut::<State>();
|
||||
|
||||
operation.focusable(state, self.id.as_ref().map(|id| &id.0));
|
||||
}
|
||||
|
||||
fn on_event(
|
||||
&mut self,
|
||||
tree: &mut Tree,
|
||||
|
|
@ -294,6 +315,19 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Id(widget::Id);
|
||||
|
||||
impl Id {
|
||||
pub fn new(id: impl Into<std::borrow::Cow<'static, str>>) -> Self {
|
||||
Self(widget::Id::new(id))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn focus<Message: 'static>(id: Id) -> Command<Message> {
|
||||
Command::widget(operation::focus(id.0))
|
||||
}
|
||||
|
||||
/// Computes the layout of a [`TextInput`].
|
||||
pub fn layout<Renderer>(
|
||||
renderer: &Renderer,
|
||||
|
|
@ -915,6 +949,7 @@ impl State {
|
|||
/// Focuses the [`TextInput`].
|
||||
pub fn focus(&mut self) {
|
||||
self.is_focused = true;
|
||||
self.move_cursor_to_end();
|
||||
}
|
||||
|
||||
/// Unfocuses the [`TextInput`].
|
||||
|
|
|
|||
|
|
@ -119,7 +119,9 @@ pub mod toggler {
|
|||
|
||||
pub mod text_input {
|
||||
//! Display fields that can be filled with text.
|
||||
pub use iced_native::widget::text_input::{Appearance, StyleSheet};
|
||||
pub use iced_native::widget::text_input::{
|
||||
focus, Appearance, Id, StyleSheet,
|
||||
};
|
||||
|
||||
/// A field that can be filled with text.
|
||||
pub type TextInput<'a, Message, Renderer = crate::Renderer> =
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue