diff --git a/examples/delineate/src/main.rs b/examples/delineate/src/main.rs index 97bd7d62..d4bc8a9a 100644 --- a/examples/delineate/src/main.rs +++ b/examples/delineate/src/main.rs @@ -28,8 +28,8 @@ enum Message { MouseMoved(Point), WindowResized, Scrolled, - OuterFound(Option), - InnerFound(Option), + OuterFound(Option), + InnerFound(Option), } impl Example { @@ -41,16 +41,18 @@ impl Example { Task::none() } Message::Scrolled | Message::WindowResized => Task::batch(vec![ - selector::delineate(OUTER_CONTAINER).map(Message::OuterFound), - selector::delineate(INNER_CONTAINER).map(Message::InnerFound), + selector::find(OUTER_CONTAINER).map(Message::OuterFound), + selector::find(INNER_CONTAINER).map(Message::InnerFound), ]), Message::OuterFound(outer) => { - self.outer_bounds = outer; + self.outer_bounds = + outer.as_ref().and_then(selector::Target::visible_bounds); Task::none() } Message::InnerFound(inner) => { - self.inner_bounds = inner; + self.inner_bounds = + inner.as_ref().and_then(selector::Target::visible_bounds); Task::none() } diff --git a/runtime/src/widget/selector.rs b/runtime/src/widget/selector.rs index a6f306c5..77d4eb2d 100644 --- a/runtime/src/widget/selector.rs +++ b/runtime/src/widget/selector.rs @@ -1,28 +1,25 @@ //! Find and query widgets in your applications. -pub use iced_selector::{Bounded, Candidate, Selector, Target, Text}; - -use crate::core::Rectangle; +pub use iced_selector::{ + Bounded, Candidate, Selector, Target, Text, id, is_focused, +}; use crate::Task; -use crate::core::widget; use crate::task; -/// Finds a widget by the given [`widget::Id`]. -pub fn find_by_id(id: impl Into) -> Task> { - task::widget(id.into().find()) -} - -/// Finds a widget that contains the given text. -pub fn find_by_text(text: impl Into) -> Task> { - task::widget(Selector::find(text.into())) -} - -/// Finds the visible bounds of the first [`Selector`] target. -pub fn delineate(selector: S) -> Task> +/// Finds a widget matching the given [`Selector`]. +pub fn find(selector: S) -> Task> where S: Selector + Send + 'static, - S::Output: Bounded + Clone + Send + 'static, + S::Output: Send + Clone + 'static, { task::widget(selector.find()) - .map(|target| target.as_ref().and_then(Bounded::visible_bounds)) +} + +/// Finds all widgets matching the given [`Selector`]. +pub fn find_all(selector: S) -> Task> +where + S: Selector + Send + 'static, + S::Output: Send + Clone + 'static, +{ + task::widget(selector.find_all()) } diff --git a/selector/src/lib.rs b/selector/src/lib.rs index e5703df5..1f90ef8e 100644 --- a/selector/src/lib.rs +++ b/selector/src/lib.rs @@ -146,3 +146,28 @@ where pub fn id(id: impl Into) -> impl Selector { id.into() } + +/// Returns a [`Selector`] that matches widgets that are currently focused. +pub fn is_focused() -> impl Selector { + struct IsFocused; + + impl Selector for IsFocused { + type Output = Target; + + fn select(&mut self, candidate: Candidate<'_>) -> Option { + if let Candidate::Focusable { state, .. } = candidate + && state.is_focused() + { + Some(Target::from(candidate)) + } else { + None + } + } + + fn description(&self) -> String { + "is focused".to_string() + } + } + + IsFocused +}