grouping.rs
raw
//! Containers that say what the things inside them are.
//!
//! Each is a [`Container`] with two answers changed: the name a theme matches
//! and the accessibility role. They hold no selection and no children of their
//! own kind — a tab strip does not own which tab is showing, any more than a
//! radio group owns which radio is chosen. Mutual exclusion stays a fact about
//! the application's data; what these add is the announcement, which is the
//! part a `container` and a theme rule could never have supplied.
use guiduck_scene::Fragment;
use guiduck_scene::geom::Size;
use super::{Container, Widget};
use crate::dirty::Dirt;
use crate::style::ComputedStyle;
/// Define a container that differs only in its name and its role.
macro_rules! role_container {
($(#[$meta:meta])* $name:ident, $type_name:literal, $role:expr) => {
$(#[$meta])*
#[derive(Default)]
pub struct $name(Container);
impl $name {
pub fn new() -> Self {
Self::default()
}
}
impl Widget for $name {
fn paint(&mut self, fragment: &mut Fragment, size: Size) {
self.0.paint(fragment, size);
}
fn role(&self) -> accesskit::Role {
$role
}
fn take_dirt(&mut self) -> Dirt {
self.0.take_dirt()
}
fn type_name(&self) -> &'static str {
$type_name
}
fn apply_style(&mut self, style: &ComputedStyle) {
self.0.apply_style(style);
}
}
};
}
role_container!(
/// The strip a set of `tab`s sits in.
TabList,
"tab-list",
accesskit::Role::TabList
);
role_container!(
/// A list of `list-item`s.
///
/// Selection lives in the application's data and reaches each item through
/// its `:selected` binding, so this holds nothing. What it adds is that a
/// screen reader is told these rows are a list and how many there are —
/// which a `container` full of rows cannot say.
ListBox,
"list",
accesskit::Role::ListBox
);
#[cfg(test)]
mod tests;