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
use re_types::{components::MarkerShape, reflection::Enum as _};
use re_ui::UiExt as _;
use re_viewer_context::{MaybeMutRef, ViewerContext};

use crate::response_utils::response_with_changes_of_inner;

pub(crate) fn edit_marker_shape_ui(
    _ctx: &ViewerContext<'_>,
    ui: &mut egui::Ui,
    marker: &mut MaybeMutRef<'_, MarkerShape>,
) -> egui::Response {
    let item_width = 100.0;

    if let Some(edit_marker) = marker.as_mut() {
        let marker_text = edit_marker.to_string(); // TODO(emilk): Show marker shape in the selected text

        response_with_changes_of_inner(
            egui::ComboBox::from_id_salt("marker_shape")
                .selected_text(marker_text)
                .height(320.0)
                .show_ui(ui, |ui| {
                    let list_ui = |ui: &mut egui::Ui| {
                        let mut combined_response: Option<egui::Response> = None;
                        for &marker in MarkerShape::variants() {
                            let mut response =
                                ui.list_item().selected(*edit_marker == marker).show_flat(
                                    ui,
                                    re_ui::list_item::LabelContent::new(marker.to_string())
                                        .min_desired_width(item_width)
                                        .with_icon_fn(|ui, rect, visuals| {
                                            paint_marker(
                                                ui,
                                                marker.into(),
                                                rect,
                                                visuals.text_color(),
                                            );
                                        }),
                                );

                            if response.clicked() {
                                *edit_marker = marker;
                                response.mark_changed();
                            }

                            combined_response = Some(match combined_response {
                                Some(combined_response) => combined_response | response,
                                None => response,
                            });
                        }
                        combined_response.expect("At least one marker shape should be available")
                    };

                    re_ui::list_item::list_item_scope(ui, "marker_shape", list_ui)
                }),
        )
    } else {
        let marker: MarkerShape = *marker.as_ref();
        ui.list_item().interactive(false).show_hierarchical(
            ui,
            re_ui::list_item::LabelContent::new(marker.to_string())
                .min_desired_width(item_width)
                .with_icon_fn(|ui, rect, visuals| {
                    paint_marker(ui, marker.into(), rect, visuals.text_color());
                }),
        )
    }
}

pub(crate) fn paint_marker(
    ui: &egui::Ui,
    marker: egui_plot::MarkerShape,
    rect: egui::Rect,
    color: egui::Color32,
) {
    use egui_plot::PlotItem as _;

    let points = egui_plot::Points::new([0.0, 0.0])
        .shape(marker)
        .color(color)
        .radius(rect.size().min_elem() / 2.0)
        .filled(true);

    let bounds = egui_plot::PlotBounds::new_symmetrical(0.5);
    let transform = egui_plot::PlotTransform::new(rect, bounds, true);

    let mut shapes = vec![];
    points.shapes(ui, &transform, &mut shapes);
    ui.painter().extend(shapes);
}