use crate::core::ObjectId;
use crate::signal::{ConnectionHandle, GenericSignal};
use alloc::sync::Arc;
use core::fmt;
#[derive(Clone)]
pub struct Action {
pub id: String,
pub text: String,
enabled: bool,
checkable: bool,
checked: bool,
triggered: GenericSignal,
toggled: crate::signal::Signal1<bool>,
enabled_changed: crate::signal::Signal1<bool>,
}
impl fmt::Debug for Action {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Action")
.field("id", &self.id)
.field("text", &self.text)
.field("enabled", &self.enabled)
.field("checkable", &self.checkable)
.field("checked", &self.checked)
.field("triggered", &self.triggered.slot_count())
.field("toggled", &self.toggled.slot_count())
.field("enabled_changed", &self.enabled_changed.slot_count())
.finish()
}
}
impl Action {
pub fn new(id: impl Into<String>, text: impl Into<String>) -> Self {
Self {
id: id.into(),
text: text.into(),
enabled: true,
checkable: false,
checked: false,
triggered: GenericSignal::new(),
toggled: crate::signal::Signal1::new(),
enabled_changed: crate::signal::Signal1::new(),
}
}
pub fn is_enabled(&self) -> bool {
self.enabled
}
pub fn set_enabled(&mut self, enabled: bool) {
if self.enabled == enabled {
return;
}
self.enabled = enabled;
self.enabled_changed.emit(enabled);
}
pub fn is_checkable(&self) -> bool {
self.checkable
}
pub fn set_checkable(&mut self, checkable: bool) {
if self.checkable == checkable {
return;
}
self.checkable = checkable;
if !checkable {
self.set_checked(false);
}
}
pub fn is_checked(&self) -> bool {
self.checked
}
pub fn set_checked(&mut self, checked: bool) {
let normalized = if self.checkable { checked } else { false };
if self.checked == normalized {
return;
}
self.checked = normalized;
self.toggled.emit(self.checked);
}
pub fn connect_triggered<F>(&self, slot: F) -> ConnectionHandle
where
F: FnMut() + Send + Sync + 'static,
{
self.triggered.connect(slot)
}
pub fn connect_toggled<F>(&self, slot: F) -> ConnectionHandle
where
F: FnMut(Arc<bool>) + Send + Sync + 'static,
{
self.toggled.connect(slot)
}
pub fn connect_enabled_changed<F>(&self, slot: F) -> ConnectionHandle
where
F: FnMut(Arc<bool>) + Send + Sync + 'static,
{
self.enabled_changed.connect(slot)
}
pub fn trigger(&mut self) -> bool {
if !self.enabled {
return false;
}
if self.checkable {
self.set_checked(!self.checked);
}
self.triggered.emit();
true
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ActionHostKind {
Menu,
Button,
ToolBar,
}
#[derive(Debug, Clone)]
pub struct ActionBinding {
pub action_id: String,
pub host_id: ObjectId,
pub kind: ActionHostKind,
}
pub(crate) fn normalize_shortcut(shortcut: &str) -> String {
shortcut
.split('+')
.map(|token| token.trim().to_lowercase())
.filter(|token| !token.is_empty())
.collect::<Vec<_>>()
.join("+")
}