summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/todos/src/main.rs15
-rw-r--r--native/src/widget/operation.rs47
-rw-r--r--src/widget.rs8
3 files changed, 59 insertions, 11 deletions
diff --git a/examples/todos/src/main.rs b/examples/todos/src/main.rs
index 25d90a0b..bb00aac6 100644
--- a/examples/todos/src/main.rs
+++ b/examples/todos/src/main.rs
@@ -51,7 +51,7 @@ enum Message {
CreateTask,
FilterChanged(Filter),
TaskMessage(usize, TaskMessage),
- TabPressed,
+ TabPressed { shift: bool },
}
impl Application for Todos {
@@ -147,7 +147,13 @@ impl Application for Todos {
Command::none()
}
- Message::TabPressed => widget::focus_next(),
+ Message::TabPressed { shift } => {
+ if shift {
+ widget::focus_previous()
+ } else {
+ widget::focus_next()
+ }
+ }
_ => Command::none(),
};
@@ -251,10 +257,13 @@ impl Application for Todos {
(
Event::Keyboard(keyboard::Event::KeyPressed {
key_code: keyboard::KeyCode::Tab,
+ modifiers,
..
}),
event::Status::Ignored,
- ) => Some(Message::TabPressed),
+ ) => Some(Message::TabPressed {
+ shift: modifiers.shift(),
+ }),
_ => None,
})
}
diff --git a/native/src/widget/operation.rs b/native/src/widget/operation.rs
index 5a0f0c18..caf7ba1c 100644
--- a/native/src/widget/operation.rs
+++ b/native/src/widget/operation.rs
@@ -109,13 +109,13 @@ where
}
}
-pub fn focus_next<T>() -> impl Operation<T> {
- struct FocusNext {
+pub fn focus_previous<T>() -> impl Operation<T> {
+ struct FocusPrevious {
count: FocusCount,
current: usize,
}
- impl<T> Operation<T> for FocusNext {
+ impl<T> Operation<T> for FocusPrevious {
fn focusable(
&mut self,
state: &mut dyn state::Focusable,
@@ -126,14 +126,45 @@ pub fn focus_next<T>() -> impl Operation<T> {
}
match self.count.focused {
+ None if self.current == self.count.total - 1 => state.focus(),
+ Some(0) if self.current == 0 => state.unfocus(),
+ Some(0) => {}
+ Some(focused) if focused == self.current => state.unfocus(),
+ Some(focused) if focused - 1 == self.current => state.focus(),
+ _ => {}
+ }
+
+ self.current += 1;
+ }
+
+ fn container(
+ &mut self,
+ _id: Option<&Id>,
+ operate_on_children: &mut dyn FnMut(&mut dyn Operation<T>),
+ ) {
+ operate_on_children(self)
+ }
+ }
+
+ count_focusable(|count| FocusPrevious { count, current: 0 })
+}
+
+pub fn focus_next<T>() -> impl Operation<T> {
+ struct FocusNext {
+ count: FocusCount,
+ current: usize,
+ }
+
+ impl<T> Operation<T> for FocusNext {
+ fn focusable(
+ &mut self,
+ state: &mut dyn state::Focusable,
+ _id: Option<&Id>,
+ ) {
+ match self.count.focused {
None if self.current == 0 => state.focus(),
Some(focused) if focused == self.current => state.unfocus(),
Some(focused) if focused + 1 == self.current => state.focus(),
- Some(focused)
- if focused == self.count.total - 1 && self.current == 0 =>
- {
- state.focus()
- }
_ => {}
}
diff --git a/src/widget.rs b/src/widget.rs
index 2333aa28..c3b6d83b 100644
--- a/src/widget.rs
+++ b/src/widget.rs
@@ -215,6 +215,14 @@ pub use svg::Svg;
use crate::Command;
use iced_native::widget::operation;
+/// Focuses the previous focusable widget.
+pub fn focus_previous<Message>() -> Command<Message>
+where
+ Message: 'static,
+{
+ Command::widget(operation::focus_previous())
+}
+
/// Focuses the next focusable widget.
pub fn focus_next<Message>() -> Command<Message>
where