use std::sync::Arc;
use crate::element::{Element, ElementData};
use crate::error::{Error, Result};
use crate::event_provider::Subscription;
use crate::locator::Locator;
use crate::provider::Provider;
use crate::selector::Selector;
pub struct App {
pub name: String,
pub pid: Option<u32>,
pub data: ElementData,
provider: Arc<dyn Provider>,
}
impl App {
pub fn by_name_with(provider: Arc<dyn Provider>, name: &str) -> Result<Self> {
let selector_str = format!(r#"application[name="{}"]"#, name);
let selector = Selector::parse(&selector_str)?;
let results = provider.find_elements(None, &selector, Some(1), Some(0))?;
let data = results
.into_iter()
.next()
.ok_or(Error::SelectorNotMatched {
selector: selector_str,
})?;
Ok(Self::from_data(provider, data))
}
pub fn by_pid_with(provider: Arc<dyn Provider>, pid: u32) -> Result<Self> {
let selector_str = "application";
let selector = Selector::parse(selector_str)?;
let results = provider.find_elements(None, &selector, None, Some(0))?;
let data =
results
.into_iter()
.find(|d| d.pid == Some(pid))
.ok_or(Error::SelectorNotMatched {
selector: format!("application with pid={}", pid),
})?;
Ok(Self::from_data(provider, data))
}
pub fn list_with(provider: Arc<dyn Provider>) -> Result<Vec<Self>> {
let selector = Selector::parse("application")?;
let results = provider.find_elements(None, &selector, None, Some(0))?;
Ok(results
.into_iter()
.map(|d| Self::from_data(Arc::clone(&provider), d))
.collect())
}
fn from_data(provider: Arc<dyn Provider>, data: ElementData) -> Self {
let name = data.name.clone().unwrap_or_default();
let pid = data.pid;
Self {
name,
pid,
data,
provider,
}
}
pub fn locator(&self, selector: &str) -> Locator {
Locator::new(
Arc::clone(&self.provider),
Some(self.data.clone()),
selector,
)
}
pub fn subscribe(&self) -> Result<Subscription> {
self.provider.subscribe(&self.data)
}
pub fn children(&self) -> 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 provider(&self) -> &Arc<dyn Provider> {
&self.provider
}
}
impl std::fmt::Display for App {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "application \"{}\"", self.name)
}
}
impl std::fmt::Debug for App {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("App")
.field("name", &self.name)
.field("pid", &self.pid)
.finish()
}
}