use super::{Key, Modifiers, Shortcut, ShortcutEntry};
use crate::compat::HashMap;
use crate::signal::Signal1;
pub struct ShortcutManager {
shortcuts: HashMap<Shortcut, String>,
entries: HashMap<String, ShortcutEntry>,
pub shortcut_triggered: Signal1<String>,
pub conflict_detected: Signal1<(Shortcut, String, String)>,
}
impl ShortcutManager {
pub fn new() -> Self {
Self {
shortcuts: HashMap::new(),
entries: HashMap::new(),
shortcut_triggered: Signal1::new(),
conflict_detected: Signal1::new(),
}
}
pub fn register(
&mut self,
action_id: impl Into<String>,
shortcut: Shortcut,
description: impl Into<String>,
) -> bool {
let action_id = action_id.into();
let description = description.into();
if let Some(existing_action) = self.shortcuts.get(&shortcut) {
if existing_action != &action_id {
self.conflict_detected.emit((
shortcut.clone(),
action_id.clone(),
existing_action.clone(),
));
return false;
}
}
if let Some(entry) = self.entries.get(&action_id) {
self.shortcuts.remove(&entry.shortcut);
}
let entry = ShortcutEntry {
action_id: action_id.clone(),
description,
shortcut: shortcut.clone(),
enabled: true,
};
self.shortcuts.insert(shortcut, action_id.clone());
self.entries.insert(action_id, entry);
true
}
pub fn unregister(&mut self, action_id: &str) -> bool {
if let Some(entry) = self.entries.remove(action_id) {
self.shortcuts.remove(&entry.shortcut);
true
} else {
false
}
}
pub fn unregister_shortcut(&mut self, shortcut: &Shortcut) -> bool {
if let Some(action_id) = self.shortcuts.remove(shortcut) {
self.entries.remove(&action_id);
true
} else {
false
}
}
pub fn handle_key_event(&mut self, key: Key, modifiers: Modifiers) -> bool {
let shortcut = Shortcut::new(key, modifiers);
if let Some(action_id) = self.shortcuts.get(&shortcut) {
if let Some(entry) = self.entries.get(action_id) {
if entry.enabled {
self.shortcut_triggered.emit(action_id.clone());
return true;
}
}
}
false
}
pub fn enable(&mut self, action_id: &str) -> bool {
if let Some(entry) = self.entries.get_mut(action_id) {
entry.enabled = true;
true
} else {
false
}
}
pub fn disable(&mut self, action_id: &str) -> bool {
if let Some(entry) = self.entries.get_mut(action_id) {
entry.enabled = false;
true
} else {
false
}
}
pub fn get_shortcut(&self, action_id: &str) -> Option<&Shortcut> {
self.entries.get(action_id).map(|e| &e.shortcut)
}
pub fn get_action(&self, shortcut: &Shortcut) -> Option<&String> {
self.shortcuts.get(shortcut)
}
pub fn all_shortcuts(&self) -> &HashMap<Shortcut, String> {
&self.shortcuts
}
pub fn all_entries(&self) -> &HashMap<String, ShortcutEntry> {
&self.entries
}
pub fn clear(&mut self) {
self.shortcuts.clear();
self.entries.clear();
}
pub fn has_shortcut(&self, shortcut: &Shortcut) -> bool {
self.shortcuts.contains_key(shortcut)
}
pub fn has_action(&self, action_id: &str) -> bool {
self.entries.contains_key(action_id)
}
pub fn find_conflicts(&self, shortcut: &Shortcut) -> Vec<&ShortcutEntry> {
self.entries.values().filter(|e| e.shortcut.conflicts_with(shortcut)).collect()
}
}
impl Default for ShortcutManager {
fn default() -> Self {
Self::new()
}
}