use egui::{InputState, Key, KeyboardShortcut, ModifierNames, Modifiers, PointerButton};
pub trait Bind: Clone {
fn set(&mut self, keyboard: Option<KeyboardShortcut>, pointer: Option<PointerButton>);
fn format(&self, names: &ModifierNames<'_>, is_mac: bool) -> String;
fn pressed(&self, input: &mut InputState) -> bool;
}
impl Bind for KeyboardShortcut {
fn set(&mut self, keyboard: Option<KeyboardShortcut>, _pointer: Option<PointerButton>) {
if let Some(keyboard) = keyboard {
*self = keyboard
}
}
fn format(&self, names: &ModifierNames<'_>, is_mac: bool) -> String {
self.format(names, is_mac)
}
fn pressed(&self, input: &mut InputState) -> bool {
input.consume_shortcut(self)
}
}
impl Bind for Option<KeyboardShortcut> {
fn set(&mut self, keyboard: Option<KeyboardShortcut>, _pointer: Option<PointerButton>) {
*self = keyboard;
}
fn format(&self, names: &ModifierNames<'_>, is_mac: bool) -> String {
self.as_ref().map_or_else(
|| "None".to_string(),
|shortcut| shortcut.format(names, is_mac),
)
}
fn pressed(&self, input: &mut InputState) -> bool {
if let Some(shortcut) = self {
input.consume_shortcut(shortcut)
} else {
false
}
}
}
impl Bind for Key {
fn set(&mut self, keyboard: Option<KeyboardShortcut>, _pointer: Option<PointerButton>) {
if let Some(keyboard) = keyboard {
*self = keyboard.logical_key
}
}
fn format(&self, _names: &ModifierNames<'_>, _is_mac: bool) -> String {
self.name().to_string()
}
fn pressed(&self, input: &mut InputState) -> bool {
input.key_pressed(*self)
}
}
impl Bind for Option<Key> {
fn set(&mut self, keyboard: Option<KeyboardShortcut>, _pointer: Option<PointerButton>) {
if let Some(keyboard) = keyboard {
*self = Some(keyboard.logical_key)
}
}
fn format(&self, _names: &ModifierNames<'_>, _is_mac: bool) -> String {
self.as_ref()
.map_or_else(|| "None".to_string(), |key| key.name().to_string())
}
fn pressed(&self, input: &mut InputState) -> bool {
if let Some(key) = self {
input.key_pressed(*key)
} else {
false
}
}
}
impl Bind for PointerButton {
fn set(&mut self, _keyboard: Option<KeyboardShortcut>, pointer: Option<PointerButton>) {
if let Some(pointer) = pointer {
*self = pointer
}
}
fn format(&self, _names: &ModifierNames<'_>, _is_mac: bool) -> String {
format!("{:?}", self)
}
fn pressed(&self, input: &mut InputState) -> bool {
input.pointer.button_pressed(*self)
}
}
impl Bind for Option<PointerButton> {
fn set(&mut self, _keyboard: Option<KeyboardShortcut>, pointer: Option<PointerButton>) {
*self = pointer;
}
fn format(&self, _names: &ModifierNames<'_>, _is_mac: bool) -> String {
self.as_ref()
.map_or_else(|| "None".to_string(), |button| format!("{:?}", button))
}
fn pressed(&self, input: &mut InputState) -> bool {
if let Some(button) = self {
input.pointer.button_pressed(*button)
} else {
false
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
struct KeyboardShortcutWrapper {
pub modifiers: Modifiers,
pub key: Key,
}
impl From<KeyboardShortcutWrapper> for KeyboardShortcut {
fn from(value: KeyboardShortcutWrapper) -> Self {
Self {
modifiers: value.modifiers,
logical_key: value.key,
}
}
}
impl From<KeyboardShortcut> for KeyboardShortcutWrapper {
fn from(value: KeyboardShortcut) -> Self {
Self {
modifiers: value.modifiers,
key: value.logical_key,
}
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Shortcut {
keyboard: Option<KeyboardShortcutWrapper>,
pointer: Option<PointerButton>,
}
impl Shortcut {
pub const NONE: Self = Self {
keyboard: None,
pointer: None,
};
pub fn new(keyboard: Option<KeyboardShortcut>, pointer: Option<PointerButton>) -> Self {
Self {
keyboard: keyboard.map(|kb| kb.into()),
pointer,
}
}
#[inline]
pub fn keyboard(&self) -> Option<KeyboardShortcut> {
self.keyboard.map(|kb| kb.into())
}
#[inline]
pub const fn pointer(&self) -> Option<PointerButton> {
self.pointer
}
}
impl Bind for Shortcut {
fn set(&mut self, keyboard: Option<KeyboardShortcut>, pointer: Option<PointerButton>) {
self.keyboard = keyboard.map(|kb| kb.into());
self.pointer = pointer;
}
fn format(&self, names: &ModifierNames<'_>, is_mac: bool) -> String {
let mut string = self.keyboard.map_or_else(
|| String::with_capacity(9),
|kb| Into::<KeyboardShortcut>::into(kb).format(names, is_mac),
);
if let Some(pointer) = self.pointer {
if !string.is_empty() {
string.push('+');
}
string.push_str(&pointer.format(names, is_mac));
}
if string.is_empty() {
string.push_str("None");
}
string
}
fn pressed(&self, input: &mut InputState) -> bool {
let mut pressed = false;
if let Some(kb) = &self.keyboard {
pressed = input.consume_shortcut(&(*kb).into());
}
if let Some(button) = self.pointer {
if self.keyboard.is_none() {
return input.pointer.button_clicked(button);
}
pressed &= input.pointer.button_clicked(button);
}
pressed
}
}
impl From<Shortcut> for Option<KeyboardShortcut> {
fn from(value: Shortcut) -> Self {
value.keyboard.map(|kb| kb.into())
}
}
impl From<Shortcut> for Option<PointerButton> {
fn from(value: Shortcut) -> Self {
value.pointer
}
}