use std::fmt;
use std::ops::Deref;
use std::sync::Arc;
use serde::{Deserialize, Serialize};
use crate::action::Action;
use crate::provider::Provider;
use crate::role::Role;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ElementData {
pub role: Role,
pub name: Option<String>,
pub value: Option<String>,
pub description: Option<String>,
pub bounds: Option<Rect>,
pub actions: Vec<Action>,
pub states: StateSet,
pub numeric_value: Option<f64>,
pub min_value: Option<f64>,
pub max_value: Option<f64>,
pub stable_id: Option<String>,
pub pid: Option<u32>,
pub raw: RawPlatformData,
#[serde(skip, default)]
pub handle: u64,
}
#[derive(Clone)]
pub struct Element {
data: ElementData,
provider: Arc<dyn Provider>,
}
impl Deref for Element {
type Target = ElementData;
fn deref(&self) -> &ElementData {
&self.data
}
}
impl fmt::Debug for Element {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.data, f)
}
}
impl fmt::Display for Element {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let name_part = self
.data
.name
.as_ref()
.map(|n| format!(" \"{}\"", n))
.unwrap_or_default();
let value_part = self
.data
.value
.as_ref()
.map(|v| format!(" value=\"{}\"", v))
.unwrap_or_default();
write!(
f,
"{}{}{}",
self.data.role.to_snake_case(),
name_part,
value_part,
)
}
}
impl Serialize for Element {
fn serialize<S: serde::Serializer>(
&self,
serializer: S,
) -> std::result::Result<S::Ok, S::Error> {
self.data.serialize(serializer)
}
}
impl Element {
pub fn new(data: ElementData, provider: Arc<dyn Provider>) -> Self {
Self { data, provider }
}
pub fn data(&self) -> &ElementData {
&self.data
}
pub fn provider(&self) -> &Arc<dyn Provider> {
&self.provider
}
pub fn children(&self) -> crate::error::Result<Vec<Element>> {
let children = self.provider.get_children(Some(&self.data))?;
Ok(children
.into_iter()
.map(|d| Element::new(d, Arc::clone(&self.provider)))
.collect())
}
pub fn parent(&self) -> crate::error::Result<Option<Element>> {
let parent = self.provider.get_parent(&self.data)?;
Ok(parent.map(|d| Element::new(d, Arc::clone(&self.provider))))
}
pub fn pid(&self) -> Option<u32> {
self.data.pid
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct StateSet {
pub enabled: bool,
pub visible: bool,
pub focused: bool,
pub checked: Option<Toggled>,
pub selected: bool,
pub expanded: Option<bool>,
pub editable: bool,
pub focusable: bool,
pub modal: bool,
pub required: bool,
pub busy: bool,
}
impl Default for StateSet {
fn default() -> Self {
Self {
enabled: true,
visible: true,
focused: false,
checked: None,
selected: false,
expanded: None,
editable: false,
focusable: false,
modal: false,
required: false,
busy: false,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Toggled {
Off,
On,
Mixed,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Rect {
pub x: i32,
pub y: i32,
pub width: u32,
pub height: u32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum RawPlatformData {
MacOS {
ax_role: String,
ax_subrole: Option<String>,
ax_identifier: Option<String>,
},
Windows {
control_type_id: i32,
automation_id: Option<String>,
class_name: Option<String>,
},
Linux {
atspi_role: String,
bus_name: String,
object_path: String,
},
Synthetic,
}