use super::{normalize_shortcut, Action, ActionBinding, ActionHostKind};
use crate::compat::HashMap;
use crate::core::ObjectId;
use crate::shortcut::Shortcut;
use core::fmt;
pub struct ActionManager {
actions: HashMap<String, Action>,
shortcut_to_action: HashMap<String, String>,
bindings: Vec<ActionBinding>,
}
impl fmt::Debug for ActionManager {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ActionManager")
.field("actions", &self.actions.keys())
.field("shortcut_to_action", &self.shortcut_to_action)
.field("bindings", &self.bindings)
.finish()
}
}
impl ActionManager {
pub fn new() -> Self {
Self { actions: HashMap::new(), shortcut_to_action: HashMap::new(), bindings: Vec::new() }
}
pub fn register_action(&mut self, id: impl Into<String>, text: impl Into<String>) -> bool {
let id = id.into();
if self.actions.contains_key(&id) {
return false;
}
self.actions.insert(id.clone(), Action::new(id, text));
true
}
pub fn action(&self, id: &str) -> Option<&Action> {
self.actions.get(id)
}
pub fn action_mut(&mut self, id: &str) -> Option<&mut Action> {
self.actions.get_mut(id)
}
pub fn set_action_enabled(&mut self, id: &str, enabled: bool) -> bool {
let Some(action) = self.actions.get_mut(id) else {
return false;
};
action.set_enabled(enabled);
true
}
pub fn bind_shortcut(
&mut self,
shortcut: impl Into<String>,
action_id: impl Into<String>,
) -> bool {
let action_id = action_id.into();
if !self.actions.contains_key(&action_id) {
return false;
}
self.shortcut_to_action.insert(normalize_shortcut(&shortcut.into()), action_id);
true
}
pub fn bind_shortcut_type(
&mut self,
shortcut: &Shortcut,
action_id: impl Into<String>,
) -> bool {
let action_id = action_id.into();
if !self.actions.contains_key(&action_id) {
return false;
}
self.shortcut_to_action.insert(shortcut.to_string().to_lowercase(), action_id);
true
}
pub fn trigger_shortcut(&mut self, shortcut: &str) -> bool {
let Some(action_id) = self.shortcut_to_action.get(&normalize_shortcut(shortcut)) else {
return false;
};
self.actions.get_mut(action_id).map(|action| action.trigger()).unwrap_or(false)
}
pub fn trigger_action(&mut self, action_id: &str) -> bool {
self.actions.get_mut(action_id).map(|action| action.trigger()).unwrap_or(false)
}
pub fn bind_action_to_menu(&mut self, action_id: impl Into<String>, menu_id: ObjectId) -> bool {
self.bind_action(action_id.into(), menu_id, ActionHostKind::Menu)
}
pub fn bind_action_to_toolbar(
&mut self,
action_id: impl Into<String>,
toolbar_id: ObjectId,
) -> bool {
self.bind_action(action_id.into(), toolbar_id, ActionHostKind::ToolBar)
}
pub fn bind_action_to_button(
&mut self,
action_id: impl Into<String>,
button_id: ObjectId,
) -> bool {
self.bind_action(action_id.into(), button_id, ActionHostKind::Button)
}
pub fn bindings_for_host(&self, host_id: ObjectId) -> Vec<&ActionBinding> {
self.bindings.iter().filter(|binding| binding.host_id == host_id).collect()
}
fn bind_action(&mut self, action_id: String, host_id: ObjectId, kind: ActionHostKind) -> bool {
if !self.actions.contains_key(&action_id) {
return false;
}
self.bindings.push(ActionBinding { action_id, host_id, kind });
true
}
}
impl Default for ActionManager {
fn default() -> Self {
Self::new()
}
}