egui_probe/
option.rs

1use crate::{EguiProbe, Style};
2
3impl<T> EguiProbe for Option<T>
4where
5    T: EguiProbe + Default,
6{
7    #[inline(always)]
8    fn probe(&mut self, ui: &mut egui::Ui, style: &Style) -> egui::Response {
9        option_probe_with(self, ui, style, T::default, |value, ui, style| {
10            value.probe(ui, style)
11        })
12    }
13
14    #[inline(always)]
15    fn iterate_inner(
16        &mut self,
17        ui: &mut egui::Ui,
18        f: &mut dyn FnMut(&str, &mut egui::Ui, &mut dyn EguiProbe),
19    ) {
20        if let Some(value) = self {
21            value.iterate_inner(ui, f);
22        }
23    }
24}
25
26#[inline(always)]
27pub fn option_probe_with<T>(
28    value: &mut Option<T>,
29    ui: &mut egui::Ui,
30    style: &Style,
31    default: impl FnOnce() -> T,
32    probe: impl FnOnce(&mut T, &mut egui::Ui, &Style) -> egui::Response,
33) -> egui::Response {
34    let mut changed = false;
35    let mut r = ui
36        .horizontal(|ui| {
37            let mut checked = value.is_some();
38
39            if ui.selectable_label(!checked, "None").clicked() {
40                checked = false;
41            }
42            if ui.selectable_label(checked, "Some").clicked() {
43                checked = true;
44            }
45
46            match (checked, value.is_some()) {
47                (true, false) => {
48                    *value = Some(default());
49                    changed = true;
50                }
51                (false, true) => {
52                    *value = None;
53                    changed = true;
54                }
55                _ => {}
56            }
57
58            if let Some(value) = value {
59                changed |= probe(value, ui, style).changed();
60            }
61        })
62        .response;
63
64    if changed {
65        r.mark_changed();
66    }
67
68    r
69}