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

Use the "Add Space View/Container" modal for the + button of the blueprint tree #5012

Merged
merged 3 commits into from
Feb 4, 2024
Merged
Show file tree
Hide file tree
Changes from all 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: 0 additions & 1 deletion crates/re_viewer/src/ui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ mod selection_history_ui;
mod top_panel;
mod welcome_screen;

pub(crate) mod add_space_view_or_container_modal;
pub(crate) mod memory_panel;
pub(crate) mod selection_panel;
pub(crate) mod space_view_space_origin_ui;
Expand Down
117 changes: 54 additions & 63 deletions crates/re_viewer/src/ui/selection_panel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ use re_viewport::{
Contents, Viewport, ViewportBlueprint,
};

use crate::ui::{
add_space_view_or_container_modal::AddSpaceViewOrContainerModal, override_ui::override_ui,
};
use crate::ui::override_ui::override_ui;
use crate::ui::{override_ui::override_visualizer_ui, visible_history::visible_history_ui};

use super::selection_history_ui::SelectionHistoryUi;
Expand All @@ -39,9 +37,6 @@ use super::selection_history_ui::SelectionHistoryUi;
#[serde(default)]
pub(crate) struct SelectionPanel {
selection_state_ui: SelectionHistoryUi,

#[serde(skip)]
add_space_view_or_container_modal: AddSpaceViewOrContainerModal,
}

/// The current time query, based on the current time control and an `entity_path`
Expand Down Expand Up @@ -164,7 +159,7 @@ impl SelectionPanel {
// blueprints feature
if ctx.app_options.experimental_additive_workflow {
ui.add_space(12.0);
self.container_children(ui, ctx, viewport, container_id);
container_children(ui, ctx, viewport, container_id);
}
}

Expand Down Expand Up @@ -228,71 +223,67 @@ impl SelectionPanel {
}
});
}

self.add_space_view_or_container_modal
.ui(ui.ctx(), ctx, viewport);
}
}

fn container_children(
&mut self,
ui: &mut egui::Ui,
ctx: &ViewerContext<'_>,
viewport: &Viewport<'_, '_>,
container_id: &ContainerId,
) {
let Some(container) = viewport.blueprint.container(container_id) else {
return;
};

ui.horizontal(|ui| {
ui.strong("Contents");
fn container_children(
ui: &mut egui::Ui,
ctx: &ViewerContext<'_>,
viewport: &mut Viewport<'_, '_>,
container_id: &ContainerId,
) {
let Some(container) = viewport.blueprint.container(container_id) else {
return;
};

ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
if ctx
.re_ui
.small_icon_button(ui, &re_ui::icons::ADD)
.clicked()
{
self.add_space_view_or_container_modal.open(*container_id);
}
});
ui.horizontal(|ui| {
ui.strong("Contents");

ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
if ctx
.re_ui
.small_icon_button(ui, &re_ui::icons::ADD)
.clicked()
{
viewport.show_add_space_view_or_container_modal(*container_id);
}
});
});

let show_content = |ui: &mut egui::Ui| {
let mut has_child = false;
for child_contents in &container.contents {
has_child |= show_list_item_for_container_child(ui, ctx, viewport, child_contents);
}
let show_content = |ui: &mut egui::Ui| {
let mut has_child = false;
for child_contents in &container.contents {
has_child |= show_list_item_for_container_child(ui, ctx, viewport, child_contents);
}

if !has_child {
ListItem::new(ctx.re_ui, "empty — use the + button to add content")
.weak(true)
.italics(true)
.active(false)
.show(ui);
}
};
if !has_child {
ListItem::new(ctx.re_ui, "empty — use the + button to add content")
.weak(true)
.italics(true)
.active(false)
.show(ui);
}
};

