#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![deny(unused_results)]
#![forbid(unsafe_code)]
#![warn(
clippy::pedantic,
clippy::nursery,
// Restriction lints
clippy::clone_on_ref_ptr,
clippy::create_dir,
clippy::dbg_macro,
clippy::decimal_literal_representation,
clippy::exit,
clippy::float_cmp_const,
clippy::get_unwrap,
clippy::let_underscore_must_use,
clippy::map_err_ignore,
clippy::mem_forget,
clippy::missing_docs_in_private_items,
clippy::multiple_inherent_impl,
clippy::panic,
clippy::panic_in_result_fn,
clippy::print_stderr,
clippy::print_stdout,
clippy::rest_pat_in_fully_bound_structs,
clippy::str_to_string,
clippy::string_to_string,
clippy::todo,
clippy::unimplemented,
clippy::unneeded_field_pattern,
clippy::unwrap_in_result,
clippy::unwrap_used,
clippy::use_debug,
)]
#![allow(
clippy::suboptimal_flops,
clippy::cast_possible_truncation,
clippy::cast_sign_loss,
clippy::cast_possible_wrap,
clippy::module_name_repetitions
)]
#[cfg(feature = "derive")]
extern crate iced_focus_derive;
#[cfg(feature = "derive")]
#[doc(hidden)]
pub use iced_focus_derive::*;
pub trait Focus {
fn focus(&mut self, direction: Direction) -> State;
fn has_focus(&self) -> bool;
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum State {
Kept,
Returned,
Ignored,
}
impl Focus for iced::text_input::State {
fn focus(&mut self, _direction: Direction) -> State {
if self.is_focused() {
self.unfocus();
State::Returned
} else {
self.focus();
State::Kept
}
}
fn has_focus(&self) -> bool {
self.is_focused()
}
}
impl<T> Focus for Vec<T>
where
T: Focus,
{
fn focus(&mut self, direction: Direction) -> State {
self.as_mut_slice().focus(direction)
}
fn has_focus(&self) -> bool {
self.iter().any(|t| t.has_focus())
}
}
impl<T, const N: usize> Focus for [T; N]
where
T: Focus,
{
fn focus(&mut self, direction: Direction) -> State {
self[..].focus(direction)
}
fn has_focus(&self) -> bool {
self[..].has_focus()
}
}
impl<T: Focus> Focus for Box<T> {
fn focus(&mut self, direction: Direction) -> State {
self.as_mut().focus(direction)
}
fn has_focus(&self) -> bool {
self.as_ref().has_focus()
}
}
impl Focus for Box<&mut dyn Focus> {
fn focus(&mut self, direction: Direction) -> State {
self.as_mut().focus(direction)
}
fn has_focus(&self) -> bool {
self.as_ref().has_focus()
}
}
impl<T: Focus> Focus for [T] {
fn focus(&mut self, direction: Direction) -> State {
if self.is_empty() {
return State::Ignored;
}
if let Some((index, _)) = self.iter().enumerate().find(|(_i, e)| e.has_focus()) {
let state = self
.get_mut(index)
.map_or(State::Ignored, |element| element.focus(direction));
if state != State::Returned {
return state;
}
let is_at_bound = match direction {
Direction::Forwards => index == self.len() - 1,
Direction::Backwards => index == 0,
};
if is_at_bound {
return State::Returned;
}
match direction {
Direction::Forwards => {
self[index + 1..]
.iter_mut()
.find_map(|e| match e.focus(direction) {
State::Kept => Some(State::Kept),
State::Returned | State::Ignored => None,
})
}
Direction::Backwards => {
self[..index]
.iter_mut()
.rev()
.find_map(|e| match e.focus(direction) {
State::Kept => Some(State::Kept),
State::Returned | State::Ignored => None,
})
}
}
.unwrap_or(State::Returned)
} else {
match direction {
Direction::Forwards => self[..].iter_mut().find_map(|e| match e.focus(direction) {
State::Kept => Some(State::Kept),
State::Returned | State::Ignored => None,
}),
Direction::Backwards => {
self[..]
.iter_mut()
.rev()
.find_map(|e| match e.focus(direction) {
State::Kept => Some(State::Kept),
State::Returned | State::Ignored => None,
})
}
}
.unwrap_or(State::Ignored)
}
}
fn has_focus(&self) -> bool {
self.iter().any(|t| t.has_focus())
}
}
impl<T: Focus> Focus for Option<T> {
fn focus(&mut self, direction: Direction) -> State {
self.as_mut().map_or(State::Ignored, |t| t.focus(direction))
}
fn has_focus(&self) -> bool {
self.as_ref().map_or(false, |t| t.has_focus())
}
}
impl Focus for Option<&mut dyn Focus> {
fn focus(&mut self, direction: Direction) -> State {
self.as_mut().map_or(State::Ignored, |t| t.focus(direction))
}
fn has_focus(&self) -> bool {
self.as_ref().map_or(false, |t| t.has_focus())
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Direction {
Forwards,
Backwards,
}