| 1003 |
1003 |
|
/// renderer can right-align one string and cannot usefully do the same to a
|
| 1004 |
1004 |
|
/// strip of chips, and a fact that is not clickable should not be drawn as
|
| 1005 |
1005 |
|
/// though it were.
|
|
1006 |
+ |
/// How much vertical room a part's text may take.
|
|
1007 |
+ |
///
|
|
1008 |
+ |
/// A row is an inline run and every part in it is a leaf, so a part's text has
|
|
1009 |
+ |
/// always been drawn on one line and no description could say otherwise. Two
|
|
1010 |
+ |
/// apps say otherwise in their own stylesheets, both to the same number and
|
|
1011 |
+ |
/// both with a comment explaining it: Balanced Breakfast clamps a feed row's
|
|
1012 |
+ |
/// title to two lines (`.row--article .row-primary`, whose comment reads
|
|
1013 |
+ |
/// "overrides .row-primary's single flex line"), and goingson clamps a
|
|
1014 |
+ |
/// problem's body to two ("two lines is enough to recognize one, and the full
|
|
1015 |
+ |
/// text is in the task once promoted").
|
|
1016 |
+ |
///
|
|
1017 |
+ |
/// Two named tiers rather than a line count, and the count is what the measured
|
|
1018 |
+ |
/// demand argues against. Both sites want exactly one tier past the default,
|
|
1019 |
+ |
/// and a number invites a row whose primary is a paragraph, which is a block
|
|
1020 |
+ |
/// and has no business in a run. A third tier is a decision, made here, rather
|
|
1021 |
+ |
/// than something a call site can reach for.
|
|
1022 |
+ |
///
|
|
1023 |
+ |
/// What a renderer owes it: `Tight` is what a run already does and needs no
|
|
1024 |
+ |
/// answer. `Relaxed` is at most two lines and then truncation, however that
|
|
1025 |
+ |
/// renderer truncates -- a webview clamps, a terminal wraps into two rows of
|
|
1026 |
+ |
/// cells, an immediate-mode renderer caps the galley. A renderer that cannot
|
|
1027 |
+ |
/// give two lines may draw one; what it may not do is grow without bound,
|
|
1028 |
+ |
/// because the run is a line and the row's neighbours are relying on that.
|
|
1029 |
+ |
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
|
|
1030 |
+ |
#[non_exhaustive]
|
|
1031 |
+ |
pub enum Flow {
|
|
1032 |
+ |
/// One line. What every part did before this type existed.
|
|
1033 |
+ |
#[default]
|
|
1034 |
+ |
Tight,
|
|
1035 |
+ |
/// Up to two lines, then truncated.
|
|
1036 |
+ |
Relaxed,
|
|
1037 |
+ |
}
|
|
1038 |
+ |
|
|
1039 |
+ |
impl Flow {
|
|
1040 |
+ |
/// How many lines the part may take.
|
|
1041 |
+ |
///
|
|
1042 |
+ |
/// A number here rather than in the enum, because a renderer needs one and
|
|
1043 |
+ |
/// a call site does not. That asymmetry is the whole argument for the
|
|
1044 |
+ |
/// tiers: the description says how much room the thing deserves and this
|
|
1045 |
+ |
/// says what that costs, so a third tier changes one line rather than every
|
|
1046 |
+ |
/// consumer's arithmetic.
|
|
1047 |
+ |
#[must_use]
|
|
1048 |
+ |
pub const fn lines(self) -> u8 {
|
|
1049 |
+ |
match self {
|
|
1050 |
+ |
Self::Relaxed => 2,
|
|
1051 |
+ |
// Including any tier added later: one line is the safe reading of
|
|
1052 |
+ |
// an unknown flow, since it is what the run guaranteed before flows
|
|
1053 |
+ |
// existed.
|
|
1054 |
+ |
_ => 1,
|
|
1055 |
+ |
}
|
|
1056 |
+ |
}
|
|
1057 |
+ |
}
|
|
1058 |
+ |
|
| 1006 |
1059 |
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
| 1007 |
1060 |
|
#[non_exhaustive]
|
| 1008 |
1061 |
|
pub enum RowPart {
|
| 3460 |
3513 |
|
Fill,
|
| 3461 |
3514 |
|
}
|
| 3462 |
3515 |
|
|
| 3463 |
|
- |
/// What a column is worth when there is not room for all of them.
|
|
3516 |
+ |
/// What a part is worth when there is not room for all of them.
|
|
3517 |
+ |
///
|
|
3518 |
+ |
/// Written for table columns and no longer only theirs: a row is an inline run
|
|
3519 |
+ |
/// and a terminal 40 columns wide has to drop something out of it, which is the
|
|
3520 |
+ |
/// same question a narrow table asks. The doc below is the column argument,
|
|
3521 |
+ |
/// which is where the type was measured; the sentence that gave it away is
|
|
3522 |
+ |
/// [`Priority::Essential`]'s, which was already written about a row.
|
| 3464 |
3523 |
|
///
|
| 3465 |
3524 |
|
/// Ordered: [`Priority::Optional`] drops first, [`Priority::Essential`] never
|
| 3466 |
3525 |
|
/// drops. This replaces addressing columns by position, which is what both
|
| 4996 |
5055 |
|
// usize, which would print as "18446744073709551516 remaining".
|
| 4997 |
5056 |
|
assert_eq!(Paging::more(500).of(400).remaining(), Some(0));
|
| 4998 |
5057 |
|
}
|
|
5058 |
+ |
|
|
5059 |
+ |
#[test]
|
|
5060 |
+ |
fn a_run_is_one_line_unless_the_description_says_two() {
|
|
5061 |
+ |
// The default is what every part did before flows existed, so a
|
|
5062 |
+ |
// description written against the old vocabulary keeps its rendering.
|
|
5063 |
+ |
assert_eq!(Flow::default(), Flow::Tight);
|
|
5064 |
+ |
assert_eq!(Flow::Tight.lines(), 1);
|
|
5065 |
+ |
assert_eq!(Flow::Relaxed.lines(), 2);
|
|
5066 |
+ |
}
|
|
5067 |
+ |
|
|
5068 |
+ |
#[test]
|
|
5069 |
+ |
fn an_unknown_flow_reads_as_one_line() {
|
|
5070 |
+ |
// `#[non_exhaustive]`'s cost, taken deliberately. A tier added upstream
|
|
5071 |
+ |
// reaches an old renderer as one line rather than as a build break, and
|
|
5072 |
+ |
// one line is the reading that cannot break a neighbour's layout. The
|
|
5073 |
+ |
// match in `lines` is what this holds; it fails if a new tier is given
|
|
5074 |
+ |
// an arm that returns something unbounded.
|
|
5075 |
+ |
for flow in [Flow::Tight, Flow::Relaxed] {
|
|
5076 |
+ |
assert!((1..=2).contains(&flow.lines()));
|
|
5077 |
+ |
}
|
|
5078 |
+ |
}
|
| 4999 |
5079 |
|
}
|