1use std::collections::HashMap;
2use std::fmt;
3use std::ops::Deref;
4use std::sync::Arc;
5
6use serde::{Deserialize, Serialize};
7
8use crate::provider::Provider;
9use crate::role::Role;
10
11#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct ElementData {
18 pub role: Role,
20
21 pub name: Option<String>,
23
24 pub value: Option<String>,
26
27 pub description: Option<String>,
29
30 pub bounds: Option<Rect>,
32
33 pub actions: Vec<String>,
40
41 pub states: StateSet,
43
44 pub numeric_value: Option<f64>,
46
47 pub min_value: Option<f64>,
49
50 pub max_value: Option<f64>,
52
53 pub stable_id: Option<String>,
60
61 pub pid: Option<u32>,
63
64 #[serde(default)]
68 pub attributes: HashMap<String, serde_json::Value>,
69
70 pub raw: RawPlatformData,
72
73 #[serde(skip, default)]
76 pub handle: u64,
77}
78
79impl ElementData {
80 pub fn populate_attributes(&mut self) {
84 use serde_json::Value;
85 let a = &mut self.attributes;
86
87 a.insert(
88 "role".into(),
89 Value::String(self.role.to_snake_case().to_string()),
90 );
91 if let Some(ref n) = self.name {
92 a.insert("name".into(), Value::String(n.clone()));
93 }
94 if let Some(ref v) = self.value {
95 a.insert("value".into(), Value::String(v.clone()));
96 }
97 if let Some(ref d) = self.description {
98 a.insert("description".into(), Value::String(d.clone()));
99 }
100 if let Some(ref b) = self.bounds {
101 a.insert(
102 "bounds".into(),
103 serde_json::json!({
104 "x": b.x, "y": b.y, "width": b.width, "height": b.height
105 }),
106 );
107 }
108 if let Some(nv) = self.numeric_value {
109 if let Some(n) = serde_json::Number::from_f64(nv) {
110 a.insert("numeric_value".into(), Value::Number(n));
111 }
112 }
113 if let Some(nv) = self.min_value {
114 if let Some(n) = serde_json::Number::from_f64(nv) {
115 a.insert("min_value".into(), Value::Number(n));
116 }
117 }
118 if let Some(nv) = self.max_value {
119 if let Some(n) = serde_json::Number::from_f64(nv) {
120 a.insert("max_value".into(), Value::Number(n));
121 }
122 }
123 if let Some(ref sid) = self.stable_id {
124 a.insert("stable_id".into(), Value::String(sid.clone()));
125 }
126 a.insert("enabled".into(), Value::Bool(self.states.enabled));
127 a.insert("visible".into(), Value::Bool(self.states.visible));
128 a.insert("focused".into(), Value::Bool(self.states.focused));
129 a.insert("focusable".into(), Value::Bool(self.states.focusable));
130 a.insert("selected".into(), Value::Bool(self.states.selected));
131 a.insert("editable".into(), Value::Bool(self.states.editable));
132 a.insert("modal".into(), Value::Bool(self.states.modal));
133 a.insert("required".into(), Value::Bool(self.states.required));
134 a.insert("busy".into(), Value::Bool(self.states.busy));
135 if let Some(exp) = self.states.expanded {
136 a.insert("expanded".into(), Value::Bool(exp));
137 }
138 if let Some(ref chk) = self.states.checked {
139 let s = match chk {
140 Toggled::On => "on",
141 Toggled::Off => "off",
142 Toggled::Mixed => "mixed",
143 };
144 a.insert("checked".into(), Value::String(s.into()));
145 }
146 }
147}
148
149#[derive(Clone)]
157pub struct Element {
158 data: ElementData,
159 provider: Arc<dyn Provider>,
160}
161
162impl Deref for Element {
163 type Target = ElementData;
164
165 fn deref(&self) -> &ElementData {
166 &self.data
167 }
168}
169
170impl fmt::Debug for Element {
171 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
172 fmt::Debug::fmt(&self.data, f)
173 }
174}
175
176impl fmt::Display for Element {
177 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
178 let name_part = self
179 .data
180 .name
181 .as_ref()
182 .map(|n| format!(" \"{}\"", n))
183 .unwrap_or_default();
184 let value_part = self
185 .data
186 .value
187 .as_ref()
188 .map(|v| format!(" value=\"{}\"", v))
189 .unwrap_or_default();
190 write!(
191 f,
192 "{}{}{}",
193 self.data.role.to_snake_case(),
194 name_part,
195 value_part,
196 )
197 }
198}
199
200impl Serialize for Element {
201 fn serialize<S: serde::Serializer>(
202 &self,
203 serializer: S,
204 ) -> std::result::Result<S::Ok, S::Error> {
205 self.data.serialize(serializer)
206 }
207}
208
209impl Element {
210 pub fn new(data: ElementData, provider: Arc<dyn Provider>) -> Self {
212 Self { data, provider }
213 }
214
215 pub fn data(&self) -> &ElementData {
217 &self.data
218 }
219
220 pub fn provider(&self) -> &Arc<dyn Provider> {
222 &self.provider
223 }
224
225 pub fn children(&self) -> crate::error::Result<Vec<Element>> {
229 let children = self.provider.get_children(Some(&self.data))?;
230 Ok(children
231 .into_iter()
232 .map(|d| Element::new(d, Arc::clone(&self.provider)))
233 .collect())
234 }
235
236 pub fn parent(&self) -> crate::error::Result<Option<Element>> {
240 let parent = self.provider.get_parent(&self.data)?;
241 Ok(parent.map(|d| Element::new(d, Arc::clone(&self.provider))))
242 }
243
244 pub fn pid(&self) -> Option<u32> {
246 self.data.pid
247 }
248}
249
250#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
261pub struct StateSet {
262 pub enabled: bool,
263 pub visible: bool,
264 pub focused: bool,
265 pub checked: Option<Toggled>,
267 pub selected: bool,
268 pub expanded: Option<bool>,
270 pub editable: bool,
271 pub focusable: bool,
273 pub modal: bool,
275 pub required: bool,
277 pub busy: bool,
279}
280
281impl Default for StateSet {
282 fn default() -> Self {
283 Self {
284 enabled: true,
285 visible: true,
286 focused: false,
287 checked: None,
288 selected: false,
289 expanded: None,
290 editable: false,
291 focusable: false,
292 modal: false,
293 required: false,
294 busy: false,
295 }
296 }
297}
298
299#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
301pub enum Toggled {
302 Off,
303 On,
304 Mixed,
306}
307
308#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
312pub struct Rect {
313 pub x: i32,
314 pub y: i32,
315 pub width: u32,
316 pub height: u32,
317}
318
319pub type RawPlatformData = HashMap<String, serde_json::Value>;