use serde::{Deserialize, Serialize};
use crate::element::{reader_writer_pair, ElementData};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub enum EventKind {
FocusChanged,
ValueChanged,
NameChanged,
StateChanged { flag: StateFlag, value: bool },
StructureChanged,
WindowOpened,
WindowClosed,
WindowActivated,
WindowDeactivated,
SelectionChanged,
MenuOpened,
MenuClosed,
TextChanged,
Announcement,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[non_exhaustive]
pub enum StateFlag {
Enabled,
Visible,
Focused,
Checked,
Selected,
Expanded,
Editable,
Focusable,
Modal,
Required,
Busy,
}
reader_writer_pair! {
#[derive(Debug, Clone)]
pub struct Event;
#[allow(
clippy::exhaustive_structs,
reason = "This type IS the completeness guard for events. See \
ElementParts; the same reasoning applies."
)]
#[derive(Debug, Clone)]
pub struct EventParts;
fields {
pub kind: EventKind,
pub target: Option<ElementData>,
pub app_name: String,
pub app_pid: u32,
pub timestamp: std::time::Instant,
}
}
impl Event {
pub fn new(kind: EventKind, app_name: impl Into<String>, app_pid: u32) -> Self {
Self {
kind,
target: None,
app_name: app_name.into(),
app_pid,
timestamp: std::time::Instant::now(),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[non_exhaustive]
pub enum ElementState {
Attached,
Detached,
Visible,
Hidden,
Enabled,
Disabled,
Focused,
Unfocused,
}
impl ElementState {
pub fn is_met(self, element: Option<&ElementData>) -> bool {
match self {
Self::Attached => element.is_some(),
Self::Detached => element.is_none(),
Self::Visible => element.is_some_and(|e| e.states.visible),
Self::Hidden => element.is_none() || element.is_some_and(|e| !e.states.visible),
Self::Enabled => element.is_some_and(|e| e.states.enabled),
Self::Disabled => element.is_some_and(|e| !e.states.enabled),
Self::Focused => element.is_some_and(|e| e.states.focused),
Self::Unfocused => element.is_some_and(|e| !e.states.focused),
}
}
pub fn is_absence_state(self) -> bool {
matches!(self, Self::Detached | Self::Hidden)
}
}