Skip to content

Commit

Permalink
Explain static vs temporal components in the UI (rerun-io#6350)
Browse files Browse the repository at this point in the history
### What
<img width="332" alt="Screenshot 2024-05-16 at 11 25 08"
src="https://github.com/rerun-io/rerun/assets/1148717/86aa326c-4236-4d1d-b7ce-9db62ef45e75">

<img width="270" alt="image"
src="https://github.com/rerun-io/rerun/assets/1148717/6ccf5b02-a7ed-4ece-8ad1-43d0c655782f">

<img width="274" alt="Screenshot 2024-05-16 at 11 25 51"
src="https://github.com/rerun-io/rerun/assets/1148717/2d9da6a7-83d6-4a29-8511-be0f5161b69c">

<img width="238" alt="Screenshot 2024-05-16 at 11 25 58"
src="https://github.com/rerun-io/rerun/assets/1148717/1900d2af-4be2-4067-b1e8-12fdebb1019f">

<img width="362" alt="Screenshot 2024-05-16 at 11 28 02"
src="https://github.com/rerun-io/rerun/assets/1148717/cc4eef04-0e39-4490-b991-a2d8cd07139f">

<img width="324" alt="Screenshot 2024-05-16 at 11 27 59"
src="https://github.com/rerun-io/rerun/assets/1148717/1a6ff5ef-93ac-4726-a040-81d83257250b">


### 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/6350?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/6350?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/6350)
- [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
emilk authored May 16, 2024
1 parent b08d8bd commit a223368
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 24 deletions.
16 changes: 11 additions & 5 deletions crates/re_data_ui/src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,19 @@ impl DataUi for EntityLatestAtResults {

// Display data time and additional diagnostic information for static components.
if ui_layout != UiLayout::List {
ui.label(format!(
"Data time: {}",
query
let time = self.results.index().0;
if time.is_static() {
// No need to show anything here. We already tell the user this is a static component elsewhere.
} else {
let formatted_time = query
.timeline()
.typ()
.format(self.results.index().0, ctx.app_options.time_zone),
));
.format(time, ctx.app_options.time_zone);
ui.horizontal(|ui| {
ui.add(re_ui::icons::COMPONENT_TEMPORAL.as_image());
ui.label(format!("Temporal component at {formatted_time}"));
});
}

// if the component is static, we display extra diagnostic information
if self.results.is_static() {
Expand Down
40 changes: 32 additions & 8 deletions crates/re_data_ui/src/item_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ pub fn guess_query_and_db_for_selected_entity<'a>(
pub fn guess_instance_path_icon(
ctx: &ViewerContext<'_>,
instance_path: &InstancePath,
) -> &'static re_ui::icons::Icon {
) -> &'static icons::Icon {
let (query, db) = guess_query_and_db_for_selected_entity(ctx, &instance_path.entity_path);
instance_path_icon(&query.timeline(), db, instance_path)
}
Expand Down Expand Up @@ -383,7 +383,6 @@ pub fn component_path_button(
component_path,
db,
)
.on_hover_text(component_path.component_name.full_name()) // we should show the full name somewhere
}

/// Show a component path and make it selectable.
Expand All @@ -395,18 +394,43 @@ pub fn component_path_button_to(
db: &re_entity_db::EntityDb,
) -> egui::Response {
let item = Item::ComponentPath(component_path.clone());
let is_component_static = db.is_component_static(component_path).unwrap_or_default();
let is_static = db.is_component_static(component_path).unwrap_or_default();
let icon = if is_static {
&icons::COMPONENT_STATIC
} else {
&icons::COMPONENT_TEMPORAL
};
let response = ctx.re_ui.selectable_label_with_icon(
ui,
if is_component_static {
&icons::COMPONENT_STATIC
} else {
&icons::COMPONENT
},
icon,
text,
ctx.selection().contains_item(&item),
re_ui::LabelStyle::Normal,
);

let response = response.on_hover_ui(|ui| {
// TODO(egui#4471): better tooltip size management
ui.set_max_width(250.0);
ui.style_mut().wrap = Some(false);

re_ui::ListItem::new(
ctx.re_ui,
if is_static {
"Static component"
} else {
"Temporal component"
},
)
.with_icon(icon)
.interactive(false)
.show_flat(ui);

ui.label(format!(
"Full name: {}",
component_path.component_name.full_name()
));
});

cursor_interact_with_selectable(ctx, response, item)
}

Expand Down
7 changes: 5 additions & 2 deletions crates/re_smart_channel/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,10 @@ pub enum SmartMessageSource {
File(std::path::PathBuf),

/// The sender is a background thread fetching data from an HTTP file server.
RrdHttpStream { url: String },
RrdHttpStream {
/// Should include `http(s)://` prefix.
url: String,
},

/// The sender is a javascript callback triggered by a `postMessage` event.
///
Expand Down Expand Up @@ -146,7 +149,7 @@ impl std::fmt::Display for SmartMessageSource {
f.write_str(&match self {
SmartMessageSource::Unknown => "unknown".into(),
SmartMessageSource::File(path) => format!("file://{}", path.to_string_lossy()),
SmartMessageSource::RrdHttpStream { url } => format!("http://{url}"),
SmartMessageSource::RrdHttpStream { url } => url.clone(),
SmartMessageSource::RrdWebEventCallback => "web_callback".into(),
SmartMessageSource::JsChannelPush => "javascript".into(),
SmartMessageSource::Sdk => "sdk".into(),
Expand Down
24 changes: 22 additions & 2 deletions crates/re_time_panel/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -750,7 +750,7 @@ impl TimePanel {
.with_icon(if is_static {
&re_ui::icons::COMPONENT_STATIC
} else {
&re_ui::icons::COMPONENT
&re_ui::icons::COMPONENT_TEMPORAL
})
.show_hierarchical(ui);

Expand Down Expand Up @@ -780,10 +780,30 @@ impl TimePanel {
timeline.name()
)));
} else {
ui.label(format!("Number of events: {total_num_messages}"));
re_ui::ListItem::new(
ctx.re_ui,
format!(
"{} component, logged {}",
if is_static { "Static" } else { "Temporal" },
if total_num_messages == 1 {
"once".to_owned()
} else {
format!("{} times", re_format::format_uint(total_num_messages))
},
),
)
.with_icon(if is_static {
&re_ui::icons::COMPONENT_STATIC
} else {
&re_ui::icons::COMPONENT_TEMPORAL
})
.interactive(false)
.show_flat(ui);

// Static components are not displayed at all on the timeline, so cannot be
// previewed there. So we display their content in this tooltip instead.
// Conversely, temporal components change over time, and so showing a specific instance here
// can be confusing.
if is_static {
let query = re_data_store::LatestAtQuery::new(
*time_ctrl.timeline(),
Expand Down
14 changes: 10 additions & 4 deletions crates/re_ui/src/icons.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,16 @@ impl Icon {
}

#[inline]
pub fn as_image(&self) -> Image<'static> {
Image::new(ImageSource::Bytes {
pub fn as_image_source(&self) -> ImageSource<'static> {
ImageSource::Bytes {
uri: self.id.into(),
bytes: self.png_bytes.into(),
})
}
}

#[inline]
pub fn as_image(&self) -> Image<'static> {
Image::new(self.as_image_source())
}
}

Expand Down Expand Up @@ -143,7 +148,8 @@ pub const ENTITY_EMPTY: Icon = Icon::new(
include_bytes!("../data/icons/entity_empty.png"),
);
pub const LINK: Icon = Icon::new("link", include_bytes!("../data/icons/link.png"));
pub const COMPONENT: Icon = Icon::new("component", include_bytes!("../data/icons/component.png"));
pub const COMPONENT_TEMPORAL: Icon =
Icon::new("component", include_bytes!("../data/icons/component.png"));
pub const COMPONENT_STATIC: Icon = Icon::new(
"component_static",
include_bytes!("../data/icons/component_static.png"),
Expand Down
10 changes: 7 additions & 3 deletions crates/re_viewer/src/ui/selection_panel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,17 +367,21 @@ fn what_is_selected_ui(
Some(if is_static {
&icons::COMPONENT_STATIC
} else {
&icons::COMPONENT
&icons::COMPONENT_TEMPORAL
}),
&format!(
"Component {} of entity '{}'",
"{} component {} of entity '{}'",
if is_static { "Static" } else { "Temporal" },
component_name.full_name(),
entity_path
),
);

ui.horizontal(|ui| {
ui.label("component of");
ui.label(format!(
"{} component of",
if is_static { "Static" } else { "Temporal" }
));
item_ui::entity_path_button(ctx, &query, db, ui, None, entity_path);
});

Expand Down

0 comments on commit a223368

Please sign in to comment.