egui::Frame {
outer_margin: egui::Margin::ZERO,
inner_margin: egui::Margin::ZERO,
stroke: ui.visuals().widgets.noninteractive.bg_stroke,
..Default::default()
}
.show(ui, |ui| {
let clip_rect = ui.clip_rect();
ui.set_clip_rect(ui.max_rect());
ui.spacing_mut().item_spacing.y = 0.0;

egui::Frame {
outer_margin: egui::Margin::ZERO,
inner_margin: egui::Margin::ZERO,
stroke: ui.visuals().widgets.noninteractive.bg_stroke,
inner_margin: egui::Margin::symmetric(4.0, 0.0),
..Default::default()
}
.show(ui, |ui| {
let clip_rect = ui.clip_rect();
ui.set_clip_rect(ui.max_rect());
ui.spacing_mut().item_spacing.y = 0.0;

egui::Frame {
inner_margin: egui::Margin::symmetric(4.0, 0.0),
..Default::default()
}
.show(ui, show_content);
.show(ui, show_content);

ui.set_clip_rect(clip_rect);
});
}
ui.set_clip_rect(clip_rect);
});
}

fn data_section_ui(item: &Item) -> Option<Box<dyn DataUi>> {
Expand Down Expand Up @@ -861,7 +852,7 @@ fn blueprint_ui_for_space_view(
);

if response.clicked() {
viewport.show_add_remove_entities_window(*space_view_id);
viewport.show_add_remove_entities_modal(*space_view_id);
}
}

Expand Down Expand Up @@ -1152,7 +1143,7 @@ The last rule matching `/world/house` is `+ /world/**`, so it is included.
.on_hover_text("Modify the entity query using the editor")
.clicked()
{
viewport.show_add_remove_entities_window(*space_view_id);
viewport.show_add_remove_entities_modal(*space_view_id);
}
},
);
Expand Down
9 changes: 9 additions & 0 deletions crates/re_viewer_context/src/selection_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,15 @@ impl Selection {
self.0.first().map(|(item, _)| item)
}

/// Check if the selection contains a single item and returns it if so.
pub fn single_item(&self) -> Option<&Item> {
if self.0.len() == 1 {
Some(&self.0[0].0)
} else {
None
}
}

