xloop_types 0.1.1

core types for xloop.
Documentation
//! Modifier key data.
//!
//! Modifier keys like Shift and Control alter the character value
//! and are used in keyboard shortcuts.
//!
//! Use the constants to match for combinations of the modifier keys.

/// Pressed modifier keys.
///
/// Specification:
/// <https://www.w3.org/TR/uievents-key/#keys-modifier>
#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Metas(u32);

impl Metas {
	/// Return `true` if a shift key is pressed.
	pub fn shift(&self) -> bool {
		self.contains(Metas::SHIFT)
	}

	/// Return `true` if a control key is pressed.
	pub fn ctrl(&self) -> bool {
		self.contains(Metas::CONTROL)
	}

	/// Return `true` if an alt key is pressed.
	pub fn alt(&self) -> bool {
		self.contains(Metas::ALT)
	}

	/// Return `true` if a meta key is pressed.
	pub fn meta(&self) -> bool {
		self.contains(Metas::META)
	}
}

// remove bitflags dep
impl Metas {
	pub const EMPTY: Self = Self::from_bits_retain(0);
	pub const ALL: Self = Self::all();

	pub const ALT: Self = Self::from_bits_retain(0x01);
	pub const ALT_GRAPH: Self = Self::from_bits_retain(0x2);
	pub const CAPS_LOCK: Self = Self::from_bits_retain(0x4);
	pub const CONTROL: Self = Self::from_bits_retain(0x8);
	pub const FN: Self = Self::from_bits_retain(0x10);
	pub const FN_LOCK: Self = Self::from_bits_retain(0x20);
	pub const META: Self = Self::from_bits_retain(0x40);
	pub const NUM_LOCK: Self = Self::from_bits_retain(0x80);
	pub const SCROLL_LOCK: Self = Self::from_bits_retain(0x100);
	pub const SHIFT: Self = Self::from_bits_retain(0x200);
	pub const SYMBOL: Self = Self::from_bits_retain(0x400);
	pub const SYMBOL_LOCK: Self = Self::from_bits_retain(0x800);
	pub const HYPER: Self = Self::from_bits_retain(0x1000);
	pub const SUPER: Self = Self::from_bits_retain(0x2000);
}

