Skip to content

Commit

Permalink
Migrate all full-span widgets to re_ui::full_span (#6248)
Browse files Browse the repository at this point in the history
### What

Migrate all widgets to the "full span scope" mechanism introduced in
#6211, including the legacy `ListItem`. This completes the migration
away from the clip rect hack, but does highlight a number of issues and
improvements:
- #6245 
- #6246

Showcase of `full_span_scope()` nestability:

<img width="324" alt="image"
src="https://github.com/rerun-io/rerun/assets/49431240/be8e72b1-7f1d-4533-a456-870a8c51572d">
<br/> <br/>


- Fixes #6156

### 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 examples from latest `main` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6248?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[rerun.io/viewer](https://rerun.io/viewer/pr/6248?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
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/6248)
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

To run all checks from `main`, comment on the PR with `@rerun-bot
full-check`.
  • Loading branch information
abey79 committed May 8, 2024
1 parent 29fc70b commit 8d64e99
Show file tree
Hide file tree
Showing 9 changed files with 255 additions and 257 deletions.
84 changes: 50 additions & 34 deletions crates/re_data_ui/src/app_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,62 +41,78 @@ impl crate::DataUi for ApplicationId {
.sorted_by_key(|entity_db| entity_db.store_info().map(|info| info.started))
.collect();

//TODO(#6245): we should _not_ use interactive UI in code used for hover tooltip!
if !recordings.is_empty() {
ui.scope(|ui| {
ui.set_clip_rect(ui.max_rect()); // TODO(#5740): Hack required because `entity_db_button_ui` uses `ListItem`, which fills the full width until the clip rect.
let content_ui = |ui: &mut egui::Ui| {
ui.spacing_mut().item_spacing.y = 0.0;

ui.add_space(8.0);
ui.strong("Loaded recordings for this app");
for entity_db in recordings {
entity_db_button_ui(ctx, ui, entity_db, true);
}
};

ui.scope(|ui| {
// TODO(#6246): this test is needed because we're called in a context that may or may
// not have a full span defined.
if verbosity == UiVerbosity::Reduced {
// This typically happens in tooltips, so a scope is needed
//TODO(ab): in the context of tooltips, ui.max_rect() doesn't provide the correct width
re_ui::full_span::full_span_scope(ui, ui.max_rect().x_range(), content_ui);
} else {
// This only happens from the selection panel, so the full span scope is already set.
content_ui(ui);
}
});
}

// ---------------------------------------------------------------------
// do not show UI code in tooltips

ui.add_space(8.0);
if verbosity != UiVerbosity::Reduced {
ui.add_space(8.0);

// ---------------------------------------------------------------------
// ---------------------------------------------------------------------

// Blueprint section.
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 is_same_as_default = default_blueprint.map_or(false, |default_blueprint| {
default_blueprint.latest_row_id() == active_blueprint.latest_row_id()
});

if is_same_as_default {
ui.add_enabled(false, button)
.on_disabled_hover_text("No modifications has been made");
} else if default_blueprint.is_none() {
ui.add_enabled(false, button)
.on_disabled_hover_text("There's no default blueprint");
} else {
// The active blueprint is different from the default blueprint
if ui
.add(button)
.on_hover_text("Reset to the default blueprint for this app")
.clicked()
{
ctx.command_sender
.send_system(re_viewer_context::SystemCommand::ClearActiveBlueprint);
// Blueprint section.
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 is_same_as_default = default_blueprint.map_or(false, |default_blueprint| {
default_blueprint.latest_row_id() == active_blueprint.latest_row_id()
});

if is_same_as_default {
ui.add_enabled(false, button)
.on_disabled_hover_text("No modifications have been made");
} else if default_blueprint.is_none() {
ui.add_enabled(false, button)
.on_disabled_hover_text("There's no default blueprint");
} else {
// The active blueprint is different from the default blueprint
if ui
.add(button)
.on_hover_text("Reset to the default blueprint for this app")
.clicked()
{
ctx.command_sender
.send_system(re_viewer_context::SystemCommand::ClearActiveBlueprint);
}
}
}

if ui.add(egui::Button::image_and_text(
if ui.add(egui::Button::image_and_text(
re_ui::icons::RESET.as_image(),
"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
.send_system(re_viewer_context::SystemCommand::ClearAndGenerateBlueprint);
}
}
}
}
20 changes: 16 additions & 4 deletions crates/re_data_ui/src/data_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,8 @@ impl crate::DataUi for re_smart_channel::SmartChannelSource {
recordings.sort_by_key(|entity_db| entity_db.store_info().map(|info| info.started));
blueprints.sort_by_key(|entity_db| entity_db.store_info().map(|info| info.started));

ui.scope(|ui| {
ui.set_clip_rect(ui.max_rect()); // TODO(#5740): Hack required because `entity_db_button_ui` uses `ListItem`, which fills the full width until the clip rect.
ui.spacing_mut().item_spacing.y = 0.0;

//TODO(#6245): we should _not_ use interactive UI in code used for hover tooltip!
let content_ui = |ui: &mut egui::Ui| {
if !recordings.is_empty() {
ui.add_space(8.0);
ui.strong("Recordings from this data source");
Expand All @@ -69,6 +67,20 @@ impl crate::DataUi for re_smart_channel::SmartChannelSource {
entity_db_button_ui(ctx, ui, entity_db, true);
}
}
};
ui.scope(|ui| {
ui.spacing_mut().item_spacing.y = 0.0;

// TODO(#6246): this test is needed because we're called in a context that may or may
// not have a full span defined.
if verbosity == UiVerbosity::Reduced {
// This typically happens in tooltips, so a scope is needed
//TODO(ab): in the context of tooltips, ui.max_rect() doesn't provide the correct width
re_ui::full_span::full_span_scope(ui, ui.max_rect().x_range(), content_ui);
} else {
// This only happens from the selection panel, so the full span scope is already set.
content_ui(ui);
}
});
}
}
43 changes: 11 additions & 32 deletions crates/re_time_panel/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -431,16 +431,17 @@ impl TimePanel {
));

// All the entity rows and their data density graphs:
self.tree_ui(
ctx,
viewport_blueprint,
entity_db,
time_ctrl,
&time_area_response,
&lower_time_area_painter,
time_x_left,
ui,
);
re_ui::full_span::full_span_scope(ui, (0.0..=time_x_left).into(), |ui| {
self.tree_ui(
ctx,
viewport_blueprint,
entity_db,
time_ctrl,
&time_area_response,
&lower_time_area_painter,
ui,
);
});

{
// Paint a shadow between the stream names on the left
Expand Down Expand Up @@ -490,7 +491,6 @@ impl TimePanel {
time_ctrl: &mut TimeControl,
time_area_response: &egui::Response,
time_area_painter: &egui::Painter,
tree_max_y: f32,
ui: &mut egui::Ui,
) {
re_tracing::profile_function!();
Expand Down Expand Up @@ -519,7 +519,6 @@ impl TimePanel {
time_ctrl,
time_area_response,
time_area_painter,
tree_max_y,
None,
entity_db.tree(),
ui,
Expand All @@ -533,7 +532,6 @@ impl TimePanel {
time_ctrl,
time_area_response,
time_area_painter,
tree_max_y,
entity_db.tree(),
ui,
);
Expand All @@ -550,7 +548,6 @@ impl TimePanel {
time_ctrl: &mut TimeControl,
time_area_response: &egui::Response,
time_area_painter: &egui::Painter,
tree_max_y: f32,
last_path_part: Option<&EntityPathPart>,
tree: &EntityTree,
ui: &mut egui::Ui,
Expand Down Expand Up @@ -584,11 +581,6 @@ impl TimePanel {
.highlight_for_ui_element(&item.to_item())
== HoverHighlight::Hovered;

let clip_rect_save = ui.clip_rect();
let mut clip_rect = clip_rect_save;
clip_rect.max.x = tree_max_y;
ui.set_clip_rect(clip_rect);

// expand if children is focused
let focused_entity_path = ctx
.focused_item
Expand Down Expand Up @@ -624,15 +616,12 @@ impl TimePanel {
time_ctrl,
time_area_response,
time_area_painter,
tree_max_y,
tree,
ui,
);
},
);

ui.set_clip_rect(clip_rect_save);

let response = response.on_hover_ui(|ui| {
re_data_ui::item_ui::entity_hover_card_ui(
ui,
Expand Down Expand Up @@ -717,7 +706,6 @@ impl TimePanel {
time_ctrl: &mut TimeControl,
time_area_response: &egui::Response,
time_area_painter: &egui::Painter,
tree_max_y: f32,
tree: &EntityTree,
ui: &mut egui::Ui,
) {
Expand All @@ -729,7 +717,6 @@ impl TimePanel {
time_ctrl,
time_area_response,
time_area_painter,
tree_max_y,
Some(last_component),
child,
ui,
Expand All @@ -739,8 +726,6 @@ impl TimePanel {

// If this is an entity:
if !tree.entity.components.is_empty() {
let clip_rect_save = ui.clip_rect();

for component_name in re_data_ui::component_list_for_ui(tree.entity.components.keys()) {
let data = &tree.entity.components[&component_name];

Expand All @@ -752,10 +737,6 @@ impl TimePanel {
let short_component_name = component_path.component_name.short_name();
let item = TimePanelItem::component_path(component_path.clone());

let mut clip_rect = clip_rect_save;
clip_rect.max.x = tree_max_y;
ui.set_clip_rect(clip_rect);

let response = ListItem::new(ctx.re_ui, short_component_name)
.selected(ctx.selection().contains_item(&item.to_item()))
.width_allocation_mode(WidthAllocationMode::Compact)
Expand All @@ -771,8 +752,6 @@ impl TimePanel {
})
.show_hierarchical(ui);

ui.set_clip_rect(clip_rect_save);

context_menu_ui_for_item(
ctx,
viewport_blueprint,
Expand Down
Loading

0 comments on commit 8d64e99

Please sign in to comment.