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
//! **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, the `+` that begins a conversation 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
//! rows 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`). The one exception is an engine's own
//! row, which the walk may stand on without opening it ([`walk`]).
//!
//! # There is ONE list, so there is nothing to ask which list this is
//!
//! The walk used to be two tracks behind a `Pane` field on the model, because
//! the roster and the conversations were two panes. DESIGN §4.39 folded the
//! conversations under their wall, so there is one list, one track and one
//! order — engine rows, the open engine's walls, and the aimed wall's
//! conversations, exactly as the glass paints them
//! (`crate::ui::roster::track`). The field, the enum and the mark on a heading
//! that said which of the two was live all go with the second track: an answer
//! with no alternative is not an answer worth holding.
//!
//! # 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**. In the broad shape they name nothing, because
//! both columns are already on the glass and only one of them is a list — so
//! they gain no meaning there rather than acquiring a second one.
//!
//! **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;
/// Every box on the glass that takes text, and the gate that reads them.
pub use ;
/// **Take this frame's keys.** Called at the top of the frame, so what a key
/// changed is what the frame paints.
/// **Enter or Space opens the engine the walk is standing on** (DESIGN §4.39)
/// — the one binding this module has that is not a walk, and it exists because
/// the cursor on an engine row is deliberately NOT the selection: the walk has
/// to be able to pass a closed engine without opening it, so opening is a
/// second keypress.
///
/// It names a control rather than adding one: [`Model::open_engine`] is the
/// door `crate::ui::roster::engine`'s own click calls.
///
/// **It fires only while nothing holds the keyboard**, which is the whole of
/// why it is a binding at all. An arrow key walks the list without focusing
/// anything, so egui has no widget to fire and this stands in for the click;
/// the moment a Tab has put the keyboard on a control — the engine's row, the
/// `+` beside it, anything — egui fires THAT control itself, and a binding
/// running beside it would spend a second act the operator did not ask for.
/// Move the one list's cursor 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::track` exists to prevent —
/// the cursor IS the selection, so the selection has to be somewhere an
/// operator can see it.
///
/// **The track crosses three kinds of row** (DESIGN §4.39): landing on a wall
/// aims it and landing on a conversation selects it, exactly as a click does,
/// and landing on an engine's row only STANDS there — the row takes the
/// keyboard, and Enter or Space fires the same act a pointer fires, because a
/// walk that opened every engine it moved through would be a walk nobody could
/// use to reach the one below.
/// 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.