1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
use crate::{State, Tone};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Act<'a> {
/// What the control says.
pub label: &'a str,
/// The key that reaches it where a host has keys.
///
/// The one member written for a terminal before there was one. A webview
/// hangs it off `accesskey` or ignores it; a terminal has nothing else to
/// offer, so this is the whole of how a control is reached there.
pub key: Option<&'a str>,
/// What pressing it means. [`Tone::Danger`] is the destructive one.
pub tone: Tone,
/// Disabled, or nothing said.
///
/// [`State::Disabled`] is what changes what a renderer may do: see
/// [`State::suppresses_interaction`], which is what says a disabled control
/// is drawn and not reachable. A control's focus is not sayable here at
/// all: see the crate header, "Reach, focus and the focus ring".
pub state: Option<State>,
/// A sentence that is always true of this control, shown rather than hunted
/// for.
///
/// Standing help, not a message and not a tooltip. Half the hosts that read
/// this have no pointer: a hover is one spelling of it, and the shipped
/// apps reached for that spelling only because egui and a browser both had
/// one. What is being said is that the sentence is true, never that it is
/// hidden until a pointer arrives.
///
/// # Why it is here rather than a layer up
///
/// A hint left to `quasi_router::Act` alone means each renderer draws it
/// for itself: `makeover_tui` had no hint to read, so quasi-tui built
/// the muted line, and quasi-immediate called `on_hover_text` outside
/// [`crate::Act`] rather than inside it. `Field::hint` was here the whole
/// time, so the same idea sat at two layers depending on which thing
/// carried it, and a host that was not quasi could say it of a field and
/// not of a control.
///
/// What kept it out was price rather than doubt: this crate declares
/// `links`, so a member here moves 25 manifests across 12 repos. That is a
/// release's forward-fix pass, which is a cost and was being read as a
/// barrier.
///
/// # What a renderer owes it
///
/// Somewhere to put it, or nothing. Dropping it is legitimate; drawing it
/// *instead of* the label is not, and neither is drawing it in a way that
/// takes it out of the accessible tree, which is the failure `title` alone
/// has on a browser. Nothing may live only in a hint.
///
/// `None` is a control whose label is the whole of it, which is nearly all
/// of them.
pub hint: Option<&'a str>,
/// Whether pressing it commits: the one control that locks in what the
/// reader has staged.
///
/// A form's submit, or the verb over a set of ticked rows. Wiki
/// `explicit-commit-affordance` is the ruling: changing a control stages a
/// change, and a separate, visible control commits it, and the commit is
/// what the reader sees. So the control has to be told apart from the
/// controls beside it that only navigate or stage, and wiki
/// `look-restoration` says how far that goes: the mark goes on the control
/// that commits and on nothing else, not on every control that writes.
///
/// # What a renderer owes it
///
/// A spelling the reader can pick out at a glance, and the same one every
/// time. A webview draws the default-button ring the Platinum specimen
/// picked and never shipped; a terminal writes `[ Label ]` where an
/// ordinary control is `< Label >`; an immediate-mode host strokes a frame
/// round the button. Nothing else changes: a committing control takes its
/// tone, its key, its state and its hint exactly as any other.
///
/// # Why a member and not a renderer's inference
///
/// Each renderer could guess it from the node a control sits in, and each
/// was left to: `makeover-tui` grew `filled_act` for a form's submit, which
/// no caller in the tree reached, while the webview drew every submit like
/// every other button. A fact the description has is said here once, which
/// is the reason [`hint`](Self::hint) is here too.
///
/// `false` on nearly every control.
pub commits: bool,
}
impl<'a> Act<'a> {
/// An ordinary control, reachable, with no key.
#[must_use]
pub const fn new(label: &'a str) -> Self {
Self {
label,
key: None,
tone: Tone::Neutral,
state: None,
hint: None,
commits: false,
}
}
/// The control that commits what the reader staged; see
/// [`commits`](Self::commits).
#[must_use]
pub const fn committing(mut self) -> Self {
self.commits = true;
self
}
/// The sentence that is always true of it; see [`hint`](Self::hint).
///
/// A renderer with nowhere to put it drops it, so this must never be the
/// only place a fact appears.
#[must_use]
pub const fn hinted(mut self, hint: &'a str) -> Self {
self.hint = Some(hint);
self
}
/// The key that reaches it.
#[must_use]
pub const fn key(mut self, key: &'a str) -> Self {
self.key = Some(key);
self
}
/// What pressing it means.
#[must_use]
pub const fn tone(mut self, tone: Tone) -> Self {
self.tone = tone;
self
}
/// Focus, or disabled.
#[must_use]
pub const fn state(mut self, state: State) -> Self {
self.state = Some(state);
self
}
/// Whether the control is drawn and does not answer.
#[must_use]
pub fn disabled(&self) -> bool {
self.state.is_some_and(State::suppresses_interaction)
}
}