diff --git a/crates/re_data_ui/src/item_ui.rs b/crates/re_data_ui/src/item_ui.rs index 9cca518e2ec0..261c1bb61af5 100644 --- a/crates/re_data_ui/src/item_ui.rs +++ b/crates/re_data_ui/src/item_ui.rs @@ -3,7 +3,6 @@ //! TODO(andreas): This is not a `data_ui`, can this go somewhere else, shouldn't be in `re_data_ui`. use re_entity_db::{EntityTree, InstancePath}; -use re_log_types::external::re_types_core::components::InstanceKey; use re_log_types::{ComponentPath, EntityPath, TimeInt, Timeline}; use re_ui::SyntaxHighlighting; use re_viewer_context::{HoverHighlight, Item, SpaceViewId, UiVerbosity, ViewerContext}; @@ -62,22 +61,29 @@ pub fn entity_path_parts_buttons( space_view_id: Option, entity_path: &EntityPath, ) -> egui::Response { + let with_icon = false; // too much noise with icons in a path + ui.horizontal(|ui| { - ui.spacing_mut().item_spacing.x = 4.0; + ui.spacing_mut().item_spacing.x = 2.0; + + // Show one single icon up-front instead: + let instance_path = InstancePath::entity_splat(entity_path.clone()); + ui.add(instance_path_icon(&query.timeline, store, &instance_path).as_image()); let mut accumulated = Vec::new(); for part in entity_path.iter() { accumulated.push(part.clone()); ui.strong("/"); - entity_path_button_to( + instance_path_button_to_ex( ctx, query, store, ui, space_view_id, - &accumulated.clone().into(), + &InstancePath::entity_splat(accumulated.clone().into()), part.syntax_highlighted(ui.style()), + with_icon, ); } }) @@ -134,17 +140,19 @@ pub fn instance_path_icon( store: &re_data_store::DataStore, instance_path: &InstancePath, ) -> &'static re_ui::icons::Icon { - if instance_path.instance_key != InstanceKey::SPLAT { - return &re_ui::icons::ENTITY; - } - - if store - .all_components(timeline, &instance_path.entity_path) - .is_some() - { - &re_ui::icons::ENTITY + if instance_path.is_splat() { + // It is an entity path + if store + .all_components(timeline, &instance_path.entity_path) + .is_some() + { + &re_ui::icons::ENTITY + } else { + &re_ui::icons::ENTITY_EMPTY + } } else { - &re_ui::icons::ENTITY_EMPTY + // An instance path + &re_ui::icons::ENTITY } } @@ -190,6 +198,30 @@ pub fn instance_path_button_to( space_view_id: Option, instance_path: &InstancePath, text: impl Into, +) -> egui::Response { + instance_path_button_to_ex( + ctx, + query, + store, + ui, + space_view_id, + instance_path, + text, + true, + ) +} + +/// Show an instance id and make it selectable. +#[allow(clippy::too_many_arguments)] +fn instance_path_button_to_ex( + ctx: &ViewerContext<'_>, + query: &re_data_store::LatestAtQuery, + store: &re_data_store::DataStore, + ui: &mut egui::Ui, + space_view_id: Option, + instance_path: &InstancePath, + text: impl Into, + with_icon: bool, ) -> egui::Response { let item = if let Some(space_view_id) = space_view_id { Item::DataResult(space_view_id, instance_path.clone()) @@ -197,18 +229,21 @@ pub fn instance_path_button_to( Item::InstancePath(instance_path.clone()) }; - let response = ctx - .re_ui - .selectable_label_with_icon( + let response = if with_icon { + ctx.re_ui.selectable_label_with_icon( ui, instance_path_icon(&query.timeline, store, instance_path), text, ctx.selection().contains_item(&item), re_ui::LabelStyle::Normal, ) - .on_hover_ui(|ui| { - instance_hover_card_ui(ui, ctx, query, store, instance_path); - }); + } else { + ui.selectable_label(ctx.selection().contains_item(&item), text) + }; + + let response = response.on_hover_ui(|ui| { + instance_hover_card_ui(ui, ctx, query, store, instance_path); + }); cursor_interact_with_selectable(ctx, response, item) } @@ -222,28 +257,34 @@ pub fn instance_path_parts_buttons( space_view_id: Option, instance_path: &InstancePath, ) -> egui::Response { + let with_icon = false; // too much noise with icons in a path + ui.horizontal(|ui| { - ui.spacing_mut().item_spacing.x = 4.0; + ui.spacing_mut().item_spacing.x = 2.0; + + // Show one single icon up-front instead: + ui.add(instance_path_icon(&query.timeline, store, instance_path).as_image()); let mut accumulated = Vec::new(); for part in instance_path.entity_path.iter() { accumulated.push(part.clone()); ui.strong("/"); - entity_path_button_to( + instance_path_button_to_ex( ctx, query, store, ui, space_view_id, - &accumulated.clone().into(), + &InstancePath::entity_splat(accumulated.clone().into()), part.syntax_highlighted(ui.style()), + with_icon, ); } if !instance_path.instance_key.is_splat() { ui.strong("/"); - instance_path_button_to( + instance_path_button_to_ex( ctx, query, store, @@ -251,6 +292,7 @@ pub fn instance_path_parts_buttons( space_view_id, instance_path, instance_path.instance_key.syntax_highlighted(ui.style()), + with_icon, ); } }) diff --git a/crates/re_viewer/src/ui/selection_panel.rs b/crates/re_viewer/src/ui/selection_panel.rs index 9dd09ffad9e8..84136ab00b68 100644 --- a/crates/re_viewer/src/ui/selection_panel.rs +++ b/crates/re_viewer/src/ui/selection_panel.rs @@ -316,6 +316,7 @@ fn what_is_selected_ui( item_title_ui(ctx.re_ui, ui, &title, Some(&re_ui::icons::STORE), &id_str); } + Item::Container(container_id) => { if let Some(container_blueprint) = viewport.container(container_id) { item_title_ui( @@ -329,6 +330,7 @@ fn what_is_selected_ui( ); } } + Item::ComponentPath(re_log_types::ComponentPath { entity_path, component_name, @@ -354,6 +356,7 @@ fn what_is_selected_ui( list_existing_data_blueprints(ui, ctx, &entity_path.clone().into(), viewport); } + Item::SpaceView(space_view_id) => { if let Some(space_view) = viewport.space_view(space_view_id) { let space_view_class = space_view.class(ctx.space_view_class_registry); @@ -381,20 +384,10 @@ fn what_is_selected_ui( .on_hover_text(hover_text); } } - Item::InstancePath(instance_path) => { - let is_instance = !instance_path.instance_key.is_splat(); + Item::InstancePath(instance_path) => { let typ = item.kind(); - - let (query, store) = - guess_query_and_store_for_selected_entity(ctx, &instance_path.entity_path); - let name = instance_path.syntax_highlighted(ui.style()); - let parent = if is_instance { - Some(instance_path.entity_path.clone()) - } else { - instance_path.entity_path.parent() - }; item_title_ui( ctx.re_ui, @@ -404,10 +397,18 @@ fn what_is_selected_ui( &format!("{typ} '{instance_path}'"), ); + let is_instance = !instance_path.instance_key.is_splat(); + let parent = if is_instance { + Some(instance_path.entity_path.clone()) + } else { + instance_path.entity_path.parent() + }; if let Some(parent) = parent { if !parent.is_root() { + let (query, store) = + guess_query_and_store_for_selected_entity(ctx, &instance_path.entity_path); ui.horizontal(|ui| { - ui.label("path"); + ui.label("Parent"); item_ui::entity_path_parts_buttons(ctx, &query, store, ui, None, &parent); }); } @@ -417,21 +418,10 @@ fn what_is_selected_ui( } Item::DataResult(space_view_id, instance_path) => { - let is_instance = !instance_path.instance_key.is_splat(); - - let typ = item.kind(); - - let (query, store) = - guess_query_and_store_for_selected_entity(ctx, &instance_path.entity_path); - let name = instance_path.syntax_highlighted(ui.style()); - let parent = if is_instance { - Some(instance_path.entity_path.clone()) - } else { - instance_path.entity_path.parent() - }; if let Some(space_view) = viewport.space_view(space_view_id) { + let typ = item.kind(); item_title_ui( ctx.re_ui, ui, @@ -443,10 +433,21 @@ fn what_is_selected_ui( ), ); + let is_instance = !instance_path.instance_key.is_splat(); + let parent = if is_instance { + Some(instance_path.entity_path.clone()) + } else { + instance_path.entity_path.parent() + }; if let Some(parent) = parent { if !parent.is_root() { ui.horizontal(|ui| { - ui.label("path"); + let (query, store) = guess_query_and_store_for_selected_entity( + ctx, + &instance_path.entity_path, + ); + + ui.label("Parent"); item_ui::entity_path_parts_buttons( ctx, &query,