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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
//! **The keyboard**: every act this window affords, reachable without a
//! pointer (yog's `docs/QUALITY.md` F1 — *everything keyboard-operable*).
//!
//! A face an operator has to leave the keyboard for, once per selection, is a
//! face they use through the command line instead. The obligation is inherited;
//! the implementation is not, because the shape that fits four panes is not the
//! shape that fits thirty.
//!
//! # Most of it is egui's, and that is the point
//!
//! Every control here is a button or a text box, and egui already moves focus
//! between them with Tab and fires a focused one with Space or Enter. So Send,
//! Nudge, Start and the notice's dismiss are keyboard-operable with nothing
//! written — `tests` proves it rather than assuming it. What Tab cannot make
//! *usable* is a list: tabbing through thirty walls to reach the composer is
//! reachability without operability, and that is the whole of what this module
//! adds.
//!
//! # The cursor IS the selection, so there is nothing to keep in step
//!
//! A list cursor beside a selection is two highlights, two things to paint and
//! two ways to disagree. There is no cursor: **moving in a list selects**, so
//! the highlight the pointer already paints is where the keyboard is, and the
//! reads that follow a selection follow a keypress for free (the standing set
//! is derived — `crate::state::Standing`). What is left to paint is only
//! *which list the arrows belong to*, which is [`Pane`], and it is marked on
//! that pane's own heading: a focus that cannot be seen is a focus nobody can
//! use.
//!
//! # It names controls; it never adds one
//!
//! Every binding below calls the same door a click calls
//! (`crate::ui::model::acts`), and the roster walk asks the same question the
//! roster's own paint asks — so a row no pointer can aim at is a row no key can
//! aim at either. A binding that could fire something a click cannot is a
//! second surface.
//!
//! # The narrow shape does not add a binding; it changes what a place IS
//!
//! With one column on the glass at a time (`crate::ui::shell::policy`), left
//! and right name a **column** rather than one of two panes, and the arrows
//! belong to whichever column is showing — asked of [`Pane`] as always, set
//! from the column once per frame. Nothing else here knows: the walk, the
//! reveal and the mark on a heading read the one field they always read, and no
//! pane has to ask which shape it is in.
//!
//! **A box that is taking text takes every key**, which is the one gate: while
//! a text box holds the focus nothing here runs, so an arrow is a cursor move
//! inside the draft and Escape is egui's own *leave the box*. Press it again
//! with no box focused and it is [`Model::escape`] below — which closes the
//! enrollment where one covers the window, and puts the notice down otherwise.
//! One key, three contexts, and the contexts never overlap.
//!
//! The gate asks for **those boxes by name** rather than for egui's
//! `wants_keyboard_input`, which answers *is anything focused at all* — every
//! button included. Tabbing to Send would otherwise turn the arrows off, and a
//! click focuses a control too, so the honest question is the narrow one: every
//! box that takes text wears an id, [`BOXES`] is the whole list of them, and
//! the gate compares against it.
use crate;
/// Which list the arrows belong to. Two, because two of the four panes hold a
/// list; the chat pane scrolls and the composer takes text, and both are
/// reached the way every control is, with Tab.
/// **The id the composer's box wears**, and the whole of what the keyboard has
/// to know about it. The deposit's box and the start's are one control with two
/// subjects and are never painted together, so they wear one id — and the gate
/// below is a comparison rather than a guess about what "focused" means.
pub const BOX_ID: &str = "the composer's box";
/// **The id the flag's reason box wears** (`crate::ui::composer::acts::WHY`).
pub const REASON_ID: &str = "the flag's reason box";
/// **The id the deletion's arming box wears**
/// (`crate::ui::composer::acts::ARM`).
pub const ARM_ID: &str = "the deletion's arming box";
/// **Every box on the glass that takes text, so the gate can name them all**
/// (bl-dbc9).
///
/// It was one id, and one was enough while the only way into the other two was
/// Tab — a hazard, but one an operator walked into deliberately. A conversation
/// row's menu now LANDS the cursor in the reason box and in the arming box
/// (`crate::ui::model::fill`), and an arrow taken from inside either would have
/// walked the conversation list under a half-typed reason and flagged the row
/// it landed on. The gate is still a comparison rather than
/// `wants_keyboard_input` — which answers *is anything focused*, buttons
/// included — and this is the whole list of what it compares against. A fourth
/// box belongs here in the commit that paints it.
pub const BOXES: = ;
/// Whether a box that takes text holds the keyboard right now.
/// The mark a focused pane's heading wears — and the heading is where it goes
/// because a pane's heading is the one thing on it that is always painted, even
/// when it holds nothing at all.
pub const HERE: &str = "›";
/// The heading a pane paints, with the mark when the arrows are its.
/// **Take this frame's keys.** Called at the top of the frame, so what a key
/// changed is what the frame paints.
/// **Sideways**: the place a left or right key names, in the shape the window
/// is in. Two panes hold the arrows in the broad shape and there is one of each
/// key, so the key IS the place; the narrow shape has three columns and one on
/// the glass, so the key is a step off wherever the operator is.
/// Move the focused list's selection by one, and say the pane owes the new
/// selection a place on the glass.
///
/// **The walk is the surface that can leave the glass behind.** A list longer
/// than its pane scrolls ([`crate::ui::shell`]), and a key that moved the
/// selection past the fold without moving the fold would put the two surfaces
/// back into the disagreement `crate::ui::roster::aimable` exists to prevent —
/// the cursor IS the selection, so the selection has to be somewhere an
/// operator can see it.
/// Where the cursor lands.
///
/// **Nothing selected goes to the first row, whichever way it was pressed**: a
/// list an operator has not entered has no direction to move in yet, and the
/// alternative is teaching them that Up means "the last one" before they have
/// selected anything. The ends **saturate** rather than wrap, because a wrap
/// makes the same keypress mean *next* thirty times and *back to the top* once,
/// with nothing on the glass to say which it will be.