Skip to content

Commit 9562cea

Browse files
authored
Refactor selection panel (#8303)
### Related * Part of #4491 ### What Just moving some code around
1 parent 0e9d221 commit 9562cea

File tree

5 files changed

+259
-248
lines changed

5 files changed

+259
-248
lines changed
Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
use re_data_ui::item_ui::{guess_instance_path_icon, guess_query_and_db_for_selected_entity};
2+
use re_ui::{icons, list_item, DesignTokens, SyntaxHighlighting as _, UiExt as _};
3+
use re_viewer_context::{contents_name_style, Item, SystemCommandSender as _, ViewerContext};
4+
use re_viewport_blueprint::ViewportBlueprint;
5+
6+
#[must_use]
7+
pub struct ItemTitle {
8+
name: egui::WidgetText,
9+
hover: Option<String>,
10+
icon: &'static re_ui::Icon,
11+
label_style: Option<re_ui::LabelStyle>,
12+
}
13+
14+
impl ItemTitle {
15+
pub fn from_item(
16+
ctx: &ViewerContext<'_>,
17+
viewport: &ViewportBlueprint,
18+
style: &egui::Style,
19+
item: &Item,
20+
) -> Option<Self> {
21+
match &item {
22+
Item::AppId(app_id) => {
23+
let title = app_id.to_string();
24+
Some(Self::new(title, &icons::APPLICATION))
25+
}
26+
27+
Item::DataSource(data_source) => {
28+
let title = data_source.to_string();
29+
Some(Self::new(title, &icons::DATA_SOURCE))
30+
}
31+
32+
Item::StoreId(store_id) => {
33+
let id_str = format!("{} ID: {}", store_id.kind, store_id);
34+
35+
let title = if let Some(entity_db) = ctx.store_context.bundle.get(store_id) {
36+
if let Some(info) = entity_db.store_info() {
37+
let time = info
38+
.started
39+
.format_time_custom(
40+
"[hour]:[minute]:[second]",
41+
ctx.app_options.time_zone,
42+
)
43+
.unwrap_or("<unknown time>".to_owned());
44+
45+
format!("{} - {}", info.application_id, time)
46+
} else {
47+
id_str.clone()
48+
}
49+
} else {
50+
id_str.clone()
51+
};
52+
53+
let icon = match store_id.kind {
54+
re_log_types::StoreKind::Recording => &icons::RECORDING,
55+
re_log_types::StoreKind::Blueprint => &icons::BLUEPRINT,
56+
};
57+
58+
Some(Self::new(title, icon).with_tooltip(id_str))
59+
}
60+
61+
Item::Container(container_id) => {
62+
if let Some(container_blueprint) = viewport.container(container_id) {
63+
let hover_text =
64+
if let Some(display_name) = container_blueprint.display_name.as_ref() {
65+
format!(
66+
"{:?} container {display_name:?}",
67+
container_blueprint.container_kind,
68+
)
69+
} else {
70+
format!("Unnamed {:?} container", container_blueprint.container_kind,)
71+
};
72+
73+
let container_name = container_blueprint.display_name_or_default();
74+
Some(
75+
Self::new(
76+
container_name.as_ref(),
77+
re_viewer_context::icon_for_container_kind(
78+
&container_blueprint.container_kind,
79+
),
80+
)
81+
.with_label_style(contents_name_style(&container_name))
82+
.with_tooltip(hover_text),
83+
)
84+
} else {
85+
None
86+
}
87+
}
88+
89+
Item::ComponentPath(component_path) => {
90+
let entity_path = &component_path.entity_path;
91+
let component_name = &component_path.component_name;
92+
93+
let (_query, db) = guess_query_and_db_for_selected_entity(ctx, entity_path);
94+
let is_static = db
95+
.storage_engine()
96+
.store()
97+
.entity_has_static_component(entity_path, component_name);
98+
99+
Some(
100+
Self::new(
101+
component_name.short_name(),
102+
if is_static {
103+
&icons::COMPONENT_STATIC
104+
} else {
105+
&icons::COMPONENT_TEMPORAL
106+
},
107+
)
108+
.with_tooltip(format!(
109+
"{} component {} of entity '{}'",
110+
if is_static { "Static" } else { "Temporal" },
111+
component_name.full_name(),
112+
entity_path
113+
)),
114+
)
115+
}
116+
117+
Item::SpaceView(view_id) => {
118+
if let Some(view) = viewport.view(view_id) {
119+
let view_class = view.class(ctx.space_view_class_registry);
120+
121+
let hover_text = if let Some(display_name) = view.display_name.as_ref() {
122+
format!(
123+
"Space view {:?} of type {}",
124+
display_name,
125+
view_class.display_name()
126+
)
127+
} else {
128+
format!("Unnamed view of type {}", view_class.display_name())
129+
};
130+
131+
let view_name = view.display_name_or_default();
132+
133+
Some(
134+
Self::new(
135+
view_name.as_ref(),
136+
view.class(ctx.space_view_class_registry).icon(),
137+
)
138+
.with_label_style(contents_name_style(&view_name))
139+
.with_tooltip(hover_text),
140+
)
141+
} else {
142+
None
143+
}
144+
}
145+
146+
Item::InstancePath(instance_path) => {
147+
let typ = item.kind();
148+
let name = instance_path.syntax_highlighted(style);
149+
150+
Some(
151+
Self::new(name, guess_instance_path_icon(ctx, instance_path))
152+
.with_tooltip(format!("{typ} '{instance_path}'")),
153+
)
154+
}
155+
156+
Item::DataResult(view_id, instance_path) => {
157+
let name = instance_path.syntax_highlighted(style);
158+
159+
if let Some(view) = viewport.view(view_id) {
160+
let typ = item.kind();
161+
Some(
162+
Self::new(name, guess_instance_path_icon(ctx, instance_path)).with_tooltip(
163+
format!(
164+
"{typ} '{instance_path}' as shown in view {:?}",
165+
view.display_name
166+
),
167+
),
168+
)
169+
} else {
170+
None
171+
}
172+
}
173+
}
174+
}
175+
176+
fn new(name: impl Into<egui::WidgetText>, icon: &'static re_ui::Icon) -> Self {
177+
Self {
178+
name: name.into(),
179+
hover: None,
180+
icon,
181+
label_style: None,
182+
}
183+
}
184+
185+
#[inline]
186+
fn with_tooltip(mut self, hover: impl Into<String>) -> Self {
187+
self.hover = Some(hover.into());
188+
self
189+
}
190+
191+
#[inline]
192+
fn with_label_style(mut self, label_style: re_ui::LabelStyle) -> Self {
193+
self.label_style = Some(label_style);
194+
self
195+
}
196+
197+
pub fn ui(self, ctx: &ViewerContext<'_>, ui: &mut egui::Ui, item: &Item) {
198+
let Self {
199+
name,
200+
hover,
201+
icon,
202+
label_style,
203+
} = self;
204+
205+
let mut content = list_item::LabelContent::new(name).with_icon(icon);
206+
207+
if let Some(label_style) = label_style {
208+
content = content.label_style(label_style);
209+
}
210+
211+
let response = ui
212+
.list_item()
213+
.with_height(DesignTokens::title_bar_height())
214+
.selected(true)
215+
.show_flat(ui, content);
216+
217+
if response.clicked() {
218+
// If the user has multiple things selected but only wants to have one thing selected,
219+
// this is how they can do it.
220+
ctx.command_sender
221+
.send_system(re_viewer_context::SystemCommand::SetSelection(item.clone()));
222+
}
223+
224+
if let Some(hover) = hover {
225+
response.on_hover_text(hover);
226+
}
227+
}
228+
}

crates/viewer/re_selection_panel/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
//! The UI for the selection panel.
22
33
mod defaults_ui;
4+
mod item_title;
45
mod selection_history_ui;
56
mod selection_panel;
67
mod space_view_entity_picker;
78
mod space_view_space_origin_ui;
89
mod visible_time_range_ui;
910
mod visualizer_ui;
1011

12+
pub use item_title::ItemTitle;
1113
pub use selection_panel::SelectionPanel;
1214

1315
#[cfg(test)]

0 commit comments

Comments
 (0)