Skip to content

Commit

Permalink
Make Space View containers selectable and editable (#4403)
Browse files Browse the repository at this point in the history
### What

Containers may now be selected and edited. For now, they can be
transmuted into another container type, and grid containers have a
setting for their column count.

- Closes #4162

<img width="1638" alt="image"
src="https://github.com/rerun-io/rerun/assets/49431240/28c43f1e-d25f-4f70-b41d-50a3ac20f99a">

### 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 [app.rerun.io](https://app.rerun.io/pr/4403) (if
applicable)
* [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/4403)
- [Docs
preview](https://rerun.io/preview/2f30366bc1db4ffc0f5b3a4b3a7f9e8b2dffd7b4/docs)
<!--DOCS-PREVIEW-->
- [Examples
preview](https://rerun.io/preview/2f30366bc1db4ffc0f5b3a4b3a7f9e8b2dffd7b4/examples)
<!--EXAMPLES-PREVIEW-->
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)
  • Loading branch information
abey79 authored Dec 1, 2023
1 parent e3dd6f3 commit 8881e21
Show file tree
Hide file tree
Showing 12 changed files with 173 additions and 22 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion crates/re_data_ui/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ impl DataUi for Item {
query: &re_arrow_store::LatestAtQuery,
) {
match self {
Item::SpaceView(_) | Item::DataBlueprintGroup(_, _, _) => {
Item::SpaceView(_) | Item::DataBlueprintGroup(_, _, _) | Item::Container(_) => {
// Shouldn't be reachable since SelectionPanel::contents doesn't show data ui for these.
// If you add something in here make sure to adjust SelectionPanel::contents accordingly.
}
Expand Down
2 changes: 1 addition & 1 deletion crates/re_time_panel/src/data_density_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,7 @@ fn show_row_ids_tooltip(
Item::InstancePath(_, path) => {
item_ui::instance_path_button(ctx, ui, None, path);
}
Item::SpaceView(_) | Item::DataBlueprintGroup(_, _, _) => {
Item::SpaceView(_) | Item::DataBlueprintGroup(_, _, _) | Item::Container(_) => {
// No extra info. This should never happen, but not worth printing a warning over.
// Even if it does go here, the ui after will still look ok.
}
Expand Down
1 change: 1 addition & 0 deletions crates/re_viewer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ eframe = { workspace = true, default-features = false, features = [
egui_plot.workspace = true
egui-wgpu.workspace = true
egui.workspace = true
egui_tiles.workspace = true
ehttp.workspace = true
image = { workspace = true, default-features = false, features = ["png"] }
itertools = { workspace = true }
Expand Down
18 changes: 18 additions & 0 deletions crates/re_viewer/src/ui/selection_history_ui.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use egui::RichText;
use egui_tiles::Tile;
use re_ui::UICommand;
use re_viewer_context::{Item, ItemCollection, SelectionHistory};
use re_viewport::ViewportBlueprint;
Expand Down Expand Up @@ -181,5 +182,22 @@ fn item_to_string(blueprint: &ViewportBlueprint<'_>, item: &Item) -> String {
Item::ComponentPath(path) => {
format!("{} {}", path.entity_path, path.component_name.short_name(),)
}
Item::Container(tile_id) => {
if let Some(tile) = blueprint.tree.tiles.get(*tile_id) {
match tile {
Tile::Pane(sid) => {
// This case shouldn't happen really.
if let Some(space_view) = blueprint.space_view(sid) {
format!("Tile showing {}", space_view.display_name)
} else {
"Tile containing unknown Space View".to_owned()
}
}
Tile::Container(container) => format!("{:?}", container.kind()),
}
} else {
"<removed Container>".to_owned()
}
}
}
}
123 changes: 113 additions & 10 deletions crates/re_viewer/src/ui/selection_panel.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use egui::NumExt as _;
use egui_tiles::{GridLayout, Tile};

use re_data_store::{
ColorMapper, Colormap, EditableAutoValue, EntityPath, EntityProperties, VisibleHistory,
Expand Down Expand Up @@ -116,13 +117,21 @@ impl SelectionPanel {
ui.push_id(i, |ui| {
what_is_selected_ui(ui, ctx, &mut viewport.blueprint, item);

if let Item::SpaceView(space_view_id) = item {
space_view_top_level_properties(
ui,
ctx,
&mut viewport.blueprint,
space_view_id,
);
match item {
Item::Container(tile_id) => {
container_top_level_properties(ui, ctx, &mut viewport.blueprint, tile_id);
}

Item::SpaceView(space_view_id) => {
space_view_top_level_properties(
ui,
ctx,
&mut viewport.blueprint,
space_view_id,
);
}

_ => {}
}

if has_data_section(item) {
Expand Down Expand Up @@ -151,7 +160,7 @@ fn has_data_section(item: &Item) -> bool {
match item {
Item::ComponentPath(_) | Item::InstancePath(_, _) => true,
// Skip data ui since we don't know yet what to show for these.
Item::SpaceView(_) | Item::DataBlueprintGroup(_, _, _) => false,
Item::SpaceView(_) | Item::DataBlueprintGroup(_, _, _) | Item::Container(_) => false,
}
}

Expand Down Expand Up @@ -185,6 +194,17 @@ fn what_is_selected_ui(
item: &Item,
) {
match item {
Item::Container(tile_id) => {
if let Some(Tile::Container(container)) = viewport.tree.tiles.get(*tile_id) {
item_title_ui(
ctx.re_ui,
ui,
&format!("{:?}", container.kind()),
None,
&format!("{:?} container", container.kind()),
);
}
}
Item::ComponentPath(re_log_types::ComponentPath {
entity_path,
component_name,
Expand Down Expand Up @@ -379,9 +399,92 @@ fn space_view_top_level_properties(
}
}

fn container_top_level_properties(
ui: &mut egui::Ui,
_ctx: &mut ViewerContext<'_>,
viewport: &mut ViewportBlueprint<'_>,
tile_id: &egui_tiles::TileId,
) {
if let Some(Tile::Container(container)) = viewport.tree.tiles.get_mut(*tile_id) {
egui::Grid::new("container_top_level_properties")
.num_columns(2)
.show(ui, |ui| {
ui.label("Kind");

let mut container_kind = container.kind();
egui::ComboBox::from_id_source("container_kind")
.selected_text(format!("{container_kind:?}"))
.show_ui(ui, |ui| {
ui.style_mut().wrap = Some(false);
ui.set_min_width(64.0);

ui.selectable_value(
&mut container_kind,
egui_tiles::ContainerKind::Tabs,
format!("{:?}", egui_tiles::ContainerKind::Tabs),
);
ui.selectable_value(
&mut container_kind,
egui_tiles::ContainerKind::Horizontal,
format!("{:?}", egui_tiles::ContainerKind::Horizontal),
);
ui.selectable_value(
&mut container_kind,
egui_tiles::ContainerKind::Vertical,
format!("{:?}", egui_tiles::ContainerKind::Vertical),
);
ui.selectable_value(
&mut container_kind,
egui_tiles::ContainerKind::Grid,
format!("{:?}", egui_tiles::ContainerKind::Grid),
);
});

container.set_kind(container_kind);

ui.end_row();

if let egui_tiles::Container::Grid(grid) = container {
ui.label("Columns");

fn grid_layout_to_string(layout: &egui_tiles::GridLayout) -> String {
match layout {
GridLayout::Auto => "Auto".to_owned(),
GridLayout::Columns(cols) => cols.to_string(),
}
}

egui::ComboBox::from_id_source("container_grid_columns")
.selected_text(grid_layout_to_string(&grid.layout))
.show_ui(ui, |ui| {
ui.style_mut().wrap = Some(false);
ui.set_min_width(64.0);

ui.selectable_value(
&mut grid.layout,
GridLayout::Auto,
grid_layout_to_string(&GridLayout::Auto),
);
ui.separator();

for columns in 1..=grid.num_children() {
ui.selectable_value(
&mut grid.layout,
GridLayout::Columns(columns),
grid_layout_to_string(&GridLayout::Columns(columns)),
);
}
});

ui.end_row();
}
});
}
}

fn has_blueprint_section(item: &Item) -> bool {
match item {
Item::ComponentPath(_) => false,
Item::ComponentPath(_) | Item::Container(_) => false,
Item::InstancePath(space_view_id, _) => space_view_id.is_some(),
_ => true,
}
Expand Down Expand Up @@ -594,7 +697,7 @@ fn blueprint_ui(
}
}

Item::ComponentPath(_) => {}
Item::ComponentPath(_) | Item::Container(_) => {}
}
}

Expand Down
1 change: 1 addition & 0 deletions crates/re_viewer_context/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ anyhow.workspace = true
bytemuck.workspace = true
egui-wgpu.workspace = true
egui.workspace = true
egui_tiles.workspace = true
glam.workspace = true
half.workspace = true
itertools.workspace = true
Expand Down
10 changes: 7 additions & 3 deletions crates/re_viewer_context/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub enum Item {
SpaceView(SpaceViewId),
InstancePath(Option<SpaceViewId>, InstancePath),
DataBlueprintGroup(SpaceViewId, DataQueryId, EntityPath),
Container(egui_tiles::TileId),
}

impl From<SpaceViewId> for Item {
Expand Down Expand Up @@ -90,6 +91,7 @@ impl std::fmt::Debug for Item {
Item::DataBlueprintGroup(sid, qid, entity_path) => {
write!(f, "({sid:?}, {qid:?}, {entity_path:?})")
}
Item::Container(tile_id) => write!(f, "(tile: {tile_id:?})"),
}
}
}
Expand All @@ -111,6 +113,7 @@ impl Item {
Item::ComponentPath(_) => "Entity Component",
Item::SpaceView(_) => "Space View",
Item::DataBlueprintGroup(_, _, _) => "Group",
Item::Container(_) => "Container",
}
}
}
Expand Down Expand Up @@ -199,9 +202,10 @@ pub fn resolve_mono_instance_path_item(
*space_view,
resolve_mono_instance_path(query, store, instance),
),
Item::ComponentPath(_) | Item::SpaceView(_) | Item::DataBlueprintGroup(_, _, _) => {
item.clone()
}
Item::ComponentPath(_)
| Item::SpaceView(_)
| Item::DataBlueprintGroup(_, _, _)
| Item::Container(_) => item.clone(),
}
}

Expand Down
7 changes: 4 additions & 3 deletions crates/re_viewer_context/src/selection_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,9 +215,10 @@ impl SelectionState {
.hovered_previous_frame
.iter()
.any(|current| match current {
Item::ComponentPath(_) | Item::SpaceView(_) | Item::DataBlueprintGroup(_, _, _) => {
current == test
}
Item::ComponentPath(_)
| Item::SpaceView(_)
| Item::DataBlueprintGroup(_, _, _)
| Item::Container(_) => current == test,

Item::InstancePath(current_space_view_id, current_instance_path) => {
if let Item::InstancePath(test_space_view_id, test_instance_path) = test {
Expand Down
4 changes: 2 additions & 2 deletions crates/re_viewport/src/space_view_highlights.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pub fn highlights_for_space_view(

for current_selection in selection_state.current().iter() {
match current_selection {
Item::ComponentPath(_) | Item::SpaceView(_) => {}
Item::ComponentPath(_) | Item::SpaceView(_) | Item::Container(_) => {}

Item::DataBlueprintGroup(_space_view_id, _query_id, _entity_path) => {
// TODO(#4377): Fix DataBlueprintGroup
Expand Down Expand Up @@ -115,7 +115,7 @@ pub fn highlights_for_space_view(

for current_hover in selection_state.hovered().iter() {
match current_hover {
Item::ComponentPath(_) | Item::SpaceView(_) => {}
Item::ComponentPath(_) | Item::SpaceView(_) | Item::Container(_) => {}

Item::DataBlueprintGroup(_space_view_id, _query_id, _entity_path) => {
// TODO(#4377): Fix DataBlueprintGroup
Expand Down
15 changes: 15 additions & 0 deletions crates/re_viewport/src/viewport_blueprint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,21 @@ impl<'a> ViewportBlueprint<'a> {
.space_views
.get(space_view_id)
.map_or(false, |sv| sv.queries.iter().any(|q| q.id == *query_id)),
Item::Container(tile_id) => {
if Some(*tile_id) == self.tree.root {
// the root tile is always visible
true
} else if let Some(tile) = self.tree.tiles.get(*tile_id) {
if let egui_tiles::Tile::Container(container) = tile {
// single children containers are generally hidden
container.num_children() > 1
} else {
true
}
} else {
false
}
}
}
}

Expand Down
10 changes: 8 additions & 2 deletions crates/re_viewport/src/viewport_blueprint_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,17 @@ impl ViewportBlueprint<'_> {
return self.tile_ui(ctx, ui, child_id);
}

let item = Item::Container(tile_id);

let mut visibility_changed = false;
let mut visible = self.tree.is_visible(tile_id);
let mut remove = false;

let default_open = true;

ListItem::new(ctx.re_ui, format!("{:?}", container.kind()))
let response = ListItem::new(ctx.re_ui, format!("{:?}", container.kind()))
.subdued(true)
.selected(ctx.selection().contains(&item))
.with_buttons(|re_ui, ui| {
let vis_response = visibility_button_ui(re_ui, ui, true, &mut visible);
visibility_changed = vis_response.changed();
Expand All @@ -122,7 +125,10 @@ impl ViewportBlueprint<'_> {
for &child in container.children() {
self.tile_ui(ctx, ui, child);
}
});
})
.item_response;

item_ui::select_hovered_on_click(ctx, &response, &[item]);

if remove {
self.mark_user_interaction();
Expand Down

0 comments on commit 8881e21

Please sign in to comment.