use core::ops::{BitOr, BitOrAssign};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct Sense(u8);
impl Sense {
pub const HOVER: Self = Self(1 << 0);
pub const CLICK: Self = Self(1 << 1);
pub const DRAG: Self = Self(1 << 2);
pub const FOCUSABLE: Self = Self(1 << 3);
pub const SCROLL: Self = Self(1 << 4);
pub const SECONDARY_CLICK: Self = Self(1 << 5);
pub const NONE: Self = Self(0);
#[must_use]
pub const fn click() -> Self {
Self(Self::HOVER.0 | Self::CLICK.0 | Self::FOCUSABLE.0)
}
#[must_use]
pub const fn drag() -> Self {
Self(Self::click().0 | Self::DRAG.0)
}
#[must_use]
pub const fn hover() -> Self {
Self::HOVER
}
#[must_use]
pub const fn scroll() -> Self {
Self(Self::HOVER.0 | Self::SCROLL.0)
}
#[must_use]
pub const fn secondary_click() -> Self {
Self(Self::HOVER.0 | Self::SECONDARY_CLICK.0)
}
#[must_use]
pub const fn contains(self, other: Self) -> bool {
(self.0 & other.0) == other.0
}
#[must_use]
pub const fn wants_pointer(self) -> bool {
self.0
& (Self::HOVER.0
| Self::CLICK.0
| Self::DRAG.0
| Self::SCROLL.0
| Self::SECONDARY_CLICK.0)
!= 0
}
}
impl BitOr for Sense {
type Output = Self;
fn bitor(self, rhs: Self) -> Self {
Self(self.0 | rhs.0)
}
}
impl BitOrAssign for Sense {
fn bitor_assign(&mut self, rhs: Self) {
self.0 |= rhs.0;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn contains_checks_all_bits() {
let s = Sense::HOVER | Sense::FOCUSABLE;
assert!(s.contains(Sense::HOVER));
assert!(s.contains(Sense::FOCUSABLE));
assert!(!s.contains(Sense::CLICK));
assert!(s.contains(Sense::NONE)); }
#[test]
fn constructors_match_their_documented_bit_combinations() {
assert_eq!(
Sense::click(),
Sense::HOVER | Sense::CLICK | Sense::FOCUSABLE
);
assert_eq!(Sense::drag(), Sense::click() | Sense::DRAG);
assert_eq!(Sense::hover(), Sense::HOVER);
assert_eq!(Sense::scroll(), Sense::HOVER | Sense::SCROLL);
}
#[test]
fn wants_pointer_ignores_focusable() {
assert!(!Sense::FOCUSABLE.wants_pointer());
assert!(Sense::HOVER.wants_pointer());
assert!(Sense::CLICK.wants_pointer());
assert!(Sense::DRAG.wants_pointer());
assert!(Sense::SCROLL.wants_pointer());
assert!(!Sense::NONE.wants_pointer());
}
#[test]
fn default_is_none() {
assert_eq!(Sense::default(), Sense::NONE);
}
}