use crate::prelude::*;
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct KeyBinding {
pub key: egui::Key,
pub modifiers: egui::Modifiers,
}
impl KeyBinding {
pub fn new(key: egui::Key) -> Self {
Self {
key,
modifiers: egui::Modifiers::NONE,
}
}
pub fn ctrl(key: egui::Key) -> Self {
Self {
key,
modifiers: egui::Modifiers::CTRL,
}
}
pub fn shift(key: egui::Key) -> Self {
Self {
key,
modifiers: egui::Modifiers::SHIFT,
}
}
pub fn ctrl_shift(key: egui::Key) -> Self {
Self {
key,
modifiers: egui::Modifiers {
ctrl: true,
shift: true,
..Default::default()
},
}
}
pub fn alt(key: egui::Key) -> Self {
Self {
key,
modifiers: egui::Modifiers::ALT,
}
}
pub fn display_name(&self) -> String {
let mut parts = Vec::new();
if self.modifiers.ctrl {
parts.push("Ctrl");
}
if self.modifiers.shift {
parts.push("Shift");
}
if self.modifiers.alt {
parts.push("Alt");
}
parts.push(key_display_name(self.key));
parts.join("+")
}
pub fn is_pressed(&self, ui_context: &egui::Context) -> bool {
ui_context.input(|input| {
input.key_pressed(self.key) && input.modifiers.matches_exact(self.modifiers)
})
}
}
pub struct ShortcutEntry {
pub name: String,
pub binding: KeyBinding,
pub action: Box<dyn FnMut() + Send>,
}
pub struct ShortcutManager {
shortcuts: Vec<ShortcutEntry>,
}
impl ShortcutManager {
pub fn new() -> Self {
Self {
shortcuts: Vec::new(),
}
}
pub fn register(
&mut self,
name: impl Into<String>,
binding: KeyBinding,
action: impl FnMut() + Send + 'static,
) {
self.shortcuts.push(ShortcutEntry {
name: name.into(),
binding,
action: Box::new(action),
});
}
pub fn process(&mut self, ui_context: &egui::Context) {
for entry in &mut self.shortcuts {
if entry.binding.is_pressed(ui_context) {
(entry.action)();
}
}
}
pub fn shortcuts(&self) -> &[ShortcutEntry] {
&self.shortcuts
}
}
impl Default for ShortcutManager {
fn default() -> Self {
Self::new()
}
}
fn key_display_name(key: egui::Key) -> &'static str {
match key {
egui::Key::A => "A",
egui::Key::B => "B",
egui::Key::C => "C",
egui::Key::D => "D",
egui::Key::E => "E",
egui::Key::F => "F",
egui::Key::G => "G",
egui::Key::H => "H",
egui::Key::I => "I",
egui::Key::J => "J",
egui::Key::K => "K",
egui::Key::L => "L",
egui::Key::M => "M",
egui::Key::N => "N",
egui::Key::O => "O",
egui::Key::P => "P",
egui::Key::Q => "Q",
egui::Key::R => "R",
egui::Key::S => "S",
egui::Key::T => "T",
egui::Key::U => "U",
egui::Key::V => "V",
egui::Key::W => "W",
egui::Key::X => "X",
egui::Key::Y => "Y",
egui::Key::Z => "Z",
egui::Key::Num0 => "0",
egui::Key::Num1 => "1",
egui::Key::Num2 => "2",
egui::Key::Num3 => "3",
egui::Key::Num4 => "4",
egui::Key::Num5 => "5",
egui::Key::Num6 => "6",
egui::Key::Num7 => "7",
egui::Key::Num8 => "8",
egui::Key::Num9 => "9",
egui::Key::Escape => "Esc",
egui::Key::Tab => "Tab",
egui::Key::Space => "Space",
egui::Key::Enter => "Enter",
egui::Key::Backspace => "Backspace",
egui::Key::Delete => "Delete",
egui::Key::Home => "Home",
egui::Key::End => "End",
egui::Key::PageUp => "PageUp",
egui::Key::PageDown => "PageDown",
egui::Key::ArrowUp => "Up",
egui::Key::ArrowDown => "Down",
egui::Key::ArrowLeft => "Left",
egui::Key::ArrowRight => "Right",
egui::Key::F1 => "F1",
egui::Key::F2 => "F2",
egui::Key::F3 => "F3",
egui::Key::F4 => "F4",
egui::Key::F5 => "F5",
egui::Key::F6 => "F6",
egui::Key::F7 => "F7",
egui::Key::F8 => "F8",
egui::Key::F9 => "F9",
egui::Key::F10 => "F10",
egui::Key::F11 => "F11",
egui::Key::F12 => "F12",
_ => "?",
}
}