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

More compact selection panel when multiple items selected #8351

Merged
merged 9 commits into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6143,6 +6143,7 @@ dependencies = [
"re_context_menu",
"re_data_ui",
"re_entity_db",
"re_format",
"re_log",
"re_log_types",
"re_space_view",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ fn edit_multiline_string_impl(
*value = edit_name.into();
response
} else {
UiLayout::SelectionPanelFull.data_label(ui, value.as_str())
UiLayout::SelectionPanel.data_label(ui, value.as_str())
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/viewer/re_component_ui/src/geo_line_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ fn multiline_view_geo_line_string(
// TODO(andreas): Editing this would be nice!
let value = value.as_ref();

UiLayout::SelectionPanelFull
UiLayout::SelectionPanel
.table(ui)
.resizable(true)
.cell_layout(egui::Layout::left_to_right(egui::Align::Center))
Expand Down
4 changes: 2 additions & 2 deletions crates/viewer/re_component_ui/src/line_strip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ fn multiline_view_line_strip_3d(

// TODO(andreas): Is it really a good idea to always have the full table here?
// Can we use the ui stack to know where we are and do the right thing instead?
UiLayout::SelectionPanelFull
UiLayout::SelectionPanel
.table(ui)
.resizable(true)
.cell_layout(egui::Layout::left_to_right(egui::Align::Center))
Expand Down Expand Up @@ -89,7 +89,7 @@ fn multiline_view_line_strip_2d(

// TODO(andreas): Is it really a good idea to always have the full table here?
// Can we use the ui stack to know where we are and do the right thing instead?
UiLayout::SelectionPanelFull
UiLayout::SelectionPanel
.table(ui)
.resizable(true)
.cell_layout(egui::Layout::left_to_right(egui::Align::Center))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,28 +36,25 @@ impl ContextMenuAction for AddEntitiesToNewSpaceViewAction {
.collect();

ui.menu_button("Add to new space view", |ui| {
let buttons_for_space_view_classes = |ui: &mut egui::Ui,
space_view_classes: &IntSet<
SpaceViewClassIdentifier,
>| {
for (identifier, class) in space_view_classes
.iter()
.map(|identifier| {
(
identifier,
space_view_class_registry.get_class_or_log_error(*identifier),
)
})
.sorted_by_key(|(_, class)| class.display_name().to_owned())
{
let btn =
egui::Button::image_and_text(class.icon().as_image(), class.display_name());
if ui.add(btn).clicked() {
create_space_view_for_selected_entities(ctx, *identifier);
ui.close_menu();
let buttons_for_space_view_classes =
|ui: &mut egui::Ui, space_view_classes: &IntSet<SpaceViewClassIdentifier>| {
for (identifier, class) in space_view_classes
.iter()
.map(|identifier| {
(
identifier,
space_view_class_registry.get_class_or_log_error(*identifier),
)
})
.sorted_by_key(|(_, class)| class.display_name().to_owned())
{
let btn = egui::Button::image_and_text(class.icon(), class.display_name());
if ui.add(btn).clicked() {
create_space_view_for_selected_entities(ctx, *identifier);
ui.close_menu();
}
}
}
};
};

ui.label(egui::WidgetText::from("Recommended:").italics());
if recommended_space_view_classes.is_empty() {
Expand Down
13 changes: 3 additions & 10 deletions crates/viewer/re_data_ui/src/annotation_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ impl DataUi for AnnotationContext {
};
ui_layout.label(ui, text);
}
UiLayout::SelectionPanelLimitHeight | UiLayout::SelectionPanelFull => {
UiLayout::SelectionPanel => {
ui.vertical(|ui| {
ui.maybe_collapsing_header(true, "Classes", true, |ui| {
let annotation_infos = self
Expand All @@ -153,7 +153,7 @@ impl DataUi for AnnotationContext {

fn class_description_ui(
ui: &mut egui::Ui,
mut ui_layout: UiLayout,
ui_layout: UiLayout,
class: &ClassDescription,
id: re_types::datatypes::ClassId,
) {
Expand All @@ -163,14 +163,7 @@ fn class_description_ui(

re_tracing::profile_function!();

let use_collapsible = ui_layout == UiLayout::SelectionPanelLimitHeight
|| ui_layout == UiLayout::SelectionPanelFull;

// We use collapsible header as a means for the user to limit the height, so the annotation info
// tables can be fully unrolled.
if ui_layout == UiLayout::SelectionPanelLimitHeight {
ui_layout = UiLayout::SelectionPanelFull;
}
let use_collapsible = ui_layout == UiLayout::SelectionPanel;

let row_height = DesignTokens::table_line_height();
if !class.keypoint_annotations.is_empty() {
Expand Down
8 changes: 3 additions & 5 deletions crates/viewer/re_data_ui/src/app_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,8 @@ impl crate::DataUi for ApplicationId {
let active_blueprint = ctx.store_context.blueprint;
let default_blueprint = ctx.store_context.hub.default_blueprint_for_app(self);

let button = egui::Button::image_and_text(
re_ui::icons::RESET.as_image(),
"Reset to default blueprint",
);
let button =
egui::Button::image_and_text(&re_ui::icons::RESET, "Reset to default blueprint");

let is_same_as_default = default_blueprint.map_or(false, |default_blueprint| {
default_blueprint.latest_row_id() == active_blueprint.latest_row_id()
Expand All @@ -95,7 +93,7 @@ impl crate::DataUi for ApplicationId {
}

if ui.add(egui::Button::image_and_text(
re_ui::icons::RESET.as_image(),
&re_ui::icons::RESET,
"Reset to heuristic blueprint",
)).on_hover_text("Clear both active and default blueprint, and auto-generate a new blueprint based on heuristics").clicked() {
ctx.command_sender
Expand Down
2 changes: 1 addition & 1 deletion crates/viewer/re_data_ui/src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ impl DataUi for ComponentPathLatestAtResults<'_> {
let max_row = match ui_layout {
UiLayout::List => 0,
UiLayout::Tooltip => num_instances.at_most(4), // includes "…x more" if any
UiLayout::SelectionPanelLimitHeight | UiLayout::SelectionPanelFull => num_instances,
UiLayout::SelectionPanel => num_instances,
};

let engine = db.storage_engine();
Expand Down
2 changes: 1 addition & 1 deletion crates/viewer/re_data_ui/src/instance_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ fn component_list_ui(
// types of components).
indicator_count == components.len()
}
UiLayout::SelectionPanelLimitHeight | UiLayout::SelectionPanelFull => true,
UiLayout::SelectionPanel => true,
UiLayout::List => false, // unreachable
};

Expand Down
6 changes: 3 additions & 3 deletions crates/viewer/re_selection_panel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,17 @@ workspace = true
all-features = true

[dependencies]
re_chunk_store.workspace = true
re_chunk.workspace = true
re_context_menu.workspace = true
re_chunk_store.workspace = true
re_data_ui.workspace = true
re_entity_db.workspace = true
re_format.workspace = true
re_log_types.workspace = true
re_log.workspace = true
re_space_view.workspace = true
re_tracing.workspace = true
# TODO(jleibs): Remove this once VisualizerOverrides is gone
re_types_blueprint.workspace = true
re_types_blueprint.workspace = true # TODO(jleibs): Remove this once VisualizerOverrides is gone
re_types_core.workspace = true
re_types.workspace = true
re_ui.workspace = true
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use egui::WidgetText;

use re_data_ui::item_ui::guess_instance_path_icon;
use re_log_types::ComponentPath;
use re_ui::{icons, Icon, SyntaxHighlighting};
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},
};

const ICON_SCALE: f32 = 0.5; // Because we save all icons as 2x
emilk marked this conversation as resolved.
Show resolved Hide resolved

/// Fully descriptive heading for an item, without any breadcrumbs.
pub 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::SpaceView(_) => {
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::SpaceView(*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().fit_to_original_size(ICON_SCALE));
ui.label(title);
}
Original file line number Diff line number Diff line change
Expand Up @@ -249,12 +249,13 @@ fn viewport_breadcrumbs(
}
cursor_interact_with_selectable(ctx, response, item);

separator_icon_ui(ui, icons::BREADCRUMBS_SEPARATOR);
separator_icon_ui(ui);
}

fn separator_icon_ui(ui: &mut egui::Ui, icon: re_ui::Icon) {
pub fn separator_icon_ui(ui: &mut egui::Ui) {
ui.add(
icon.as_image()
icons::BREADCRUMBS_SEPARATOR
.as_image()
.fit_to_original_size(ICON_SCALE)
.tint(ui.visuals().text_color().gamma_multiply(0.65)),
);
Expand Down Expand Up @@ -313,5 +314,5 @@ fn entity_path_breadcrumbs(
};
cursor_interact_with_selectable(ctx, response, item);

separator_icon_ui(ui, icons::BREADCRUMBS_SEPARATOR);
separator_icon_ui(ui);
}
33 changes: 19 additions & 14 deletions crates/viewer/re_selection_panel/src/item_title.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,17 @@ use re_viewer_context::{
};
use re_viewport_blueprint::ViewportBlueprint;

pub fn is_component_static(ctx: &ViewerContext<'_>, component_path: &ComponentPath) -> bool {
emilk marked this conversation as resolved.
Show resolved Hide resolved
let ComponentPath {
entity_path,
component_name,
} = component_path;
let (_query, db) = guess_query_and_db_for_selected_entity(ctx, entity_path);
db.storage_engine()
.store()
.entity_has_static_component(entity_path, component_name)
}

#[must_use]
pub struct ItemTitle {
pub icon: &'static re_ui::Icon,
Expand All @@ -30,14 +41,10 @@ impl ItemTitle {
item: &Item,
) -> Self {
match &item {
Item::AppId(app_id) => {
let title = app_id.to_string();
Self::new(title, &icons::APPLICATION)
}
Item::AppId(app_id) => Self::new(app_id.to_string(), &icons::APPLICATION),

Item::DataSource(data_source) => {
let title = data_source.to_string();
Self::new(title, &icons::DATA_SOURCE)
Self::new(data_source.to_string(), &icons::DATA_SOURCE)
}

Item::StoreId(store_id) => Self::from_store_id(ctx, store_id),
Expand Down Expand Up @@ -120,14 +127,12 @@ impl ItemTitle {
}

pub fn from_component_path(ctx: &ViewerContext<'_>, component_path: &ComponentPath) -> Self {
let entity_path = &component_path.entity_path;
let component_name = &component_path.component_name;

let (_query, db) = guess_query_and_db_for_selected_entity(ctx, entity_path);
let is_static = db
.storage_engine()
.store()
.entity_has_static_component(entity_path, component_name);
let is_static = is_component_static(ctx, component_path);

let ComponentPath {
entity_path,
component_name,
} = component_path;

Self::new(
component_name.short_name(),
Expand Down
1 change: 1 addition & 0 deletions crates/viewer/re_selection_panel/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! The UI for the selection panel.

mod defaults_ui;
mod item_heading_no_breadcrumbs;
mod item_heading_with_breadcrumbs;
mod item_title;
mod selection_panel;
Expand Down
Loading
Loading