cushy/src/utils.rs
Jonathan Johnson 5e5d826267
Checkpoint
Progress on tab focus
2023-11-07 15:16:29 -08:00

124 lines
2.9 KiB
Rust

use std::ops::Deref;
use std::sync::OnceLock;
use kludgine::app::winit::event::Modifiers;
use kludgine::app::winit::keyboard::ModifiersState;
/// Invokes the provided macro with a pattern that can be matched using this
/// `macro_rules!` expression: `$($type:ident $field:tt),+`, where `$type` is an
/// identifier to use for the generic parameter and `$field` is the field index
/// inside of the tuple.
macro_rules! impl_all_tuples {
($macro_name:ident) => {
$macro_name!(T0 0);
$macro_name!(T0 0, T1 1);
$macro_name!(T0 0, T1 1, T2 2);
$macro_name!(T0 0, T1 1, T2 2, T3 3);
$macro_name!(T0 0, T1 1, T2 2, T3 3, T4 4);
$macro_name!(T0 0, T1 1, T2 2, T3 3, T4 4, T5 5);
}
}
/// Invokes a function with a clone of `self`.
pub trait WithClone: Sized {
/// The type that results from cloning.
type Cloned;
/// Maps `with` with the results of cloning `self`.
fn with_clone<R>(&self, with: impl FnOnce(Self::Cloned) -> R) -> R;
}
macro_rules! impl_with_clone {
($($name:ident $field:tt),+) => {
impl<'a, $($name: Clone,)+> WithClone for ($(&'a $name,)+)
{
type Cloned = ($($name,)+);
fn with_clone<R>(&self, with: impl FnOnce(Self::Cloned) -> R) -> R {
with(($(self.$field.clone(),)+))
}
}
};
}
impl<'a, T> WithClone for &'a T
where
T: Clone,
{
type Cloned = T;
fn with_clone<R>(&self, with: impl FnOnce(Self::Cloned) -> R) -> R {
with((*self).clone())
}
}
impl_all_tuples!(impl_with_clone);
pub trait ModifiersExt {
fn primary(&self) -> bool;
fn word_select(&self) -> bool;
fn possible_shortcut(&self) -> bool;
}
impl ModifiersExt for ModifiersState {
#[cfg(any(target_os = "macos", target_os = "ios"))]
fn primary(&self) -> bool {
self.super_key()
}
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
fn primary(&self) -> bool {
self.control_key()
}
#[cfg(any(target_os = "macos", target_os = "ios"))]
fn word_select(&self) -> bool {
self.alt_key()
}
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
fn word_select(&self) -> bool {
self.control_key()
}
fn possible_shortcut(&self) -> bool {
self.control_key() || self.alt_key() || self.super_key()
}
}
impl ModifiersExt for Modifiers {
fn primary(&self) -> bool {
self.state().primary()
}
fn word_select(&self) -> bool {
self.state().word_select()
}
fn possible_shortcut(&self) -> bool {
self.state().word_select()
}
}
pub struct Lazy<T> {
init: fn() -> T,
once: OnceLock<T>,
}
impl<T> Lazy<T> {
pub const fn new(init: fn() -> T) -> Self {
Self {
init,
once: OnceLock::new(),
}
}
}
impl<T> Deref for Lazy<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.once.get_or_init(self.init)
}
}