use crate::core::{Bounds, FocusHandle, FocusId, Point, px};
use crate::view::window::Window;
use accesskit::{Action, ActionRequest, Node, NodeId, Rect, Role, TreeId, TreeInfo, TreeUpdate};
use std::rc::Rc;
#[derive(Clone, Debug)]
pub struct AccessNode {
pub role: Role,
pub label: Option<Rc<str>>,
pub value: Option<Rc<str>>,
pub bounds: Bounds,
pub focus: Option<FocusId>,
pub clickable: bool,
}
const ROOT: NodeId = NodeId(0);
fn rect(bounds: Bounds, scale: f32) -> Rect {
let scale = f64::from(scale);
Rect {
x0: f64::from(bounds.origin.x.0) * scale,
y0: f64::from(bounds.origin.y.0) * scale,
x1: f64::from(bounds.origin.x.0 + bounds.size.width.0) * scale,
y1: f64::from(bounds.origin.y.0 + bounds.size.height.0) * scale,
}
}
impl Window {
pub fn set_accessibility(&mut self, active: bool) {
self.accessibility = active;
}
pub fn accessibility_active(&self) -> bool {
self.accessibility
}
pub fn accessibility_tree(&self) -> TreeUpdate {
let mut window = Node::new(Role::Window);
window.set_label("Aura");
let focused = self.entities.focus.focused();
let mut nodes = Vec::with_capacity(self.frame.access.len() + 1);
let mut focus = ROOT;
let mut children = Vec::with_capacity(self.frame.access.len());
for (index, entry) in self.frame.access.iter().enumerate() {
let id = NodeId(index as u64 + 1);
let mut node = Node::new(entry.role);
if let Some(label) = &entry.label {
node.set_label(label.to_string());
}
if let Some(value) = &entry.value {
node.set_value(value.to_string());
}
node.set_bounds(rect(entry.bounds, self.scale));
if entry.clickable {
node.add_action(Action::Click);
}
if entry.focus.is_some() {
node.add_action(Action::Focus);
if entry.focus == focused {
focus = id;
}
}
children.push(id);
nodes.push((id, node));
}
window.set_children(children);
nodes.push((ROOT, window));
TreeUpdate { nodes, tree: Some(TreeInfo::new(ROOT)), tree_id: TreeId::ROOT, focus }
}
pub fn accessibility_action(&mut self, request: &ActionRequest) -> bool {
let Some(index) = (request.target_node.0 as usize).checked_sub(1) else { return false };
let Some(entry) = self.frame.access.get(index).cloned() else { return false };
match request.action {
Action::Focus => match entry.focus.map(|id| FocusHandle { id }) {
Some(handle) => {
self.entities.focus.focus(&handle);
true
}
None => false,
},
Action::Click => {
let center = Point::new(
px(entry.bounds.origin.x.0 + entry.bounds.size.width.0 / 2.0),
px(entry.bounds.origin.y.0 + entry.bounds.size.height.0 / 2.0),
);
use crate::core::{InputEvent, MouseButton};
let mut redraw = self.handle_event(&InputEvent::MouseMove { position: center });
redraw |= self.handle_event(&InputEvent::MouseDown { position: center, button: MouseButton::Left });
redraw | self.handle_event(&InputEvent::MouseUp { position: center, button: MouseButton::Left })
}
_ => false,
}
}
}