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;