improv: operation and select for directional navigation

This commit is contained in:
Ashley Wulber 2026-09-01 23:18:45 -04:00 • committed by Ashley Wulber
parent d0f221c48b
commit 880f2c7565
7 changed files with 98 additions and 12 deletions

View file

@ -1,3 +1,5 @@
use iced_core::window;
use crate::Selector;
use crate::core::widget::operation::{
Focusable, Outcome, Scrollable, TextInput,
@ -100,6 +102,10 @@ where
fn finish(&self) -> Self::Output {
self.outputs.clone()
}
fn set_window_id(&mut self, id: window::Id) {
self.selector.set_window_id(id);
}
}
pub trait Strategy {
@ -110,6 +116,8 @@ pub trait Strategy {
fn is_done(&self) -> bool;
fn finish(&self) -> Self::Output;
fn set_window_id(&mut self, _id: window::Id) {}
}
#[derive(Debug)]
@ -273,4 +281,8 @@ where
fn finish(&self) -> Outcome<S::Output> {
Outcome::Some(self.strategy.finish())
}
fn set_window_id(&mut self, id: window::Id) {
self.strategy.set_window_id(id);
}
}

View file

@ -1,5 +1,6 @@
//! Select data from the widget tree.
use iced_core as core;
use iced_core::window;
mod find;
mod target;
@ -48,6 +49,8 @@ pub trait Selector {
{
FindAll::new(find::All::new(self))
}
fn set_window_id(&mut self, _id: window::Id) {}
}
impl Selector for &str {
@ -171,3 +174,40 @@ pub fn is_focused() -> impl Selector<Output = Target> {
IsFocused
}
/// Returns a [`Selector`] that matches widgets that are focusable.
pub fn focus() -> impl Selector<Output = (bool, Target, window::Id)> {
struct Focus {
cur_window_id: window::Id,
}
impl Selector for Focus {
type Output = (bool, Target, window::Id);
fn select(&mut self, candidate: Candidate<'_>) -> Option<Self::Output> {
if let Candidate::Focusable { state, .. } = candidate {
Some((
state.is_focused(),
Target::from(candidate),
self.cur_window_id,
))
} else if matches!(candidate, Candidate::Scrollable { .. }) {
Some((false, Target::from(candidate), self.cur_window_id))
} else {
None
}
}
fn description(&self) -> String {
"is focusable and focused".to_owned()
}
fn set_window_id(&mut self, id: iced_core::window::Id) {
self.cur_window_id = id;
}
}
Focus {
cur_window_id: window::Id::NONE,
}
}