| 263 |
263 |
|
//! case that proves this cannot be one renderer-wide setting: its first frame
|
| 264 |
264 |
|
//! is on screen and its others are not, in one widget, at one moment.
|
| 265 |
265 |
|
//!
|
|
266 |
+ |
//! 0.23.0 adds [`Showing`], which is three open findings collapsing into one
|
|
267 |
+ |
//! member. A tab group could not say which tab was open, a carousel could not
|
|
268 |
+ |
//! say which frame was up, and a disclosure could not say whether its child was
|
|
269 |
+ |
//! showing. All three are the same missing sentence, and while it was missing a
|
|
270 |
+ |
//! renderer had two moves: match on a widget name, or draw every child.
|
|
271 |
+ |
//!
|
|
272 |
+ |
//! So the widget tier was taking the blame for a gap one level below it. With
|
|
273 |
+ |
//! this a renderer derives its chrome from the description — labels get a strip,
|
|
274 |
+ |
//! no labels get previous/position/next — once, for every widget there will ever
|
|
275 |
+ |
//! be, and [`Region::Widget`]'s name goes back to being app vocabulary a
|
|
276 |
+ |
//! renderer may decline to know.
|
|
277 |
+ |
//!
|
|
278 |
+ |
//! Only the kind lives here. Which child is up, and what each child is called,
|
|
279 |
+ |
//! sit with whatever holds the regions, the same split [`Selector`] already made
|
|
280 |
+ |
//! against `Node::Select`.
|
|
281 |
+ |
//!
|
| 266 |
282 |
|
//! # Reach, focus and the focus ring
|
| 267 |
283 |
|
//!
|
| 268 |
284 |
|
//! Three terms, and no others, for what 0.19.0 moved out of the description.
|
| 1705 |
1721 |
|
}
|
| 1706 |
1722 |
|
}
|
| 1707 |
1723 |
|
|
|
1724 |
+ |
/// How many of a region's children are visible at once.
|
|
1725 |
+ |
///
|
|
1726 |
+ |
/// `4dcd241b`. Three findings turned out to be one sentence the vocabulary
|
|
1727 |
+ |
/// could not say: *this region holds several children and shows some of them,
|
|
1728 |
+ |
/// and the reader can change which.* [`Region::TabGroup`] existed with nothing
|
|
1729 |
+ |
/// saying which tab was open, a carousel had nothing saying which frame was up,
|
|
1730 |
+ |
/// and a disclosure had nothing saying whether its one child was showing at all.
|
|
1731 |
+ |
///
|
|
1732 |
+ |
/// Because the fact lived nowhere, a renderer had two moves: hardcode a widget
|
|
1733 |
+ |
/// name, or draw every child. That is what put per-widget code in renderers, and
|
|
1734 |
+ |
/// it was the missing member rather than the widget tier that put it there.
|
|
1735 |
+ |
///
|
|
1736 |
+ |
/// # What is here and what is not
|
|
1737 |
+ |
///
|
|
1738 |
+ |
/// The *kind*, and only the kind. Which child is currently up is the current
|
|
1739 |
+ |
/// answer, and a layer that defers every address does not hold the current
|
|
1740 |
+ |
/// answer either — the split [`Selector`] already makes, where this crate says
|
|
1741 |
+ |
/// what kind of chooser a thing is and the router says which option is picked.
|
|
1742 |
+ |
/// So a holder of regions carries the index and the per-child label beside this.
|
|
1743 |
+ |
///
|
|
1744 |
+ |
/// # What a renderer does with it
|
|
1745 |
+ |
///
|
|
1746 |
+ |
/// Derives its chrome, once, for every widget rather than per name:
|
|
1747 |
+ |
///
|
|
1748 |
+ |
/// - Children carrying labels get a strip of the labels, the current one marked.
|
|
1749 |
+ |
/// - Children carrying none get previous, position, next.
|
|
1750 |
+ |
/// - [`AtMostOne`](Self::AtMostOne) over one child gets a summary line that
|
|
1751 |
+ |
/// opens.
|
|
1752 |
+ |
///
|
|
1753 |
+ |
/// The name on [`Region::Widget`] survives as app vocabulary, for a renderer
|
|
1754 |
+ |
/// that wants to do something *special* with one, which is what it should have
|
|
1755 |
+ |
/// been from the start.
|
|
1756 |
+ |
///
|
|
1757 |
+ |
/// Degradation runs the way it already did: a renderer ignoring this draws every
|
|
1758 |
+ |
/// child, which is more content rather than less.
|
|
1759 |
+ |
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
|
|
1760 |
+ |
#[non_exhaustive]
|
|
1761 |
+ |
pub enum Showing {
|
|
1762 |
+ |
/// Every child, in order. What every region did before this existed.
|
|
1763 |
+ |
#[default]
|
|
1764 |
+ |
All,
|
|
1765 |
+ |
/// Exactly one. A carousel, a tab group.
|
|
1766 |
+ |
One,
|
|
1767 |
+ |
/// One, or none. A disclosure, which is closed until it is opened.
|
|
1768 |
+ |
AtMostOne,
|
|
1769 |
+ |
}
|
|
1770 |
+ |
|
|
1771 |
+ |
impl Showing {
|
|
1772 |
+ |
/// Whether the reader can change which child is up.
|
|
1773 |
+ |
///
|
|
1774 |
+ |
/// The question every renderer's region arm asks before deriving any
|
|
1775 |
+ |
/// chrome, and a method rather than a `matches!` at each renderer for
|
|
1776 |
+ |
/// [`Region::name`]'s reason: three renderers writing the same comparison is
|
|
1777 |
+ |
/// how they come to disagree about a member added later.
|
|
1778 |
+ |
#[must_use]
|
|
1779 |
+ |
pub const fn selective(self) -> bool {
|
|
1780 |
+ |
!matches!(self, Self::All)
|
|
1781 |
+ |
}
|
|
1782 |
+ |
|
|
1783 |
+ |
/// Whether showing nothing is a legal state.
|
|
1784 |
+ |
///
|
|
1785 |
+ |
/// True only for [`AtMostOne`](Self::AtMostOne). A renderer needs this to
|
|
1786 |
+ |
/// know whether its control closes as well as moves: a carousel's row moves
|
|
1787 |
+ |
/// between frames and never reaches empty, and a disclosure's summary line
|
|
1788 |
+ |
/// is the same control wearing its closed state.
|
|
1789 |
+ |
#[must_use]
|
|
1790 |
+ |
pub const fn dismissible(self) -> bool {
|
|
1791 |
+ |
matches!(self, Self::AtMostOne)
|
|
1792 |
+ |
}
|
|
1793 |
+ |
}
|
|
1794 |
+ |
|
| 1708 |
1795 |
|
/// How much of the width an arrangement's first region takes.
|
| 1709 |
1796 |
|
///
|
| 1710 |
1797 |
|
/// `e0fd485e`. Nothing said how much room a region got, so every renderer
|
| 2536 |
2623 |
|
}
|
| 2537 |
2624 |
|
}
|
| 2538 |
2625 |
|
|
|
2626 |
+ |
#[test]
|
|
2627 |
+ |
fn a_region_shows_all_of_its_children_unless_it_says_otherwise() {
|
|
2628 |
+ |
// The default is the behaviour every region had before this member
|
|
2629 |
+ |
// existed, which is what keeps it additive: a description written
|
|
2630 |
+ |
// against 0.22.0 says the same thing under 0.23.0.
|
|
2631 |
+ |
assert_eq!(Showing::default(), Showing::All);
|
|
2632 |
+ |
assert!(!Showing::All.selective());
|
|
2633 |
+ |
}
|
|
2634 |
+ |
|
|
2635 |
+ |
#[test]
|
|
2636 |
+ |
fn only_a_disclosure_can_show_nothing() {
|
|
2637 |
+ |
// The two derived idioms differ in one respect and this is it. A
|
|
2638 |
+ |
// carousel's row moves between frames and never reaches empty; a
|
|
2639 |
+ |
// disclosure's summary line is the same control wearing its closed
|
|
2640 |
+ |
// state, so a renderer has to know which it is drawing.
|
|
2641 |
+ |
assert!(Showing::AtMostOne.dismissible());
|
|
2642 |
+ |
assert!(!Showing::One.dismissible());
|
|
2643 |
+ |
assert!(!Showing::All.dismissible());
|
|
2644 |
+ |
|
|
2645 |
+ |
// Both are selective, though. Deriving chrome is one question and
|
|
2646 |
+ |
// whether that chrome closes is another.
|
|
2647 |
+ |
assert!(Showing::One.selective());
|
|
2648 |
+ |
assert!(Showing::AtMostOne.selective());
|
|
2649 |
+ |
}
|
|
2650 |
+ |
|
| 2539 |
2651 |
|
#[test]
|
| 2540 |
2652 |
|
fn an_empty_region_is_not_a_broken_one() {
|
| 2541 |
2653 |
|
// An empty list is the normal state of a new install. Drawing it in a
|