impl Metas {
	#[inline]
	pub const fn is_empty(&self) -> bool {
		self.0 == 0
	}
	#[inline]
	pub const fn bits(&self) -> u32 {
		self.0
	}
	#[inline]
	pub const fn all() -> Self {
		Self::from_bits_retain(
			Self::ALT.0
				| Self::ALT_GRAPH.0
				| Self::CAPS_LOCK.0
				| Self::CONTROL.0
				| Self::FN.0 | Self::FN_LOCK.0
				| Self::META.0 | Self::NUM_LOCK.0
				| Self::SCROLL_LOCK.0
				| Self::SHIFT.0 | Self::SYMBOL.0
				| Self::SYMBOL_LOCK.0
				| Self::HYPER.0 | Self::SUPER.0,
		)
	}
	#[inline]
	pub const fn from_bits_retain(bits: u32) -> Self {
		Self(bits)
	}
	#[inline]
	pub const fn from_bits_truncate(bits: u32) -> Self {
		let bits = bits;
		{
			Self(bits & Self::all().bits())
		}
	}
	#[inline]
	pub const fn contains(&self, other: Self) -> bool {
		let f = self;
		let other = other;
		{
			f.bits() & other.bits() == other.bits()
		}
	}
	#[inline]
	pub fn insert(&mut self, other: Self) {
		*self = Self::from_bits_retain(self.bits()).union(other);
	}
	#[inline]
	pub fn remove(&mut self, other: Self) {
		*self = Self::from_bits_retain(self.bits()).difference(other);
	}
	#[inline]
	pub fn toggle(&mut self, other: Self) {
		*self = Self::from_bits_retain(self.bits()).symmetric_difference(other);
	}
	#[inline]
	pub fn set(&mut self, other: Self, value: bool) {
		if value {
			self.insert(other);
		} else {
			self.remove(other);
		}
	}
	#[inline]
	#[must_use]
	pub const fn intersection(self, other: Self) -> Self {
		Self::from_bits_retain(self.bits() & other.bits())
	}
	#[inline]
	#[must_use]
	pub const fn union(self, other: Self) -> Self {
		Self::from_bits_retain(self.bits() | other.bits())
	}
	#[inline]
	#[must_use]
	pub const fn difference(self, other: Self) -> Self {
		Self::from_bits_retain(self.bits() & !other.bits())
	}
	#[inline]
	#[must_use]
	pub const fn symmetric_difference(self, other: Self) -> Self {
		Self::from_bits_retain(self.bits() ^ other.bits())
	}
	#[inline]
	#[must_use]
	pub const fn complement(self) -> Self {
		Self::from_bits_truncate(!self.bits())
	}
	#[inline]
	pub fn from_name(name: &str) -> Option<Self> {
		if name == "ALT" {
			return Self::ALT.into();
		}
		if name == "ALT_GRAPH" {
			return Self::ALT_GRAPH.into();
		}
		if name == "CAPS_LOCK" {
			return Self::CAPS_LOCK.into();
		}
		if name == "CONTROL" {
			return Self::CONTROL.into();
		}
		if name == "FN" {
			return Self::FN.into();
		}
		if name == "FN_LOCK" {
			return Self::FN_LOCK.into();
		}
		if name == "META" {
			return Self::META.into();
		}
		if name == "NUM_LOCK" {
			return Self::NUM_LOCK.into();
		}
		if name == "SCROLL_LOCK" {
			return Self::SCROLL_LOCK.into();
		}
		if name == "SHIFT" {
			return Self::SHIFT.into();
		}
		if name == "SYMBOL" {
			return Self::SYMBOL.into();
		}
		if name == "SYMBOL_LOCK" {
			return Self::SYMBOL_LOCK.into();
		}
		if name == "HYPER" {
			return Self::HYPER.into();
		}
		if name == "SUPER" {
			return Self::SUPER.into();
		}
		None
	}
}
impl std::fmt::Debug for Metas {
	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
		let mut f = f.debug_tuple("");
		if self.contains(Metas::ALT) {
			f.field(&"ALT");
		}
		if self.contains(Metas::ALT_GRAPH) {
			f.field(&"ALT_GRAPH");
		}
		if self.contains(Metas::CAPS_LOCK) {
			f.field(&"CAPS_LOCK");
		}
		if self.contains(Metas::CONTROL) {
			f.field(&"CONTROL");
		}
		if self.contains(Metas::FN) {
			f.field(&"FN");
		}
		if self.contains(Metas::FN_LOCK) {
			f.field(&"FN_LOCK");
		}
		if self.contains(Metas::META) {
			f.field(&"META");
		}
		if self.contains(Metas::NUM_LOCK) {
			f.field(&"NUM_LOCK");
		}
		if self.contains(Metas::SCROLL_LOCK) {
			f.field(&"SCROLL_LOCK");
		}
		if self.contains(Metas::SHIFT) {
			f.field(&"SHIFT");
		}
		if self.contains(Metas::SYMBOL) {
			f.field(&"SYMBOL");
		}
		if self.contains(Metas::SYMBOL_LOCK) {
			f.field(&"SYMBOL_LOCK");
		}
		if self.contains(Metas::HYPER) {
			f.field(&"HYPER");
		}
		if self.contains(Metas::SUPER) {
			f.field(&"SUPER");
		}
		f.finish()
	}
}
impl core::ops::BitOr for Metas {
	type Output = Self;
	#[inline]
	fn bitor(self, other: Metas) -> Self {
		self.union(other)
	}
}
impl core::ops::BitOrAssign for Metas {
	#[inline]
	fn bitor_assign(&mut self, other: Self) {
		self.insert(other);
	}
}
impl core::ops::BitXor for Metas {
	type Output = Self;
	#[inline]
	fn bitxor(self, other: Self) -> Self {
		self.symmetric_difference(other)
	}
}
impl core::ops::BitXorAssign for Metas {
	#[inline]
	fn bitxor_assign(&mut self, other: Self) {
		self.toggle(other);
	}
}
impl core::ops::BitAnd for Metas {
	type Output = Self;
	#[inline]
	fn bitand(self, other: Self) -> Self {
		self.intersection(other)
	}
}
impl core::ops::BitAndAssign for Metas {
	#[inline]
	fn bitand_assign(&mut self, other: Self) {
		*self = Self::from_bits_retain(self.bits()).intersection(other);
	}
}
impl core::ops::Sub for Metas {
	type Output = Self;
	#[inline]
	fn sub(self, other: Self) -> Self {
		self.difference(other)
	}
}
impl core::ops::SubAssign for Metas {
	#[inline]
	fn sub_assign(&mut self, other: Self) {
		self.remove(other);
	}
}
impl core::ops::Not for Metas {
	type Output = Self;
	#[inline]
	fn not(self) -> Self {
		self.complement()
	}
}