mod role;
pub use role::{Role, RoleSet};
use crate::event::Event;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
pub enum FocusDirection {
#[default]
Forward,
Backward,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum FocusAction {
Next,
Previous,
Focus(FocusDirection),
Blur,
Select,
Teardown,
}
impl FocusAction {
#[must_use]
pub fn into_event(self, group: FocusGroup) -> Event {
Event::Focus {
action: self,
group,
}
}
}
pub trait DefaultFocus {
fn default_first() -> Self;
fn default_last() -> Self;
}
impl DefaultFocus for () {
fn default_first() -> Self {}
fn default_last() -> Self {}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct FocusGroup(u8);
#[derive(Clone, Copy, Debug, Eq)]
pub struct FocusGroupSet(u8);
impl FocusGroup {
#[must_use]
pub const fn new(i: u8) -> Option<Self> {
if i < 8 { Some(Self(0b1 << i)) } else { None }
}
#[must_use]
pub const fn new_unchecked(i: u8) -> Self {
debug_assert!(i < 8, "Focus group index must be between 0 and 7");
Self(0b1 << i)
}
#[must_use]
pub const fn index(self) -> u8 {
self.0.trailing_zeros() as u8
}
#[must_use]
pub const fn set(self) -> FocusGroupSet {
FocusGroupSet(self.0)
}
}
impl FocusGroupSet {
#[must_use]
pub const fn new_none() -> Self {
Self(0b0000_0000)
}
#[must_use]
pub const fn new_any() -> Self {
Self(0b1111_1111)
}
#[must_use]
pub const fn contains(self, group: FocusGroup) -> bool {
(self.0 & group.0) != 0
}
}
impl core::ops::BitOr for FocusGroup {
type Output = FocusGroupSet;
fn bitor(self, rhs: Self) -> Self::Output {
FocusGroupSet(self.0 | rhs.0)
}
}
impl From<FocusGroup> for FocusGroupSet {
fn from(group: FocusGroup) -> Self {
group.set()
}
}
impl PartialEq for FocusGroupSet {
fn eq(&self, other: &Self) -> bool {
(self.0 & other.0) != 0
}
}
impl core::ops::BitOr<FocusGroup> for FocusGroupSet {
type Output = Self;
fn bitor(self, rhs: FocusGroup) -> Self::Output {
Self(self.0 | rhs.0)
}
}
impl core::ops::BitOr for FocusGroupSet {
type Output = Self;
fn bitor(self, rhs: Self) -> Self::Output {
Self(self.0 | rhs.0)
}
}
impl core::ops::BitAnd for FocusGroupSet {
type Output = Self;
fn bitand(self, rhs: Self) -> Self::Output {
Self(self.0 & rhs.0)
}
}
pub static GROUP_0: FocusGroup = FocusGroup(0b1 << 0);
pub static GROUP_1: FocusGroup = FocusGroup(0b1 << 1);
pub static GROUP_2: FocusGroup = FocusGroup(0b1 << 2);
pub static GROUP_3: FocusGroup = FocusGroup(0b1 << 3);
pub static GROUP_4: FocusGroup = FocusGroup(0b1 << 4);
pub static GROUP_5: FocusGroup = FocusGroup(0b1 << 5);
pub static GROUP_6: FocusGroup = FocusGroup(0b1 << 6);
pub static GROUP_7: FocusGroup = FocusGroup(0b1 << 7);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum BoundaryBehavior {
#[default]
Wrap,
Stop,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn group_indices() {
for i in 0..8 {
let group = FocusGroup::new(i).unwrap();
let unchecked_group = FocusGroup::new_unchecked(i);
assert_eq!(group, unchecked_group);
assert_eq!(group.index(), i);
}
}
#[test]
fn group_equals_all_groups() {
assert_eq!(FocusGroupSet::new_any(), FocusGroupSet::new_any());
for i in 0..8 {
let group = FocusGroup::new(i).unwrap();
assert_eq!(group.set(), FocusGroupSet::new_any());
}
}
}