summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--native/src/element.rs37
-rw-r--r--native/src/user_interface.rs8
-rw-r--r--native/src/widget.rs1
-rw-r--r--native/src/widget/action.rs6
-rw-r--r--native/src/widget/button.rs16
-rw-r--r--native/src/widget/column.rs19
-rw-r--r--native/src/widget/container.rs17
-rw-r--r--native/src/widget/operation.rs18
-rw-r--r--native/src/widget/row.rs19
-rw-r--r--native/src/widget/scrollable.rs16
-rw-r--r--native/src/widget/text_input.rs39
-rw-r--r--src/widget.rs4
12 files changed, 178 insertions, 22 deletions
diff --git a/native/src/element.rs b/native/src/element.rs
index cc74035e..01b71aa4 100644
--- a/native/src/element.rs
+++ b/native/src/element.rs
@@ -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,
diff --git a/native/src/user_interface.rs b/native/src/user_interface.rs
index 25557240..42669f95 100644
--- a/native/src/user_interface.rs
+++ b/native/src/user_interface.rs
@@ -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(
diff --git a/native/src/widget.rs b/native/src/widget.rs
index 79f6ae3a..56ba28c8 100644
--- a/native/src/widget.rs
+++ b/native/src/widget.rs
@@ -171,6 +171,7 @@ where
/// Applies an [`Operation`] to the [`Widget`].
fn operate(
&self,
+ _state: &mut Tree,
_layout: Layout<'_>,
_operation: &mut dyn Operation<Message>,
) {
diff --git a/native/src/widget/action.rs b/native/src/widget/action.rs
index 23ea4269..69723358 100644
--- a/native/src/widget/action.rs
+++ b/native/src/widget/action.rs
@@ -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 });
});
}
diff --git a/native/src/widget/button.rs b/native/src/widget/button.rs
index 6eac6c1b..6c0b8f6e 100644
--- a/native/src/widget/button.rs
+++ b/native/src/widget/button.rs
@@ -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,
diff --git a/native/src/widget/column.rs b/native/src/widget/column.rs
index 834f9858..a8b0f183 100644
--- a/native/src/widget/column.rs
+++ b/native/src/widget/column.rs
@@ -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,
diff --git a/native/src/widget/container.rs b/native/src/widget/container.rs
index b0fa0315..2afad3f2 100644
--- a/native/src/widget/container.rs
+++ b/native/src/widget/container.rs
@@ -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,
diff --git a/native/src/widget/operation.rs b/native/src/widget/operation.rs
index b6c108e0..2cfba005 100644
--- a/native/src/widget/operation.rs
+++ b/native/src/widget/operation.rs
@@ -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)
}
diff --git a/native/src/widget/row.rs b/native/src/widget/row.rs
index c342c277..eda7c2d3 100644
--- a/native/src/widget/row.rs
+++ b/native/src/widget/row.rs
@@ -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,
diff --git a/native/src/widget/scrollable.rs b/native/src/widget/scrollable.rs
index b40c3743..91c13eb5 100644
--- a/native/src/widget/scrollable.rs
+++ b/native/src/widget/scrollable.rs
@@ -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,
diff --git a/native/src/widget/text_input.rs b/native/src/widget/text_input.rs
index 1dbb8d6b..1ca5ccf2 100644
--- a/native/src/widget/text_input.rs
+++ b/native/src/widget/text_input.rs
@@ -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`].
diff --git a/src/widget.rs b/src/widget.rs
index 4ddf0566..abffadd5 100644
--- a/src/widget.rs
+++ b/src/widget.rs
@@ -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> =