Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show all loaded applications in recordings panel #5766

Merged
merged 15 commits into from
Apr 4, 2024
Merged
55 changes: 55 additions & 0 deletions crates/re_data_ui/src/app_id.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
use itertools::Itertools as _;

use re_entity_db::EntityDb;
use re_log_types::ApplicationId;
use re_viewer_context::{UiVerbosity, ViewerContext};

use crate::item_ui::entity_db_button_ui;

impl crate::DataUi for ApplicationId {
fn data_ui(
&self,
ctx: &ViewerContext<'_>,
ui: &mut egui::Ui,
verbosity: UiVerbosity,
_query: &re_data_store::LatestAtQuery,
_store: &re_data_store::DataStore,
) {
egui::Grid::new("application_id")
.num_columns(2)
.show(ui, |ui| {
ui.label("Application ID");
ui.label(self.to_string());
if self == &ctx.store_context.app_id {
ui.label("(active)");
}
ui.end_row();
});

if verbosity == UiVerbosity::Small {
return;
}

// Find all recordings with this app id
let recordings: Vec<&EntityDb> = ctx
Comment on lines +33 to +34
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice to have the blueprints here as well.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe, but could also be very confusing. Do we show all the blueprints? Or just the active and default ones? What if the active and default are the same? Etc. I opted to keep it simple for now.

.store_context
.bundle
.recordings()
.filter(|db| db.app_id() == Some(self))
.sorted_by_key(|entity_db| entity_db.store_info().map(|info| info.started))
.collect();

if !recordings.is_empty() {
ui.scope(|ui| {
ui.set_clip_rect(ui.max_rect()); // TODO(#5740): Hack required because `entity_db_button_ui` uses `ListItem`, which fills the full width until the clip rect.
ui.spacing_mut().item_spacing.y = 0.0;

ui.add_space(8.0);
ui.strong("Loaded recordings for this app");
for entity_db in recordings {
entity_db_button_ui(ctx, ui, entity_db, true);
}
});
}
}
}
37 changes: 18 additions & 19 deletions crates/re_data_ui/src/data_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ impl crate::DataUi for re_smart_channel::SmartChannelSource {
for other in ctx
.store_context
.bundle
.entity_dbs_from_channel_source(self)
.entity_dbs()
.filter(|db| db.data_source.as_ref() == Some(self))
{
let is_clone = other.cloned_from().is_some();
if is_clone {
Expand All @@ -46,30 +47,28 @@ impl crate::DataUi for re_smart_channel::SmartChannelSource {
}
}

if !recordings.is_empty() {
ui.add_space(8.0);
ui.strong("Recordings from this data source");
let max_rect = ui.max_rect();
ui.indent("recordings", |ui| {
ui.set_clip_rect(max_rect); // TODO(#5740): Hack required because `entity_db_button_ui` uses `ListItem`, which fills the full width until the clip rect.
ui.spacing_mut().item_spacing.y = 0.0;
recordings.sort_by_key(|entity_db| entity_db.store_info().map(|info| info.started));
blueprints.sort_by_key(|entity_db| entity_db.store_info().map(|info| info.started));

ui.scope(|ui| {
ui.set_clip_rect(ui.max_rect()); // TODO(#5740): Hack required because `entity_db_button_ui` uses `ListItem`, which fills the full width until the clip rect.
ui.spacing_mut().item_spacing.y = 0.0;

if !recordings.is_empty() {
ui.add_space(8.0);
ui.strong("Recordings from this data source");
for entity_db in recordings {
entity_db_button_ui(ctx, ui, entity_db, true);
}
});
}
}

if !blueprints.is_empty() {
ui.add_space(8.0);
ui.strong("Blueprints from this data source");
let max_rect = ui.max_rect();
ui.indent("blueprints", |ui| {
ui.set_clip_rect(max_rect); // TODO(#5740): Hack required because `entity_db_button_ui` uses `ListItem`, which fills the full width until the clip rect.
ui.spacing_mut().item_spacing.y = 0.0;
if !blueprints.is_empty() {
ui.add_space(8.0);
ui.strong("Blueprints from this data source");
for entity_db in blueprints {
entity_db_button_ui(ctx, ui, entity_db, true);
}
});
}
}
});
}
}
2 changes: 1 addition & 1 deletion crates/re_data_ui/src/editors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ fn edit_marker_shape_ui(
);

