From f5c513235b011b25c34c732a92dff25f2eba81b7 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler Date: Wed, 1 May 2024 20:12:10 +0200 Subject: [PATCH] Update visualizer and overrides UI with list item2 --- crates/re_viewer/src/ui/override_ui.rs | 232 +++++++++------------ crates/re_viewer/src/ui/selection_panel.rs | 62 +++--- 2 files changed, 136 insertions(+), 158 deletions(-) diff --git a/crates/re_viewer/src/ui/override_ui.rs b/crates/re_viewer/src/ui/override_ui.rs index 0092235b6831..1a0a7f0340d9 100644 --- a/crates/re_viewer/src/ui/override_ui.rs +++ b/crates/re_viewer/src/ui/override_ui.rs @@ -82,114 +82,92 @@ pub fn override_ui( &data_result, ); - ui.end_row(); - let Some(overrides) = data_result.property_overrides else { return; }; - let components: Vec<_> = overrides + let components = overrides .resolved_component_overrides .into_iter() .sorted_by_key(|(c, _)| *c) - .filter(|(c, _)| component_to_vis.contains_key(c)) - .collect(); - - egui_extras::TableBuilder::new(ui) - .cell_layout(egui::Layout::left_to_right(egui::Align::Center)) - .auto_shrink([false, true]) - .column(egui_extras::Column::auto()) - .column(egui_extras::Column::auto()) - .column(egui_extras::Column::remainder()) - .body(|mut body| { - re_ui::ReUi::setup_table_body(&mut body); - let row_height = re_ui::ReUi::table_line_height(); - body.rows(row_height, components.len(), |mut row| { - if let Some(( - component_name, - OverridePath { - store_kind, - path: entity_path_overridden, - }, - )) = components.get(row.index()) - { - // Remove button - row.col(|ui| { - if ctx - .re_ui - .small_icon_button(ui, &re_ui::icons::CLOSE) - .clicked() - { - // Note: need to use the blueprint store since the data might - // not exist in the recording store. - ctx.save_empty_blueprint_component_name( - &overrides.individual_override_path, - *component_name, - ); - } - }); - // Component label - row.col(|ui| { - // NOTE: this is not a component button because it is not a component that exists in the recording, just in the blueprint. - // So we don't allow users to select it. - ui.label(component_name.short_name()) - .on_hover_text(component_name.full_name()); - }); - // Editor last to take up remainder of space - row.col(|ui| { - let component_data = match store_kind { - StoreKind::Blueprint => { - let store = ctx.store_context.blueprint.store(); - let query = ctx.blueprint_query; - ctx.store_context - .blueprint - .query_caches() - .latest_at( - store, - query, - entity_path_overridden, - [*component_name], - ) - .components - .get(component_name) - .cloned() /* arc */ - } - StoreKind::Recording => { - ctx.recording() - .query_caches() - .latest_at( - ctx.recording_store(), - &query, - entity_path_overridden, - [*component_name], - ) - .components - .get(component_name) - .cloned() /* arc */ - } - }; - - if let Some(results) = component_data { - ctx.component_ui_registry.edit_ui( - ctx, - ui, - UiVerbosity::Small, + .filter(|(c, _)| component_to_vis.contains_key(c)); + + ui.scope(|ui| { + ui.spacing_mut().item_spacing.y = 0.0; + for ( + ref component_name, + OverridePath { + ref store_kind, + path: ref entity_path_overridden, + }, + ) in components + { + let value_fn = |ui: &mut egui::Ui| { + // TODO(ab): we should use the built in value feature of PropertyContent instead of + // reinventing the wheel. + let component_data = match store_kind { + StoreKind::Blueprint => { + let store = ctx.store_context.blueprint.store(); + let query = ctx.blueprint_query; + ctx.store_context + .blueprint + .query_caches() + .latest_at(store, query, entity_path_overridden, [*component_name]) + .components + .get(component_name) + .cloned() /* arc */ + } + StoreKind::Recording => { + ctx.recording() + .query_caches() + .latest_at( + ctx.recording_store(), &query, - ctx.recording(), entity_path_overridden, + [*component_name], + ) + .components + .get(component_name) + .cloned() /* arc */ + } + }; + + if let Some(results) = component_data { + ctx.component_ui_registry.edit_ui( + ctx, + ui, + UiVerbosity::Small, + &query, + ctx.recording(), + entity_path_overridden, + &overrides.individual_override_path, + &results, + instance, + ); + } else { + // TODO(jleibs): Is it possible to set an override to empty and not confuse + // the situation with "not-overridden?". Maybe we hit this in cases of `[]` vs `[null]`. + ui.weak("(empty)"); + } + }; + + ctx.re_ui + .list_item2() + .interactive(false) + .show_flat( + ui, + re_ui::list_item2::PropertyContent::new(component_name.short_name()) + .action_button(&re_ui::icons::CLOSE, || { + ctx.save_empty_blueprint_component_name( &overrides.individual_override_path, - &results, - instance, + *component_name, ); - } else { - // TODO(jleibs): Is it possible to set an override to empty and not confuse - // the situation with "not-overridden?". Maybe we hit this in cases of `[]` vs `[null]`. - ui.weak("(empty)"); - } - }); - } - }); - }); + }) + .value_fn(|_, ui, _| value_fn(ui)), + ) + .on_hover_text(component_name.full_name()); + } + }); } #[allow(clippy::too_many_arguments)] @@ -353,43 +331,31 @@ pub fn override_visualizer_ui( &active_visualizers, ); - ui.end_row(); - - egui_extras::TableBuilder::new(ui) - .cell_layout(egui::Layout::left_to_right(egui::Align::Center)) - .auto_shrink([false, true]) - .column(egui_extras::Column::auto()) - .column(egui_extras::Column::remainder()) - .body(|mut body| { - re_ui::ReUi::setup_table_body(&mut body); - let row_height = re_ui::ReUi::table_line_height(); - body.rows(row_height, active_visualizers.len(), |mut row| { - if let Some(vis_name) = active_visualizers.get(row.index()) { - // Remove button - row.col(|ui| { - if ctx - .re_ui - .small_icon_button(ui, &re_ui::icons::CLOSE) - .clicked() - { - let component = VisualizerOverrides::from( - active_visualizers - .iter() - .filter(|v| *v != vis_name) - .map(|v| re_types_core::ArrowString::from(v.as_str())) - .collect::>(), - ); + ui.scope(|ui| { + ui.spacing_mut().item_spacing.y = 0.0; + + for viz_name in &active_visualizers { + ctx.re_ui.list_item2().interactive(false).show_flat( + ui, + // TODO(ab): use LabelContent instead, but it needs to have an option for the + // same action button as PropertyContent. + re_ui::list_item2::PropertyContent::new(viz_name.as_str()).action_button( + &re_ui::icons::CLOSE, + || { + let component = VisualizerOverrides::from( + active_visualizers + .iter() + .filter(|v| *v != viz_name) + .map(|v| re_types_core::ArrowString::from(v.as_str())) + .collect::>(), + ); - ctx.save_blueprint_component(override_path, &component); - } - }); - // Visualizer label - row.col(|ui| { - ui.label(vis_name.as_str()); - }); - } - }); - }); + ctx.save_blueprint_component(override_path, &component); + }, + ), + ); + } + }); }); } diff --git a/crates/re_viewer/src/ui/selection_panel.rs b/crates/re_viewer/src/ui/selection_panel.rs index d03bbcf72682..253e13848c90 100644 --- a/crates/re_viewer/src/ui/selection_panel.rs +++ b/crates/re_viewer/src/ui/selection_panel.rs @@ -71,35 +71,47 @@ impl SelectionPanel { // enclosing frame doesn't have inner margins. ui.set_clip_rect(ui.max_rect()); - ctx.re_ui.panel_content(ui, |_, ui| { - let hover = "The Selection View contains information and options about the \ + re_ui::list_item2::list_item_scope( + ui, + "selection_panel", + Some(ui.max_rect().x_range()), + |ui| { + ctx.re_ui.panel_content(ui, |_, ui| { + let hover = + "The Selection View contains information and options about the \ currently selected object(s)"; - ctx.re_ui - .panel_title_bar_with_buttons(ui, "Selection", Some(hover), |ui| { - let mut history = ctx.selection_state().history.lock(); - if let Some(selection) = self.selection_state_ui.selection_ui( - ctx.re_ui, + ctx.re_ui.panel_title_bar_with_buttons( ui, - viewport.blueprint, - &mut history, - ) { - ctx.selection_state().set_selection(selection); - } + "Selection", + Some(hover), + |ui| { + let mut history = ctx.selection_state().history.lock(); + if let Some(selection) = self.selection_state_ui.selection_ui( + ctx.re_ui, + ui, + viewport.blueprint, + &mut history, + ) { + ctx.selection_state().set_selection(selection); + } + }, + ); }); - }); - - // move the vertical spacing between the title and the content to _inside_ the scroll - // area - ui.add_space(-ui.spacing().item_spacing.y); - egui::ScrollArea::both() - .auto_shrink([false; 2]) - .show(ui, |ui| { - ui.add_space(ui.spacing().item_spacing.y); - ctx.re_ui.panel_content(ui, |_, ui| { - self.contents(ctx, ui, viewport); - }); - }); + // move the vertical spacing between the title and the content to _inside_ the scroll + // area + ui.add_space(-ui.spacing().item_spacing.y); + + egui::ScrollArea::both() + .auto_shrink([false; 2]) + .show(ui, |ui| { + ui.add_space(ui.spacing().item_spacing.y); + ctx.re_ui.panel_content(ui, |_, ui| { + self.contents(ctx, ui, viewport); + }); + }); + }, + ); }); }