Skip to content

Commit

Permalink
ListItem 2.0 (part 4): only allocate space for property action butt…
Browse files Browse the repository at this point in the history
…ons when needed (#6183)

### What

☝🏻 

This PR also slightly adjust the semantics of the `id` parameter of
`list_item_scope()`. Now it just needs to be unique within the current
UI. It also addresses review comments from #6161, #6174, and #6182.

- Part of #6075
- Follow-up to #6182
- Fixes #6179


![Export-1714577757563](https://github.com/rerun-io/rerun/assets/49431240/45cb8284-15a9-4100-8057-bd7fd994d008)
<br/>

Note: the upper group of (nested) items (which makes use of action
buttons) has no impact on the lower group, because both sub-groups are
in a distinct `list_item_scope`.

### 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/6183?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/6183?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/6183)
- [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 authored May 2, 2024
1 parent 8c9f7ba commit 9b7a0e8
Show file tree
Hide file tree
Showing 9 changed files with 290 additions and 180 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

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

5 changes: 2 additions & 3 deletions crates/re_ui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,15 @@ re_format.workspace = true
re_log.workspace = true
re_log_types.workspace = true # syntax-highlighting for EntityPath

egui.workspace = true
egui_commonmark = { workspace = true, features = ["pulldown_cmark"] }
egui_extras.workspace = true
egui.workspace = true
parking_lot.workspace = true
serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
strum_macros.workspace = true
strum.workspace = true
strum_macros.workspace = true
sublime_fuzzy.workspace = true
once_cell.workspace = true


eframe = { workspace = true, default-features = false, features = ["wgpu"] }
Expand Down
56 changes: 45 additions & 11 deletions crates/re_ui/examples/re_ui_example/right_panel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ pub struct RightPanel {
drag_and_drop: drag_and_drop::ExampleDragAndDrop,
hierarchical_drag_and_drop: hierarchical_drag_and_drop::HierarchicalDragAndDrop,
selected_list_item: Option<usize>,
use_action_button: bool,

// dummy data
text: String,
Expand All @@ -22,6 +23,7 @@ impl Default for RightPanel {
hierarchical_drag_and_drop:
hierarchical_drag_and_drop::HierarchicalDragAndDrop::default(),
selected_list_item: None,
use_action_button: false,
// dummy data
text: "Hello world".to_owned(),
color: [128, 0, 0, 255],
Expand Down Expand Up @@ -236,21 +238,53 @@ impl RightPanel {

re_ui.list_item2().show_hierarchical_with_children(
ui,
"other features",
"property content right button reserve",
true,
list_item2::LabelContent::new("Other contents:"),
list_item2::PropertyContent::new("PropertyContent action button:")
.value_text("demo of right gutter"),
|re_ui, ui| {
re_ui.list_item2().show_hierarchical(
ui,
list_item2::LabelContent::new("next line is a EmptyContent:")
.subdued(true)
.italics(true),
);
// By using an inner scope, we allow the nested properties to not align themselves
// to the parent property, which in this particular case looks better.
list_item2::list_item_scope(ui, "inner_scope", None, |ui| {
fn demo_item(re_ui: &ReUi, ui: &mut egui::Ui) {
re_ui.list_item2().show_hierarchical(
ui,
list_item2::PropertyContent::new("Some item:").value_fn(|_, ui, _| {
ui.ctx().debug_painter().debug_rect(
ui.max_rect(),
egui::Color32::LIGHT_BLUE,
"space for value",
);
}),
);
}

re_ui
.list_item2()
.show_hierarchical(ui, list_item2::EmptyContent);
for _ in 0..3 {
demo_item(re_ui, ui);
}

let mut content = list_item2::PropertyContent::new("Use action button");
if self.use_action_button {
content = content.action_button(&re_ui::icons::ADD, || {
re_log::warn!("Add button clicked");
});
}
content = content.value_bool_mut(&mut self.use_action_button);
re_ui.list_item2().show_hierarchical(ui, content);

for _ in 0..3 {
demo_item(re_ui, ui);
}
});
},
);

re_ui.list_item2().show_hierarchical_with_children(
ui,
"other features",
true,
list_item2::LabelContent::new("Other contents:"),
|re_ui, ui| {
re_ui.list_item2().show_hierarchical(
ui,
list_item2::DebugContent::default()
Expand Down
2 changes: 1 addition & 1 deletion crates/re_ui/src/drag_and_drop.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Helpers for drag and drop support for reordering hierarchical lists.
//!
//! Works well in combination with [`crate::ListItem`].
//! Works well in combination with [`crate::list_item2::ListItem`].
pub enum ItemKind<ItemId: Copy> {
/// Root container item.
Expand Down
23 changes: 18 additions & 5 deletions crates/re_ui/src/list_item2/list_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use egui::{NumExt, Response, Shape, Ui};

use crate::list_item2::{ContentContext, DesiredWidth, ListItemContent, StateStack};
use crate::list_item2::{ContentContext, DesiredWidth, LayoutInfoStack, ListItemContent};
use crate::ReUi;

struct ListItemResponse {
Expand All @@ -22,7 +22,19 @@ pub struct ShowCollapsingResponse<R> {
pub body_response: Option<egui::InnerResponse<R>>,
}

/// Generic list item that delegates its content to a [`ListItemContent`] implementation.
/// Content-generic list item.
///
/// The following features are supported:
/// - Flat or collapsible hierarchical lists.
/// - Full-span background highlighting via [`super::list_item_scope`]. TODO(#6156): fix reference
/// - Interactive or not.
/// - Support for drag and drop with [`crate::drag_and_drop`].
///
/// Besides these core features, [`ListItem`] delegates all content to the [`ListItemContent`]
/// implementations, such as [`super::LabelContent`] and [`super::PropertyContent`].
///
/// Usage example can be found in `re_ui_example`.
#[derive(Debug, Clone)]
pub struct ListItem<'a> {
re_ui: &'a ReUi,
Expand Down Expand Up @@ -226,10 +238,10 @@ impl<'a> ListItem<'a> {

// We use the state set by ListItemContainer to determine how far the background should
// extend.
let state = StateStack::top(ui.ctx());
let layout_info = LayoutInfoStack::top(ui.ctx());
let mut bg_rect = rect;
bg_rect.set_left(state.background_x_range.min);
bg_rect.set_right(state.background_x_range.max);
bg_rect.set_left(layout_info.background_x_range.min);
bg_rect.set_right(layout_info.background_x_range.max);

// We want to be able to select/hover the item across its full span, so we interact over the
// entire background rect. But…
Expand Down Expand Up @@ -283,6 +295,7 @@ impl<'a> ListItem<'a> {
bg_rect,
response: &style_response,
list_item: &self,
layout_info,
};
content.ui(re_ui, ui, &content_ctx);

Expand Down
6 changes: 6 additions & 0 deletions crates/re_ui/src/list_item2/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ pub struct ContentContext<'a> {
pub rect: egui::Rect,

/// Background area
///
/// This is the area covered by the full-span highlighting. Useful for testing if the cursor is
/// over the item.
pub bg_rect: egui::Rect,

/// List item response.
Expand All @@ -31,6 +34,9 @@ pub struct ContentContext<'a> {

/// The current list item.
pub list_item: &'a ListItem<'a>,

/// Layout information to use for rendering.
pub layout_info: LayoutInfo,
}

#[derive(Debug, Clone, Copy)]
Expand Down
29 changes: 15 additions & 14 deletions crates/re_ui/src/list_item2/other_contents.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,36 @@ use crate::list_item2::{ContentContext, DesiredWidth, ListItemContent};
use crate::ReUi;
use egui::Ui;

/// Empty list item content.
pub struct EmptyContent;

impl ListItemContent for EmptyContent {
fn ui(
self: Box<Self>,
_re_ui: &crate::ReUi,
_ui: &mut egui::Ui,
_context: &ContentContext<'_>,
) {
}
}

/// [`ListItemContent`] that delegates to a closure.
#[allow(clippy::type_complexity)]
pub struct CustomContent<'a> {
ui: Box<dyn FnOnce(&crate::ReUi, &mut egui::Ui, &ContentContext<'_>) + 'a>,
desired_width: DesiredWidth,
}

impl<'a> CustomContent<'a> {
pub fn new(ui: impl FnOnce(&crate::ReUi, &mut egui::Ui, &ContentContext<'_>) + 'a) -> Self {
Self { ui: Box::new(ui) }
Self {
ui: Box::new(ui),
desired_width: Default::default(),
}
}

#[inline]
pub fn with_desired_width(mut self, desired_width: DesiredWidth) -> Self {
self.desired_width = desired_width;
self
}
}

impl ListItemContent for CustomContent<'_> {
fn ui(self: Box<Self>, re_ui: &crate::ReUi, ui: &mut egui::Ui, context: &ContentContext<'_>) {
(self.ui)(re_ui, ui, context);
}

fn desired_width(&self, _re_ui: &ReUi, _ui: &Ui) -> DesiredWidth {
self.desired_width
}
}

/// [`ListItemContent`] that displays the content rect.
Expand Down
Loading

0 comments on commit 9b7a0e8

Please sign in to comment.