for marker in MarkerShape::ALL {
let list_item = re_ui::list_item::ListItem::new(ctx.re_ui, marker.to_string())
let list_item = re_ui::ListItem::new(ctx.re_ui, marker.to_string())
.with_icon_fn(|_re_ui, ui, rect, visuals| {
paint_marker(ui, marker.into(), rect, visuals.text_color());
})
Expand Down
4 changes: 2 additions & 2 deletions crates/re_data_ui/src/entity_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use re_log_types::StoreKind;
use re_types::SizeBytes;
use re_viewer_context::{UiVerbosity, ViewerContext};

use crate::item_ui::data_source_button_ui;
use crate::item_ui::{app_id_button_ui, data_source_button_ui};

impl crate::DataUi for EntityDb {
fn data_ui(
Expand Down Expand Up @@ -54,7 +54,7 @@ impl crate::DataUi for EntityDb {
}

re_ui.grid_left_hand_label(ui, "Application ID");
ui.label(application_id.to_string());
app_id_button_ui(ctx, ui, application_id);
ui.end_row();

re_ui.grid_left_hand_label(ui, "Source");
Expand Down
53 changes: 41 additions & 12 deletions crates/re_data_ui/src/item_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! 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::{ComponentPath, EntityPath, TimeInt, Timeline};
use re_log_types::{ApplicationId, ComponentPath, EntityPath, TimeInt, Timeline};
use re_ui::{icons, SyntaxHighlighting};
use re_viewer_context::{HoverHighlight, Item, SpaceViewId, UiVerbosity, ViewerContext};

Expand Down Expand Up @@ -551,6 +551,34 @@ pub fn entity_hover_card_ui(
instance_hover_card_ui(ui, ctx, query, store, &instance_path);
}

pub fn app_id_button_ui(
ctx: &ViewerContext<'_>,
ui: &mut egui::Ui,
app_id: &ApplicationId,
) -> egui::Response {
let item = Item::AppId(app_id.clone());

let response = ctx.re_ui.selectable_label_with_icon(
ui,
&icons::APPLICATION,
app_id.to_string(),
ctx.selection().contains_item(&item),
re_ui::LabelStyle::Normal,
);

let response = response.on_hover_ui(|ui| {
app_id.data_ui(
ctx,
ui,
re_viewer_context::UiVerbosity::Reduced,
&ctx.current_query(), // unused
ctx.recording_store(), // unused
);
});

cursor_interact_with_selectable(ctx, response, item)
}

pub fn data_source_button_ui(
ctx: &ViewerContext<'_>,
ui: &mut egui::Ui,
Expand Down Expand Up @@ -579,6 +607,7 @@ pub fn data_source_button_ui(
cursor_interact_with_selectable(ctx, response, item)
}

/// This uses [`re_ui::ListItem::show_hierarchical`], meaning it comes with built-in indentation.
pub fn store_id_button_ui(
ctx: &ViewerContext<'_>,
ui: &mut egui::Ui,
Expand All @@ -594,6 +623,8 @@ pub fn store_id_button_ui(
/// Show button for a store (recording or blueprint).
///
/// You can set `include_app_id` to hide the App Id, but usually you want to show it.
///
/// This uses [`re_ui::ListItem::show_hierarchical`], meaning it comes with built-in indentation.
pub fn entity_db_button_ui(
ctx: &ViewerContext<'_>,
ui: &mut egui::Ui,
Expand Down Expand Up @@ -666,17 +697,15 @@ pub fn entity_db_button_ui(
list_item = list_item.force_hovered(true);
}

let response = list_item
.show_flat(ui) // never more than one level deep
.on_hover_ui(|ui| {
entity_db.data_ui(
ctx,
ui,
re_viewer_context::UiVerbosity::Reduced,
&ctx.current_query(),
entity_db.store(),
);
});
let response = list_item.show_hierarchical(ui).on_hover_ui(|ui| {
entity_db.data_ui(
ctx,
ui,
re_viewer_context::UiVerbosity::Reduced,
&ctx.current_query(),
entity_db.store(),
);
});

if response.hovered() {
ctx.selection_state().set_hovered(item.clone());
Expand Down
1 change: 1 addition & 0 deletions crates/re_data_ui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use re_types::ComponentName;
use re_viewer_context::{UiVerbosity, ViewerContext};

mod annotation_context;
mod app_id;
mod blueprint_data;
mod component;
mod component_path;
Expand Down
15 changes: 3 additions & 12 deletions crates/re_entity_db/src/store_bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ impl StoreBundle {
}
}

pub fn remove(&mut self, id: &StoreId) {
self.entity_dbs.remove(id);
pub fn remove(&mut self, id: &StoreId) -> Option<EntityDb> {
self.entity_dbs.remove(id)
}

// --
Expand Down Expand Up @@ -134,16 +134,6 @@ impl StoreBundle {
.filter(|log| log.store_kind() == StoreKind::Blueprint)
}

/// All stores that came from the given source
pub fn entity_dbs_from_channel_source<'a>(
&'a self,
source: &'a re_smart_channel::SmartChannelSource,
) -> impl Iterator<Item = &EntityDb> + 'a {
self.entity_dbs
.values()
.filter(move |db| db.data_source.as_ref() == Some(source))
}

// --

pub fn retain(&mut self, mut f: impl FnMut(&EntityDb) -> bool) {
Expand All @@ -154,6 +144,7 @@ impl StoreBundle {
self.entity_dbs.retain(|_, entity_db| !entity_db.is_empty());
}

/// In no particular order.
pub fn drain_entity_dbs(&mut self) -> impl Iterator<Item = EntityDb> + '_ {
self.entity_dbs.drain().map(|(_, store)| store)
}
Expand Down
2 changes: 1 addition & 1 deletion crates/re_space_view_spatial/src/ui_3d.rs
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,7 @@ pub fn view_3d(
// Track focused entity if any.
if let Some(focused_item) = ctx.focused_item {
let focused_entity = match focused_item {
Item::DataSource(_) | Item::StoreId(_) | Item::Container(_) => None,
Item::AppId(_) | Item::DataSource(_) | Item::StoreId(_) | Item::Container(_) => None,

Item::SpaceView(space_view_id) => {
if space_view_id == &query.space_view_id {
Expand Down
Binary file added crates/re_ui/data/icons/application.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion crates/re_ui/examples/re_ui_example.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use re_ui::list_item::ListItem;
use re_ui::ListItem;
use re_ui::{toasts, CommandPalette, ReUi, UICommand, UICommandSender};

/// Sender that queues up the execution of a command.
Expand Down
2 changes: 1 addition & 1 deletion crates/re_ui/src/drag_and_drop.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Helpers for drag and drop support for reordering hierarchical lists.
//!
//! Works well in combination with [`crate::list_item::ListItem`].
//! Works well in combination with [`crate::ListItem`].

pub enum ItemKind<ItemId: Copy> {
/// Root container item.
Expand Down
4 changes: 4 additions & 0 deletions crates/re_ui/src/icons.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ pub const ENTITY_EMPTY: Icon = Icon::new(
pub const LINK: Icon = Icon::new("link", include_bytes!("../data/icons/link.png"));
pub const COMPONENT: Icon = Icon::new("component", include_bytes!("../data/icons/component.png"));

pub const APPLICATION: Icon = Icon::new(
"application",
include_bytes!("../data/icons/application.png"),
);
pub const DATA_SOURCE: Icon = Icon::new(
"data_source",
include_bytes!("../data/icons/data_source.png"),
Expand Down
28 changes: 17 additions & 11 deletions crates/re_ui/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,16 @@ pub mod list_item;
pub mod modal;
pub mod toasts;

pub use command::{UICommand, UICommandSender};
pub use command_palette::CommandPalette;
pub use design_tokens::DesignTokens;
pub use icons::Icon;
pub use layout_job_builder::LayoutJobBuilder;
pub use syntax_highlighting::SyntaxHighlighting;
pub use toggle_switch::toggle_switch;
pub use self::{
command::{UICommand, UICommandSender},
command_palette::CommandPalette,
design_tokens::DesignTokens,
icons::Icon,
layout_job_builder::LayoutJobBuilder,
list_item::ListItem,
syntax_highlighting::SyntaxHighlighting,
toggle_switch::toggle_switch,
};

// ---------------------------------------------------------------------------

Expand Down Expand Up @@ -62,10 +65,11 @@ pub enum LabelStyle {

// ----------------------------------------------------------------------------

use crate::list_item::ListItem;
use egui::emath::{Rangef, Rot2};
use egui::epaint::util::FloatOrd;
use egui::{pos2, Align2, CollapsingResponse, Color32, Mesh, NumExt, Rect, Shape, Vec2, Widget};
use egui::{
epaint::util::FloatOrd, pos2, Align2, CollapsingResponse, Color32, Mesh, NumExt, Rect, Shape,
Vec2, Widget,
};

#[derive(Clone)]
pub struct ReUi {
Expand Down Expand Up @@ -538,7 +542,7 @@ impl ReUi {
}

/// Popup similar to [`egui::popup_below_widget`] but suitable for use with
/// [`crate::list_item::ListItem`].
/// [`crate::ListItem`].
pub fn list_item_popup<R>(
ui: &egui::Ui,
popup_id: egui::Id,
Expand Down Expand Up @@ -931,6 +935,8 @@ impl ReUi {
}

/// Workaround for putting a label into a grid at the top left of its row.
///
/// You only need to use this if you expect the right side to have multi-line entries.
#[allow(clippy::unused_self)]
pub fn grid_left_hand_label(&self, ui: &mut egui::Ui, label: &str) -> egui::Response {
ui.with_layout(egui::Layout::left_to_right(egui::Align::TOP), |ui| {
Expand Down
Loading
Loading