use serde::{Deserialize, Serialize};
use super::application_target::ApplicationTarget;
use super::category::Category;
use super::key_combo::KeyCombo;
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Action {
None,
LeftClick,
RightClick,
MiddleClick,
MouseBack,
MouseForward,
Copy,
Paste,
Cut,
Undo,
Redo,
SelectAll,
Find,
Save,
BrowserBack,
BrowserForward,
NewTab,
CloseTab,
ReopenTab,
NextTab,
PrevTab,
ReloadPage,
MissionControl,
AppExpose,
PreviousDesktop,
NextDesktop,
ShowDesktop,
LaunchpadShow,
LockScreen,
Screenshot,
CaptureRegion,
PlayPause,
NextTrack,
PrevTrack,
VolumeUp,
VolumeDown,
MuteVolume,
CycleDpiPresets,
SetDpiPreset(u8),
ToggleSmartShift,
ScrollUp,
ScrollDown,
HorizontalScrollLeft,
HorizontalScrollRight,
CustomShortcut(KeyCombo),
Sleep,
TypeText(String),
RunAppleScript(String),
RunShellCommand(String),
Workflow(Vec<WorkflowStep>),
ShowActionsRing,
OpenApplication(ApplicationTarget),
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum WorkflowStep {
TypeText(String),
PressKey(KeyCombo),
Delay {
millis: u64,
},
RunAppleScript(String),
RunShellCommand(String),
}
macro_rules! for_each_unit_action {
($callback:ident) => {
$callback! {
LeftClick "Left Click" Mouse Pointer,
RightClick "Right Click" Mouse Pointer,
MiddleClick "Middle Click" Mouse Mouse,
MouseBack "Back (Button 4)" Mouse MouseBack,
MouseForward "Forward (Button 5)" Mouse MouseForward,
Copy "Copy" Editing Copy,
Paste "Paste" Editing Paste,
Cut "Cut" Editing Cut,
Undo "Undo" Editing Undo,
Redo "Redo" Editing Redo,
SelectAll "Select All" Editing SelectAll,
Find "Find" Editing Search,
Save "Save" Editing Save,
BrowserBack "Browser Back" Browser ArrowLeft,
BrowserForward "Browser Forward" Browser ArrowRight,
NewTab "New Tab" Browser NewTab,
CloseTab "Close Tab" Browser CloseTab,
ReopenTab "Reopen Tab" Browser ReopenTab,
NextTab "Next Tab" Browser NextTab,
PrevTab "Previous Tab" Browser PreviousTab,
ReloadPage "Reload Page" Browser Reload,
MissionControl "Mission Control" Navigation Grid,
AppExpose "App Exposé" Navigation Layers,
PreviousDesktop "Previous Desktop" Navigation PreviousDesktop,
NextDesktop "Next Desktop" Navigation NextDesktop,
ShowDesktop "Show Desktop" Navigation Monitor,
LaunchpadShow "Launchpad" Navigation Applications,
None "Do Nothing" System Ban,
LockScreen "Lock Screen" System Lock,
Screenshot "Screenshot" System Camera,
CaptureRegion "Capture Region" System Camera,
Sleep "Sleep" System Monitor,
ShowActionsRing "Actions Ring" System Grid not_pickable,
PlayPause "Play / Pause" Media Play,
NextTrack "Next Track" Media NextTrack,
PrevTrack "Previous Track" Media PreviousTrack,
VolumeUp "Volume Up" Media Volume,
VolumeDown "Volume Down" Media VolumeDown,
MuteVolume "Mute" Media Mute,
CycleDpiPresets "Cycle DPI Presets" Dpi Gauge,
ToggleSmartShift "Toggle SmartShift" Dpi Refresh,
ScrollUp "Scroll Up" Scroll ArrowUp,
ScrollDown "Scroll Down" Scroll ArrowDown,
HorizontalScrollLeft "Scroll Left" Scroll ScrollLeft,
HorizontalScrollRight "Scroll Right" Scroll ScrollRight,
}
};
}
pub(super) use for_each_unit_action;
macro_rules! derive_action_core {
( $( $variant:ident $label:literal $category:ident $icon:ident $( $tag:ident )? ),* $(,)? ) => {
impl Action {
#[must_use]
pub fn label(&self) -> String {
match self {
$( Action::$variant => $label.into(), )*
Action::SetDpiPreset(i) => format!("DPI Preset {}", i + 1),
Action::CustomShortcut(combo) => combo.rendered_label(),
Action::TypeText(s) => format!("Type \"{s}\""),
Action::RunAppleScript(_) => "Run AppleScript".into(),
Action::RunShellCommand(_) => "Run Command".into(),
Action::Workflow(steps) => format!("Workflow ({} steps)", steps.len()),
Action::OpenApplication(target) => format!("Open {}", target.display_name()),
}
}
#[must_use]
pub fn category(&self) -> Category {
match self {
$( Action::$variant => Category::$category, )*
Action::CustomShortcut(_)
| Action::TypeText(_)
| Action::RunAppleScript(_)
| Action::RunShellCommand(_)
| Action::Workflow(_) => Category::Editing,
Action::SetDpiPreset(_) => Category::Dpi,
Action::OpenApplication(_) => Category::System,
}
}
#[must_use]
pub fn catalog() -> Vec<Action> {
[ $( derive_action_core!(@item $variant $( $tag )?) ),* ]
.into_iter()
.flatten()
.collect()
}
}
};
(@item $variant:ident) => {
Some(Action::$variant)
};
(@item $variant:ident not_pickable) => {
None
};
}
for_each_unit_action!(derive_action_core);