use accesskit::{Node, Role, Toggled};
#[derive(Clone, Debug)]
pub struct AccessibilityBuilder {
role: Role,
label: Option<String>,
description: Option<String>,
value: Option<String>,
tooltip: Option<String>,
focusable: bool,
disabled: bool,
expanded: Option<bool>,
toggled: Option<Toggled>,
clicked: bool,
}
impl AccessibilityBuilder {
pub fn new(role: Role) -> Self {
Self {
role,
label: None,
description: None,
value: None,
tooltip: None,
focusable: false,
disabled: false,
expanded: None,
toggled: None,
clicked: false,
}
}
pub fn label(mut self, label: impl Into<String>) -> Self {
self.label = Some(label.into());
self
}
pub fn description(mut self, desc: impl Into<String>) -> Self {
self.description = Some(desc.into());
self
}
pub fn value(mut self, value: impl Into<String>) -> Self {
self.value = Some(value.into());
self
}
pub fn tooltip(mut self, tooltip: impl Into<String>) -> Self {
self.tooltip = Some(tooltip.into());
self
}
pub fn focusable(mut self) -> Self {
self.focusable = true;
self
}
pub fn disabled(mut self) -> Self {
self.disabled = true;
self
}
pub fn expanded(mut self, expanded: bool) -> Self {
self.expanded = Some(expanded);
self
}
pub fn toggled(mut self, toggled: Toggled) -> Self {
self.toggled = Some(toggled);
self
}
pub fn clickable(mut self) -> Self {
self.clicked = true;
self
}
pub fn apply(self, node: &mut Node) {
node.set_role(self.role);
if let Some(label) = self.label {
node.set_label(label);
}
if let Some(desc) = self.description {
node.set_description(desc);
}
if let Some(value) = self.value {
node.set_value(value);
}
if let Some(tooltip) = self.tooltip {
node.set_tooltip(tooltip);
}
if self.focusable {
node.add_action(accesskit::Action::Focus);
}
if self.disabled {
node.set_disabled();
}
if let Some(expanded) = self.expanded {
node.set_expanded(expanded);
}
if let Some(toggled) = self.toggled {
node.set_toggled(toggled);
}
if self.clicked {
node.add_action(accesskit::Action::Click);
}
}
}
#[inline]
pub fn set_label(node: &mut Node, label: impl Into<String>) {
node.set_label(label);
}
#[inline]
pub fn set_description(node: &mut Node, desc: impl Into<String>) {
node.set_description(desc);
}
#[inline]
pub fn set_value(node: &mut Node, value: impl Into<String>) {
node.set_value(value);
}
#[inline]
pub fn set_focusable(node: &mut Node) {
node.add_action(accesskit::Action::Focus);
}
#[inline]
pub fn set_disabled(node: &mut Node) {
node.set_disabled();
}
#[inline]
pub fn set_expanded(node: &mut Node, expanded: bool) {
node.set_expanded(expanded);
}
#[inline]
pub fn set_toggled(node: &mut Node, toggled: Toggled) {
node.set_toggled(toggled);
}
#[inline]
pub fn set_clickable(node: &mut Node) {
node.add_action(accesskit::Action::Click);
}
pub fn role_for_button() -> Role {
Role::Button
}
pub fn role_for_text_input() -> Role {
Role::TextInput
}
pub fn role_for_checkbox() -> Role {
Role::CheckBox
}
pub fn role_for_radio_button() -> Role {
Role::RadioButton
}
pub fn role_for_slider() -> Role {
Role::Slider
}
pub fn role_for_container() -> Role {
Role::GenericContainer
}
pub fn role_for_text_display() -> Role {
Role::TextRun
}
pub fn role_for_image() -> Role {
Role::Image
}
pub fn role_for_link() -> Role {
Role::Link
}
pub fn role_for_list() -> Role {
Role::List
}
pub fn role_for_list_item() -> Role {
Role::ListItem
}
pub fn role_for_dialog() -> Role {
Role::Dialog
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn builder_sets_label() {
let mut node = Node::new(Role::Unknown);
AccessibilityBuilder::new(Role::Button)
.label("OK")
.apply(&mut node);
assert_eq!(node.label(), Some("OK"));
assert_eq!(node.role(), Role::Button);
}
#[test]
fn builder_sets_description() {
let mut node = Node::new(Role::Unknown);
AccessibilityBuilder::new(Role::Button)
.description("Confirms the action")
.apply(&mut node);
assert_eq!(node.description(), Some("Confirms the action"));
}
#[test]
fn builder_sets_value() {
let mut node = Node::new(Role::Unknown);
AccessibilityBuilder::new(Role::TextInput)
.value("hello")
.apply(&mut node);
assert_eq!(node.value(), Some("hello"));
}
#[test]
fn builder_sets_tooltip() {
let mut node = Node::new(Role::Unknown);
AccessibilityBuilder::new(Role::Button)
.tooltip("Click me")
.apply(&mut node);
assert_eq!(node.tooltip(), Some("Click me"));
}
#[test]
fn builder_focusable_adds_action() {
let mut node = Node::new(Role::Unknown);
AccessibilityBuilder::new(Role::Button)
.focusable()
.apply(&mut node);
assert!(node.supports_action(accesskit::Action::Focus));
}
#[test]
fn builder_disabled_sets_flag() {
let mut node = Node::new(Role::Unknown);
AccessibilityBuilder::new(Role::Button)
.disabled()
.apply(&mut node);
assert!(node.is_disabled());
}
#[test]
fn builder_expanded_sets_flag() {
let mut node = Node::new(Role::Unknown);
AccessibilityBuilder::new(Role::Button)
.expanded(true)
.apply(&mut node);
assert_eq!(node.is_expanded(), Some(true));
}
#[test]
fn builder_toggled_sets_state() {
let mut node = Node::new(Role::Unknown);
AccessibilityBuilder::new(Role::CheckBox)
.toggled(Toggled::True)
.apply(&mut node);
assert_eq!(node.toggled(), Some(Toggled::True));
}
#[test]
fn builder_clickable_adds_action() {
let mut node = Node::new(Role::Unknown);
AccessibilityBuilder::new(Role::Button)
.clickable()
.apply(&mut node);
assert!(node.supports_action(accesskit::Action::Click));
}
#[test]
fn builder_chains_all_properties() {
let mut node = Node::new(Role::Unknown);
AccessibilityBuilder::new(Role::CheckBox)
.label("Accept terms")
.description("Check to accept the terms of service")
.value("checked")
.tooltip("Required")
.focusable()
.clickable()
.toggled(Toggled::True)
.apply(&mut node);
assert_eq!(node.role(), Role::CheckBox);
assert_eq!(node.label(), Some("Accept terms"));
assert_eq!(
node.description(),
Some("Check to accept the terms of service")
);
assert_eq!(node.value(), Some("checked"));
assert_eq!(node.tooltip(), Some("Required"));
assert!(node.supports_action(accesskit::Action::Focus));
assert!(node.supports_action(accesskit::Action::Click));
assert_eq!(node.toggled(), Some(Toggled::True));
}
#[test]
fn helper_functions_set_properties() {
let mut node = Node::new(Role::Button);
set_label(&mut node, "Test");
set_description(&mut node, "Desc");
set_value(&mut node, "Val");
set_focusable(&mut node);
set_disabled(&mut node);
set_expanded(&mut node, true);
set_toggled(&mut node, Toggled::True);
set_clickable(&mut node);
assert_eq!(node.label(), Some("Test"));
assert_eq!(node.description(), Some("Desc"));
assert_eq!(node.value(), Some("Val"));
assert!(node.supports_action(accesskit::Action::Focus));
assert!(node.is_disabled());
assert_eq!(node.is_expanded(), Some(true));
assert_eq!(node.toggled(), Some(Toggled::True));
assert!(node.supports_action(accesskit::Action::Click));
}
#[test]
fn role_helpers_return_expected_roles() {
assert_eq!(role_for_button(), Role::Button);
assert_eq!(role_for_text_input(), Role::TextInput);
assert_eq!(role_for_checkbox(), Role::CheckBox);
assert_eq!(role_for_radio_button(), Role::RadioButton);
assert_eq!(role_for_slider(), Role::Slider);
assert_eq!(role_for_container(), Role::GenericContainer);
assert_eq!(role_for_text_display(), Role::TextRun);
assert_eq!(role_for_image(), Role::Image);
assert_eq!(role_for_link(), Role::Link);
assert_eq!(role_for_list(), Role::List);
assert_eq!(role_for_list_item(), Role::ListItem);
assert_eq!(role_for_dialog(), Role::Dialog);
}
}