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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
use egui::WidgetText;

use re_data_ui::item_ui::{cursor_interact_with_selectable, guess_instance_path_icon};
use re_log_types::ComponentPath;
use re_ui::{icons, list_item, Icon, SyntaxHighlighting, UiExt as _};
use re_viewer_context::{Item, ViewerContext};
use re_viewport_blueprint::ViewportBlueprint;

use crate::{
    item_heading_with_breadcrumbs::separator_icon_ui,
    item_title::{is_component_static, ItemTitle},
};

/// Just the title of the item; for when multiple items are selected
pub fn item_title_list_item(
    ctx: &ViewerContext<'_>,
    viewport: &ViewportBlueprint,
    ui: &mut egui::Ui,
    item: &Item,
) {
    let response = ui
        .list_item()
        .with_height(re_ui::DesignTokens::list_item_height())
        .interactive(true)
        .show_flat(
            ui,
            list_item::CustomContent::new(|ui, context| {
                ui.allocate_new_ui(
                    egui::UiBuilder::new()
                        .max_rect(context.rect)
                        .layout(egui::Layout::left_to_right(egui::Align::Center)),
                    |ui| {
                        ui.spacing_mut().item_spacing.x = 4.0;
                        ui.style_mut().interaction.selectable_labels = false;
                        item_heading_no_breadcrumbs(ctx, viewport, ui, item);
                    },
                );
            }),
        );
    cursor_interact_with_selectable(ctx, response, item.clone());
}

/// Fully descriptive heading for an item, without any breadcrumbs.
fn item_heading_no_breadcrumbs(
    ctx: &ViewerContext<'_>,
    viewport: &ViewportBlueprint,
    ui: &mut egui::Ui,
    item: &Item,
) {
    match item {
        Item::AppId(_)
        | Item::DataSource(_)
        | Item::StoreId(_)
        | Item::Container(_)
        | Item::View(_) => {
            let ItemTitle {
                icon,
                label,
                label_style: _, // no label
                tooltip: _,
            } = ItemTitle::from_item(ctx, viewport, ui.style(), item);

            icon_and_title(ui, icon, label);
        }
        Item::InstancePath(instance_path) => {
            icon_and_title(
                ui,
                guess_instance_path_icon(ctx, instance_path),
                instance_path.syntax_highlighted(ui.style()),
            );
        }
        Item::ComponentPath(component_path) => {
            let is_component_static = is_component_static(ctx, component_path);

            // Break up into entity path and component name:
            let ComponentPath {
                entity_path,
                component_name,
            } = component_path;

            item_heading_no_breadcrumbs(ctx, viewport, ui, &Item::from(entity_path.clone()));

            separator_icon_ui(ui);

            let component_icon = if is_component_static {
                &icons::COMPONENT_STATIC
            } else {
                &icons::COMPONENT_TEMPORAL
            };
            icon_and_title(
                ui,
                component_icon,
                component_name.syntax_highlighted(ui.style()),
            );
        }
        Item::DataResult(view_id, instance_path) => {
            // Break up into view and instance path:
            item_heading_no_breadcrumbs(ctx, viewport, ui, &Item::View(*view_id));
            separator_icon_ui(ui);
            item_heading_no_breadcrumbs(
                ctx,
                viewport,
                ui,
                &Item::InstancePath(instance_path.clone()),
            );
        }
    }
}

fn icon_and_title(ui: &mut egui::Ui, icon: &Icon, title: impl Into<WidgetText>) {
    ui.add(icon.as_image());
    ui.label(title);
}