| 574 |
574 |
|
kind if kind.offers_options() => u16::try_from(field.options.len()).unwrap_or(u16::MAX),
|
| 575 |
575 |
|
_ => 1,
|
| 576 |
576 |
|
};
|
| 577 |
|
- |
let note = note_of(field).map_or(0, |note| text::height(note, width));
|
|
577 |
+ |
let note = message_of(style, field).map_or(0, |(text, _)| text::height(text, width));
|
| 578 |
578 |
|
label + body + note
|
| 579 |
579 |
|
}
|
| 580 |
580 |
|
|
| 682 |
682 |
|
_ => text::draw(&measured(field, held.text()), well, below(area, used), buf),
|
| 683 |
683 |
|
};
|
| 684 |
684 |
|
|
| 685 |
|
- |
// The error wins over the hint, the same order a webview uses: a hint is
|
| 686 |
|
- |
// what to type and an error is what went wrong, and once something has gone
|
| 687 |
|
- |
// wrong that is the sentence worth the row.
|
| 688 |
|
- |
match note_of(field) {
|
| 689 |
|
- |
Some(note) => {
|
| 690 |
|
- |
let painted = if field.error.is_some() {
|
| 691 |
|
- |
style.danger
|
| 692 |
|
- |
} else {
|
| 693 |
|
- |
style.muted
|
| 694 |
|
- |
};
|
| 695 |
|
- |
used + text::draw(note, painted, below(area, used), buf)
|
| 696 |
|
- |
}
|
|
685 |
+ |
// Error, then note, then hint -- the order `Field::note` names, and the
|
|
686 |
+ |
// order a webview draws them in. Once something has gone wrong that is the
|
|
687 |
+ |
// sentence worth the row; failing that, what the chosen answer costs beats
|
|
688 |
+ |
// standing help about how the field works.
|
|
689 |
+ |
match message_of(style, field) {
|
|
690 |
+ |
Some((text, painted)) => used + text::draw(text, painted, below(area, used), buf),
|
| 697 |
691 |
|
None => used,
|
| 698 |
692 |
|
}
|
| 699 |
693 |
|
}
|
| 819 |
813 |
|
}
|
| 820 |
814 |
|
}
|
| 821 |
815 |
|
|
| 822 |
|
- |
/// What goes under the box: what is wrong now, or the standing help.
|
| 823 |
|
- |
fn note_of<'a>(field: &Field<'a>) -> Option<&'a str> {
|
| 824 |
|
- |
field.error.or(field.hint)
|
|
816 |
+ |
/// What goes under the box, and how it is painted.
|
|
817 |
+ |
///
|
|
818 |
+ |
/// A terminal field has room for exactly one line, so the three message
|
|
819 |
+ |
/// channels compete for it and the precedence is decided in
|
|
820 |
+ |
/// [`makeover_layout::Field::note`]'s docs rather than three times here:
|
|
821 |
+ |
/// **error, then note, then hint**. What is wrong outranks what the answer
|
|
822 |
+ |
/// costs, which outranks how the field works.
|
|
823 |
+ |
///
|
|
824 |
+ |
/// The tone comes with the note; an error is always danger and a hint is
|
|
825 |
+ |
/// always muted, because neither carries one.
|
|
826 |
+ |
fn message_of<'a>(style: &PieceStyle, field: &Field<'a>) -> Option<(&'a str, Style)> {
|
|
827 |
+ |
if let Some(error) = field.error {
|
|
828 |
+ |
return Some((error, style.danger));
|
|
829 |
+ |
}
|
|
830 |
+ |
if let Some((tone, note)) = field.note {
|
|
831 |
+ |
return Some((note, style.tone(tone)));
|
|
832 |
+ |
}
|
|
833 |
+ |
field.hint.map(|hint| (hint, style.muted))
|
| 825 |
834 |
|
}
|
| 826 |
835 |
|
|
| 827 |
836 |
|
/// A box with nothing in it: the ghost text, and the caret when it has focus.
|
| 863 |
872 |
|
|
| 864 |
873 |
|
#[cfg(test)]
|
| 865 |
874 |
|
mod tests {
|
|
875 |
+ |
|
|
876 |
+ |
#[test]
|
|
877 |
+ |
fn one_line_takes_the_error_then_the_note_then_the_hint() {
|
|
878 |
+ |
// A terminal field has room for exactly one message, so the three
|
|
879 |
+ |
// channels compete and `Field::note` decides the order.
|
|
880 |
+ |
let style = PieceStyle::default();
|
|
881 |
+ |
let mut f = Field::new(FieldKind::Text, "title", "Title");
|
|
882 |
+ |
f.hint = Some("how it works");
|
|
883 |
+ |
assert_eq!(message_of(&style, &f).unwrap().0, "how it works");
|
|
884 |
+ |
|
|
885 |
+ |
f.note = Some((Tone::Warning, "what it costs"));
|
|
886 |
+ |
assert_eq!(message_of(&style, &f).unwrap().0, "what it costs");
|
|
887 |
+ |
assert_eq!(message_of(&style, &f).unwrap().1, style.warning);
|
|
888 |
+ |
|
|
889 |
+ |
f.error = Some("what is wrong");
|
|
890 |
+ |
assert_eq!(message_of(&style, &f).unwrap().0, "what is wrong");
|
|
891 |
+ |
assert_eq!(message_of(&style, &f).unwrap().1, style.danger);
|
|
892 |
+ |
|
|
893 |
+ |
// A note carries its own tone, so a quiet one is not painted as a
|
|
894 |
+ |
// warning just for being a note.
|
|
895 |
+ |
f.error = None;
|
|
896 |
+ |
f.note = Some((Tone::Neutral, "an ordinary fact"));
|
|
897 |
+ |
assert_eq!(message_of(&style, &f).unwrap().1, style.content);
|
|
898 |
+ |
}
|
| 866 |
899 |
|
use super::*;
|
| 867 |
900 |
|
use makeover_layout::{Choice, State};
|
| 868 |
901 |
|
|