Implement focus_previous operation

This commit is contained in:
Héctor Ramón Jiménez 2022-08-04 03:24:44 +02:00
parent 54ad92ce91
commit 6eb3dd7e5e
No known key found for this signature in database
GPG key ID: 140CC052C94F138E
3 changed files with 60 additions and 12 deletions

View file

@ -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,
})
}

View file

@ -109,6 +109,46 @@ where
}
}
pub fn focus_previous<T>() -> impl Operation<T> {
struct FocusPrevious {
count: FocusCount,
current: usize,
}
impl<T> Operation<T> for FocusPrevious {
fn focusable(
&mut self,
state: &mut dyn state::Focusable,
_id: Option<&Id>,
) {
if self.count.total == 0 {
return;
}
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,
@ -121,19 +161,10 @@ pub fn focus_next<T>() -> impl Operation<T> {
state: &mut dyn state::Focusable,
_id: Option<&Id>,
) {
if self.count.total == 0 {
return;
}
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()
}
_ => {}
}

View file

@ -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