| 331 |
331 |
|
}
|
| 332 |
332 |
|
}
|
| 333 |
333 |
|
|
| 334 |
|
- |
/// The three shapes a control comes in here, which is fewer than there are
|
|
334 |
+ |
/// The four shapes a control comes in here, which is fewer than there are
|
| 335 |
335 |
|
/// kinds.
|
| 336 |
336 |
|
///
|
| 337 |
337 |
|
/// [`FieldKind`] is `#[non_exhaustive]` and grows; this does not, because the
|
| 342 |
342 |
|
enum Control {
|
| 343 |
343 |
|
/// Typed into, so it is drawn as a well: the user looks into it.
|
| 344 |
344 |
|
Typed,
|
| 345 |
|
- |
/// Picked from. Pressed rather than looked into, so egui's own control
|
| 346 |
|
- |
/// painting stands.
|
|
345 |
+ |
/// Picked from a control that shows one option at a time. Pressed rather
|
|
346 |
+ |
/// than looked into, so egui's own control painting stands.
|
| 347 |
347 |
|
Chosen,
|
|
348 |
+ |
/// Picked from options that are all on screen at once.
|
|
349 |
+ |
///
|
|
350 |
+ |
/// Apart from [`Chosen`](Self::Chosen) because the description holds them
|
|
351 |
+ |
/// apart, and holding them apart is the whole content of
|
|
352 |
+ |
/// [`FieldKind::Radio`]: same question, and an answer the user can read
|
|
353 |
+ |
/// without opening anything.
|
|
354 |
+ |
Listed,
|
| 348 |
355 |
|
/// Held on or off.
|
| 349 |
356 |
|
Toggled,
|
| 350 |
357 |
|
}
|
| 357 |
364 |
|
const fn control_shape(kind: FieldKind) -> Control {
|
| 358 |
365 |
|
match kind {
|
| 359 |
366 |
|
FieldKind::Select => Control::Chosen,
|
|
367 |
+ |
FieldKind::Radio => Control::Listed,
|
| 360 |
368 |
|
FieldKind::Checkbox => Control::Toggled,
|
| 361 |
369 |
|
_ => Control::Typed,
|
| 362 |
370 |
|
}
|
| 421 |
429 |
|
};
|
| 422 |
430 |
|
ui.checkbox(on, RichText::new(field.label).color(palette.content))
|
| 423 |
431 |
|
}
|
|
432 |
+ |
Control::Listed => {
|
|
433 |
+ |
let value = match filling {
|
|
434 |
+ |
Filling::Text(text) => text,
|
|
435 |
+ |
_ => &mut discard,
|
|
436 |
+ |
};
|
|
437 |
+ |
// No `shown_label` counterpart, and none is needed: a value no
|
|
438 |
+ |
// option carries leaves every button unfilled, which is already
|
|
439 |
+ |
// the honest report on screen. The select needs the fix because it
|
|
440 |
+ |
// has one slot and must put *something* in it.
|
|
441 |
+ |
let group = ui.vertical(|ui| {
|
|
442 |
+ |
let mut answered: Option<Response> = None;
|
|
443 |
+ |
for opt in field.options {
|
|
444 |
+ |
let picked = ui.radio_value(
|
|
445 |
+ |
value,
|
|
446 |
+ |
opt.value.to_owned(),
|
|
447 |
+ |
RichText::new(opt.label).color(palette.content),
|
|
448 |
+ |
);
|
|
449 |
+ |
answered = Some(match answered {
|
|
450 |
+ |
Some(prev) => prev.union(picked),
|
|
451 |
+ |
None => picked,
|
|
452 |
+ |
});
|
|
453 |
+ |
}
|
|
454 |
+ |
answered
|
|
455 |
+ |
});
|
|
456 |
+ |
// A group described with no options answers as its own empty area
|
|
457 |
+ |
// rather than as no response at all, which keeps the caller's
|
|
458 |
+ |
// `.changed()` chain working on a field whose option list has not
|
|
459 |
+ |
// loaded yet.
|
|
460 |
+ |
group.inner.unwrap_or(group.response)
|
|
461 |
+ |
}
|
| 424 |
462 |
|
Control::Chosen => {
|
| 425 |
463 |
|
let value = match filling {
|
| 426 |
464 |
|
Filling::Text(text) => text,
|
| 659 |
697 |
|
// What decides whether the control gets a well. A well is for what the
|
| 660 |
698 |
|
// user looks into, and only one of these is.
|
| 661 |
699 |
|
assert_eq!(control_shape(FieldKind::Select), Control::Chosen);
|
|
700 |
+ |
assert_eq!(control_shape(FieldKind::Radio), Control::Listed);
|
| 662 |
701 |
|
assert_eq!(control_shape(FieldKind::Checkbox), Control::Toggled);
|
| 663 |
702 |
|
for k in [
|
| 664 |
703 |
|
FieldKind::Text,
|
| 673 |
712 |
|
}
|
| 674 |
713 |
|
}
|
| 675 |
714 |
|
|
|
715 |
+ |
#[test]
|
|
716 |
+ |
fn the_two_option_taking_kinds_are_drawn_differently_on_purpose() {
|
|
717 |
+ |
// The description holds Select and Radio apart, and a renderer that
|
|
718 |
+ |
// collapsed them would silently answer a question the app did not ask:
|
|
719 |
+ |
// audiofiles' storage style is irreversible and its alternatives have
|
|
720 |
+ |
// to be readable without opening anything. Asserting the two shapes
|
|
721 |
+ |
// differ is asserting that distinction survives the trip.
|
|
722 |
+ |
assert!(FieldKind::Select.offers_options());
|
|
723 |
+ |
assert!(FieldKind::Radio.offers_options());
|
|
724 |
+ |
assert_ne!(
|
|
725 |
+ |
control_shape(FieldKind::Select),
|
|
726 |
+ |
control_shape(FieldKind::Radio)
|
|
727 |
+ |
);
|
|
728 |
+ |
}
|
|
729 |
+ |
|
| 676 |
730 |
|
#[test]
|
| 677 |
731 |
|
fn a_hidden_field_draws_nothing_and_answers_nothing() {
|
| 678 |
732 |
|
// Where the two renderers legitimately part: a webview still emits an
|