pub fn iter_items(&self) -> impl Iterator<Item = &Item> {
self.0.iter().map(|(item, _)| item)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

use itertools::Itertools;

use crate::{icon_for_container_kind, SpaceViewBlueprint, ViewportBlueprint};
use re_log_types::{EntityPath, EntityPathFilter};
use re_space_view::DataQueryBlueprint;
use re_ui::ReUi;
use re_viewer_context::{ContainerId, ViewerContext};
use re_viewport::{icon_for_container_kind, SpaceViewBlueprint, Viewport};

#[derive(Default)]
pub struct AddSpaceViewOrContainerModal {
Expand All @@ -15,16 +15,16 @@ pub struct AddSpaceViewOrContainerModal {
}

impl AddSpaceViewOrContainerModal {
pub fn open(&mut self, target_container: ContainerId) {
pub(crate) fn open(&mut self, target_container: ContainerId) {
self.target_container = Some(target_container);
self.modal_handler.open();
}

pub fn ui(
pub(crate) fn ui(
&mut self,
egui_ctx: &egui::Context,
ctx: &ViewerContext<'_>,
viewport: &Viewport<'_, '_>,
viewport: &ViewportBlueprint,
) {
self.modal_handler.ui(
ctx.re_ui,
Expand All @@ -42,7 +42,7 @@ impl AddSpaceViewOrContainerModal {
fn modal_ui(
ui: &mut egui::Ui,
ctx: &ViewerContext<'_>,
viewport: &Viewport<'_, '_>,
viewport: &ViewportBlueprint,
target_container: Option<ContainerId>,
keep_open: &mut bool,
) {
Expand Down Expand Up @@ -71,8 +71,8 @@ fn modal_ui(

for (title, subtitle, kind) in container_data {
if row_ui(ui, icon_for_container_kind(&kind), title, subtitle).clicked() {
viewport.blueprint.add_container(kind, target_container);
viewport.blueprint.mark_user_interaction(ctx);
viewport.add_container(kind, target_container);
viewport.mark_user_interaction(ctx);
*keep_open = false;
}
}
Expand All @@ -99,10 +99,8 @@ fn modal_ui(
let subtitle = format!("Create a new Space View to display {title} content.");

if row_ui(ui, icon, title, &subtitle).clicked() {
viewport
.blueprint
.add_space_views(std::iter::once(space_view), ctx, target_container);
viewport.blueprint.mark_user_interaction(ctx);
viewport.add_space_views(std::iter::once(space_view), ctx, target_container);
viewport.mark_user_interaction(ctx);
*keep_open = false;
}
}
Expand Down
3 changes: 2 additions & 1 deletion crates/re_viewport/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

pub const VIEWPORT_PATH: &str = "viewport";

mod add_space_view_or_container_modal;
mod auto_layout;
mod container;
mod space_view;
Expand All @@ -19,7 +20,7 @@ mod viewport_blueprint_ui;
///
/// They all implement the [`re_types_core::Component`] trait.
///
/// Unstable. Used for the ongoing blueprint experimentations.
/// Unstable. Used for the ongoing blueprint experimentation.
pub mod blueprint;

pub use container::{ContainerBlueprint, Contents};
Expand Down
26 changes: 21 additions & 5 deletions crates/re_viewport/src/viewport.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ use re_viewer_context::{

use crate::container::blueprint_id_to_tile_id;
use crate::{
container::Contents, icon_for_container_kind, space_view_entity_picker::SpaceViewEntityPicker,
add_space_view_or_container_modal::AddSpaceViewOrContainerModal, container::Contents,
icon_for_container_kind, space_view_entity_picker::SpaceViewEntityPicker,
space_view_heuristics::default_created_space_views,
system_execution::execute_systems_for_space_views, SpaceViewBlueprint, ViewportBlueprint,
};
Expand All @@ -34,7 +35,12 @@ pub struct PerSpaceViewState {
/// is not saved.
#[derive(Default)]
pub struct ViewportState {
space_view_entity_window: SpaceViewEntityPicker,
/// State for the "Add Entity" modal.
space_view_entity_modal: SpaceViewEntityPicker,

/// State for the "Add Space View or Container" modal.
add_space_view_container_modal: AddSpaceViewOrContainerModal,

space_view_states: HashMap<SpaceViewId, PerSpaceViewState>,

/// Current candidate parent container for the ongoing drop.
Expand Down Expand Up @@ -193,13 +199,23 @@ impl<'a, 'b> Viewport<'a, 'b> {
}
}

pub fn show_add_remove_entities_window(&mut self, space_view_id: SpaceViewId) {
self.state.space_view_entity_window.open(space_view_id);
pub fn show_add_remove_entities_modal(&mut self, space_view_id: SpaceViewId) {
self.state.space_view_entity_modal.open(space_view_id);
}

pub fn show_add_space_view_or_container_modal(&mut self, target_container: ContainerId) {
self.state
.add_space_view_container_modal
.open(target_container);
}

pub fn viewport_ui(&mut self, ui: &mut egui::Ui, ctx: &'a ViewerContext<'_>) {
// run modals (these are noop if the modals are not active)
self.state
.space_view_entity_modal
.ui(ui.ctx(), ctx, self.blueprint);
self.state
.space_view_entity_window
.add_space_view_container_modal
.ui(ui.ctx(), ctx, self.blueprint);

let Viewport {
Expand Down
26 changes: 26 additions & 0 deletions crates/re_viewport/src/viewport_blueprint_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,32 @@ impl Viewport<'_, '_> {
}

pub fn add_new_spaceview_button_ui(&mut self, ctx: &ViewerContext<'_>, ui: &mut egui::Ui) {
if ctx.app_options.experimental_additive_workflow {
if ctx
.re_ui
.small_icon_button(ui, &re_ui::icons::ADD)
.on_hover_text("Add a new Space View or Container")
.clicked()
{
// If a single container is selected, we use it as target. Otherwise, we target the
// root container.
let target_container_id =
if let Some(Item::Container(container_id)) = ctx.selection().single_item() {
Some(*container_id)
} else {
self.blueprint.root_container
};

if let Some(target_container_id) = target_container_id {
self.show_add_space_view_or_container_modal(target_container_id);
}
}
} else {
self.legacy_add_new_spaceview_popup_menu(ctx, ui);
}
}

fn legacy_add_new_spaceview_popup_menu(&mut self, ctx: &ViewerContext<'_>, ui: &mut egui::Ui) {
ui.menu_image_button(
re_ui::icons::ADD
.as_image()
Expand Down
Loading