Skip to content

Commit

Permalink
Initial support for manually adding container and space view in the h…
Browse files Browse the repository at this point in the history
…ierarchy (#4616)

### What

This is an initial take for the new so-called "additive workflow", which
enables building a hierarchy of container and space views from scratch.
It involves the following changes in UX:
- The automatic simplification of the container tree is (mostly)
disabled, as empty containers must be (temporarily) allowed while
building a hierarchy.
- Instead, a new "Simplify Container" button is available in the
Selection Panel to simplify the subtree under the selected container.
- A list if container children is displayed in the container Selection
Panel, with a button to add more.
- A new "Add Container or Space View" modal makes it possible to add a
container and/or a space view of any type in the selected container.
This feature is gated behind an experimental flag (Rerun Menu -> Options
-> Enable the container addition workflow).

<img width="1248" alt="image"
src="https://github.com/rerun-io/rerun/assets/49431240/0b58c298-d75c-480e-a88d-c1a5fe2265f5">

~~This PR also reorganises the experimental flags in the rerun menu such
that they are visible in web and release builds.~~ (superseded by #4661)

Fixes #4492 
Fixes #4493 

#### TODO (not necessarily in this PR)

- [x] Fix the hover/click UI of the big PLUS button in the modal.
- The PLUS button in the blueprint tree panel still shows the older
menu. This should reunified somehow (when we figure out how we want the
heuristics to show up): #4652
- Lots of container tree behaviour edge case to identify and fix.
- The modal really needs the new icons #4321
- Better hover highlight in the modal:
#4673

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using newly built examples:
[app.rerun.io](https://app.rerun.io/pr/4616/index.html)
* Using examples from latest `main` build:
[app.rerun.io](https://app.rerun.io/pr/4616/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[app.rerun.io](https://app.rerun.io/pr/4616/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG

- [PR Build Summary](https://build.rerun.io/pr/4616)
- [Docs
preview](https://rerun.io/preview/044dfdff939ae0e7bfa7effd2533a1026a11dd0f/docs)
<!--DOCS-PREVIEW-->
- [Examples
preview](https://rerun.io/preview/044dfdff939ae0e7bfa7effd2533a1026a11dd0f/examples)
<!--EXAMPLES-PREVIEW-->
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

---------

Co-authored-by: Jeremy Leibs <jeremy@rerun.io>
  • Loading branch information
abey79 and jleibs authored Jan 4, 2024
1 parent 790f391 commit 7342ff8
Show file tree
Hide file tree
Showing 9 changed files with 377 additions and 19 deletions.
Binary file added crates/re_ui/data/icons/add_big.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: 2 additions & 0 deletions crates/re_ui/src/icons.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ pub const VISIBLE: Icon = Icon::new("visible", include_bytes!("../data/icons/vis
pub const INVISIBLE: Icon = Icon::new("invisible", include_bytes!("../data/icons/invisible.png"));

pub const ADD: Icon = Icon::new("add", include_bytes!("../data/icons/add.png"));

pub const ADD_BIG: Icon = Icon::new("add_big", include_bytes!("../data/icons/add_big.png"));
pub const REMOVE: Icon = Icon::new("remove", include_bytes!("../data/icons/remove.png"));

pub const RESET: Icon = Icon::new("reset", include_bytes!("../data/icons/reset.png"));
Expand Down
165 changes: 165 additions & 0 deletions crates/re_viewer/src/ui/add_space_view_or_container_modal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
//! Modal for adding a new space view of container to an existing target container.
use itertools::Itertools;

use re_log_types::{EntityPath, EntityPathFilter};
use re_space_view::DataQueryBlueprint;
use re_viewer_context::ViewerContext;
use re_viewport::{icon_for_container_kind, SpaceViewBlueprint, Viewport};

#[derive(Default)]
pub struct AddSpaceViewOrContainerModal {
target_container: Option<egui_tiles::TileId>,
modal_handler: re_ui::modal::ModalHandler,
}

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

pub fn ui(&mut self, ui: &mut egui::Ui, ctx: &ViewerContext<'_>, viewport: &Viewport<'_, '_>) {
self.modal_handler.ui(
ctx.re_ui,
ui,
|| re_ui::modal::Modal::new("Add Space View or Container"),
|_, ui, _| modal_ui(ui, ctx, viewport, self.target_container),
);
}
}

fn modal_ui(
ui: &mut egui::Ui,
ctx: &ViewerContext<'_>,
viewport: &Viewport<'_, '_>,
target_container: Option<egui_tiles::TileId>,
) {
ui.spacing_mut().item_spacing = egui::vec2(14.0, 10.0);

let container_data = [
(
"Tabs",
"Create a new tabbed container.",
egui_tiles::ContainerKind::Tabs,
),
(
"Horizontal",
"Create a new horizontal container.",
egui_tiles::ContainerKind::Horizontal,
),
(
"Vertical",
"Create a new vertical container.",
egui_tiles::ContainerKind::Vertical,
),
(
"Grid",
"Create a new grid container.",
egui_tiles::ContainerKind::Grid,
),
];

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);
}
}

ui.separator();

// space view of any kind
for space_view in ctx
.space_view_class_registry
.iter_registry()
.sorted_by_key(|entry| entry.class.display_name())
.map(|entry| {
SpaceViewBlueprint::new(
entry.class.identifier(),
&format!("empty {}", entry.class.display_name()),
&EntityPath::root(),
DataQueryBlueprint::new(entry.class.identifier(), EntityPathFilter::default()),
)
})
{
let icon = space_view.class(ctx.space_view_class_registry).icon();
let title = space_view
.class(ctx.space_view_class_registry)
.display_name();
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);
}
}
}

fn row_ui(ui: &mut egui::Ui, icon: &re_ui::Icon, title: &str, subtitle: &str) -> egui::Response {
let top_left_corner = ui.cursor().min;

ui.horizontal(|ui| {
//TODO(ab): move this to re_ui
//TODO(ab): use design token
let row_height = 42.0;
let icon_size = egui::vec2(18.0, 18.0);
let thumbnail_rounding = 6.0;

let thumbnail_content = |ui: &mut egui::Ui| {
let (rect, _) = ui.allocate_exact_size(icon_size, egui::Sense::hover());
icon.as_image()
.tint(ui.visuals().widgets.active.fg_stroke.color)
.paint_at(ui, rect);
};

egui::Frame {
inner_margin: egui::Margin::symmetric(
(62. - icon_size.x) / 2.0,
(row_height - icon_size.y) / 2.0,
), // should be 62x42 when combined with icon size
rounding: egui::Rounding::same(thumbnail_rounding),
fill: egui::Color32::from_gray(50),
..Default::default()
}
.show(ui, thumbnail_content);

ui.vertical(|ui| {
ui.strong(title);
ui.add_space(-5.0);

ui.add(egui::Label::new(subtitle).wrap(false));
});

ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| {
let right_coord = ui.cursor().max.x;

// interact with the entire row
let interact_rect = egui::Rect::from_min_max(
top_left_corner,
egui::pos2(right_coord, top_left_corner.y + row_height),
);

let response =
ui.interact(interact_rect, title.to_owned().into(), egui::Sense::click());
let tint = if response.hovered() {
ui.visuals().widgets.active.fg_stroke.color
} else {
ui.visuals().widgets.inactive.fg_stroke.color
};

ui.add(
re_ui::icons::ADD_BIG
.as_image()
.fit_to_exact_size(egui::vec2(24.0, 24.0))
.tint(tint),
);

response
})
.inner
})
.inner
}
2 changes: 1 addition & 1 deletion crates/re_viewer/src/ui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ 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 visible_history;

pub use blueprint_panel::blueprint_panel_ui;
Expand Down
13 changes: 13 additions & 0 deletions crates/re_viewer/src/ui/rerun_menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,19 @@ fn experimental_feature_ui(
)
.on_hover_text("Show an entity filter DSL when selecting a space-view.");

re_ui
.checkbox(
ui,
&mut app_options.experimental_additive_workflow,
"Enable the container addition workflow",
)
.on_hover_text(
"This flag enables the experimental container addition workflow, including:\n\
- Remove the automatic simplification of the container tree.\n\
- Add a 'Content' list in the selection panel when a container is selected.\n\
- Add the 'Add space view/container' modal, accessible from the selection panel.",
);

re_ui
.checkbox(
ui,
Expand Down
Loading

0 comments on commit 7342ff8

Please sign in to comment.