From d48e28c2760c7608c59c964d24758f3d1ea6bc0a Mon Sep 17 00:00:00 2001 From: Antoine Beyeler Date: Tue, 7 Jan 2025 19:27:45 +0100 Subject: [PATCH 01/10] Introduce the filter widget to the time panel (no filtering happens yet though) --- crates/viewer/re_time_panel/src/lib.rs | 28 +++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/crates/viewer/re_time_panel/src/lib.rs b/crates/viewer/re_time_panel/src/lib.rs index 00f715e00147..ca988f1e13ca 100644 --- a/crates/viewer/re_time_panel/src/lib.rs +++ b/crates/viewer/re_time_panel/src/lib.rs @@ -135,8 +135,11 @@ pub struct TimePanel { /// Ui elements for controlling time. time_control_ui: TimeControlUi, - /// Which source is the time panel controlling + /// Which source is the time panel controlling? source: TimePanelSource, + + /// The filter widget state + filter_state: re_ui::FilterState, } impl Default for TimePanel { @@ -150,6 +153,7 @@ impl Default for TimePanel { time_ranges_ui: Default::default(), time_control_ui: TimeControlUi, source: TimePanelSource::Recording, + filter_state: Default::default(), } } } @@ -391,7 +395,10 @@ impl TimePanel { // ▲ // └ tree_max_y (= time_x_left) - self.next_col_right = ui.min_rect().left(); // next_col_right will expand during the call + // We use this to track what the rightmost coordinate for the tree section should be. We + // clamp it to a minimum of 150.0px for the filter widget to behave correctly even when the + // tree is fully collapsed (and thus narrow). + self.next_col_right = ui.min_rect().left() + 150.0; let time_x_left = (ui.min_rect().left() + self.prev_col_width + ui.spacing().item_spacing.x) @@ -427,11 +434,18 @@ impl TimePanel { ui.set_min_size(size); ui.style_mut().wrap_mode = Some(egui::TextWrapMode::Extend); ui.add_space(4.0); // hack to vertically center the text - if self.source == TimePanelSource::Blueprint { - ui.strong("Blueprint Streams"); - } else { - ui.strong("Streams"); - } + + ui.full_span_scope(0.0..=time_x_left, |ui| { + self.filter_state.ui( + ui, + egui::RichText::new(if self.source == TimePanelSource::Blueprint { + "Blueprint Streams" + } else { + "Streams" + }) + .strong(), + ); + }); }) .response .on_hover_text( From 851355e47bd7d0e69b2f9680e49d4ca45c42754f Mon Sep 17 00:00:00 2001 From: Antoine Beyeler Date: Thu, 9 Jan 2025 09:22:51 +0100 Subject: [PATCH 02/10] Implement filtering in streams tree --- crates/viewer/re_time_panel/src/lib.rs | 53 +++++++++++++++++--------- 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/crates/viewer/re_time_panel/src/lib.rs b/crates/viewer/re_time_panel/src/lib.rs index ca988f1e13ca..aac64e814152 100644 --- a/crates/viewer/re_time_panel/src/lib.rs +++ b/crates/viewer/re_time_panel/src/lib.rs @@ -26,11 +26,11 @@ use re_data_ui::DataUi as _; use re_data_ui::{item_ui::guess_instance_path_icon, sorted_component_list_for_ui}; use re_entity_db::{EntityDb, EntityTree, InstancePath}; use re_log_types::{ - external::re_types_core::ComponentName, ComponentPath, EntityPath, EntityPathPart, - ResolvedTimeRange, TimeInt, TimeReal, TimeType, + external::re_types_core::ComponentName, ComponentPath, EntityPath, ResolvedTimeRange, TimeInt, + TimeReal, TimeType, }; use re_types::blueprint::components::PanelState; -use re_ui::{list_item, ContextExt as _, DesignTokens, UiExt as _}; +use re_ui::{filter_widget, list_item, ContextExt as _, DesignTokens, UiExt as _}; use re_viewer_context::{ CollapseScope, HoverHighlight, Item, ItemContext, RecordingConfig, TimeControl, TimeView, UiLayout, ViewerContext, @@ -139,7 +139,7 @@ pub struct TimePanel { source: TimePanelSource, /// The filter widget state - filter_state: re_ui::FilterState, + filter_state: filter_widget::FilterState, } impl Default for TimePanel { @@ -604,6 +604,8 @@ impl TimePanel { // stores, due to `Item::*` not tracking stores for entity paths. let show_root = self.source == TimePanelSource::Recording; + let filter_matcher = self.filter_state.filter(); + if show_root { self.show_tree( ctx, @@ -612,10 +614,9 @@ impl TimePanel { time_ctrl, time_area_response, time_area_painter, - None, entity_db.tree(), + &filter_matcher, ui, - "/", ); } else { self.show_children( @@ -626,6 +627,7 @@ impl TimePanel { time_area_response, time_area_painter, entity_db.tree(), + &filter_matcher, ui, ); } @@ -641,26 +643,42 @@ impl TimePanel { time_ctrl: &mut TimeControl, time_area_response: &egui::Response, time_area_painter: &egui::Painter, - last_path_part: Option<&EntityPathPart>, tree: &EntityTree, + filter_matcher: &filter_widget::FilterMatcher, ui: &mut egui::Ui, - show_root_as: &str, ) { + // We traverse and display this tree only if it contains a matching entity part. + if !filter_matcher.matches_everything() // fast short-circuit + && tree + .find_first_child_recursive(|entity_path| { + entity_path + .last() + .is_some_and(|entity_part| filter_matcher.matches(&entity_part.ui_string())) + }) + .is_none() + { + return; + } + let db = match self.source { TimePanelSource::Recording => ctx.recording(), TimePanelSource::Blueprint => ctx.store_context.blueprint, }; // The last part of the path component + let last_path_part = tree.path.last(); let text = if let Some(last_path_part) = last_path_part { - let stem = last_path_part.ui_string(); - if tree.is_leaf() { - stem + let part_text = if tree.is_leaf() { + last_path_part.ui_string() } else { - format!("{stem}/") // show we have children with a / - } + format!("{}/", last_path_part.ui_string()) // show we have children with a / + }; + + filter_matcher + .matches_formatted(ui.ctx(), &part_text) + .unwrap_or_else(|| part_text.into()) } else { - show_root_as.to_owned() + "/".into() }; let default_open = tree.path.len() <= 1 && !tree.is_leaf(); @@ -721,6 +739,7 @@ impl TimePanel { time_area_response, time_area_painter, tree, + filter_matcher, ui, ); }, @@ -814,9 +833,10 @@ impl TimePanel { time_area_response: &egui::Response, time_area_painter: &egui::Painter, tree: &EntityTree, + filter_matcher: &filter_widget::FilterMatcher, ui: &mut egui::Ui, ) { - for (last_component, child) in &tree.children { + for child in tree.children.values() { self.show_tree( ctx, viewport_blueprint, @@ -824,10 +844,9 @@ impl TimePanel { time_ctrl, time_area_response, time_area_painter, - Some(last_component), child, + filter_matcher, ui, - "/", ); } From 12b46614503fb73e76cb64e3708f76674910f859 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler Date: Fri, 10 Jan 2025 11:32:08 +0100 Subject: [PATCH 03/10] Proper handling of collapse scope --- .../src/actions/collapse_expand_all.rs | 27 ++++++++++-- crates/viewer/re_time_panel/src/lib.rs | 43 +++++++++++++------ .../re_viewer_context/src/collapsed_id.rs | 6 +++ .../re_viewer_context/src/selection_state.rs | 2 + 4 files changed, 60 insertions(+), 18 deletions(-) diff --git a/crates/viewer/re_context_menu/src/actions/collapse_expand_all.rs b/crates/viewer/re_context_menu/src/actions/collapse_expand_all.rs index 700c804e62e8..e92c6d11fa32 100644 --- a/crates/viewer/re_context_menu/src/actions/collapse_expand_all.rs +++ b/crates/viewer/re_context_menu/src/actions/collapse_expand_all.rs @@ -100,24 +100,43 @@ impl ContextMenuAction for CollapseExpandAllAction { } fn process_instance_path(&self, ctx: &ContextMenuContext<'_>, instance_path: &InstancePath) { - #[expect(clippy::match_same_arms)] let (db, scope) = match ctx .selection .context_for_item(&Item::InstancePath(instance_path.clone())) { + Some(&ItemContext::StreamsTree { + store_kind: StoreKind::Recording, + filter_session_id: None, + }) => (ctx.viewer_context.recording(), CollapseScope::StreamsTree), + + Some(&ItemContext::StreamsTree { + store_kind: StoreKind::Recording, + filter_session_id: Some(session_id), + }) => ( + ctx.viewer_context.recording(), + CollapseScope::StreamsTreeFiltered { session_id }, + ), + Some(&ItemContext::StreamsTree { store_kind: StoreKind::Blueprint, + filter_session_id: None, }) => ( ctx.viewer_context.blueprint_db(), CollapseScope::BlueprintStreamsTree, ), Some(&ItemContext::StreamsTree { - store_kind: StoreKind::Recording, - }) => (ctx.viewer_context.recording(), CollapseScope::StreamsTree), + store_kind: StoreKind::Blueprint, + filter_session_id: Some(session_id), + }) => ( + ctx.viewer_context.blueprint_db(), + CollapseScope::BlueprintStreamsTreeFiltered { session_id }, + ), // default to recording if we don't have more specific information - _ => (ctx.viewer_context.recording(), CollapseScope::StreamsTree), + Some(&ItemContext::TwoD { .. } | &ItemContext::ThreeD { .. }) | None => { + (ctx.viewer_context.recording(), CollapseScope::StreamsTree) + } }; let Some(subtree) = db.tree().subtree(&instance_path.entity_path) else { diff --git a/crates/viewer/re_time_panel/src/lib.rs b/crates/viewer/re_time_panel/src/lib.rs index aac64e814152..36341d791a02 100644 --- a/crates/viewer/re_time_panel/src/lib.rs +++ b/crates/viewer/re_time_panel/src/lib.rs @@ -651,9 +651,7 @@ impl TimePanel { if !filter_matcher.matches_everything() // fast short-circuit && tree .find_first_child_recursive(|entity_path| { - entity_path - .last() - .is_some_and(|entity_part| filter_matcher.matches(&entity_part.ui_string())) + entity_path.iter().any(|entity_part| filter_matcher.matches(&entity_part.ui_string())) }) .is_none() { @@ -681,8 +679,6 @@ impl TimePanel { "/".into() }; - let default_open = tree.path.len() <= 1 && !tree.is_leaf(); - let item = TimePanelItem::entity_path(tree.path.clone()); let is_selected = ctx.selection().contains_item(&item.to_item()); let is_item_hovered = ctx @@ -690,6 +686,8 @@ impl TimePanel { .highlight_for_ui_element(&item.to_item()) == HoverHighlight::Hovered; + let collapse_scope = self.collapse_scope(); + // expand if children is focused let focused_entity_path = ctx .focused_item @@ -697,19 +695,19 @@ impl TimePanel { .and_then(|item| item.entity_path()); if focused_entity_path.is_some_and(|entity_path| entity_path.is_descendant_of(&tree.path)) { - CollapseScope::StreamsTree + collapse_scope .entity(tree.path.clone()) .set_open(ui.ctx(), true); } - // Globally unique id - should only be one of these in view at one time. - // We do this so that we can support "collapse/expand all" command. - let id = egui::Id::new(match self.source { - TimePanelSource::Recording => CollapseScope::StreamsTree.entity(tree.path.clone()), - TimePanelSource::Blueprint => { - CollapseScope::BlueprintStreamsTree.entity(tree.path.clone()) - } - }); + // Globally unique id that is dependent on the "nature" of the tree (recording or blueprint, + // in a filter session or not) + let id = collapse_scope.entity(tree.path.clone()).into(); + + let is_short_path = tree.path.len() <= 1 && !tree.is_leaf(); + let default_open = self.filter_state.session_id().is_some() || is_short_path; + + //dbg!((collapse_scope, default_open)); let list_item::ShowCollapsingResponse { item_response: response, @@ -773,6 +771,7 @@ impl TimePanel { // expand/collapse context menu actions need this information ItemContext::StreamsTree { store_kind: self.source.into(), + filter_session_id: self.filter_state.session_id(), }, &response, SelectionUpdateBehavior::UseSelection, @@ -1050,6 +1049,22 @@ impl TimePanel { }); } } + + fn collapse_scope(&self) -> CollapseScope { + match (self.source, self.filter_state.session_id()) { + (TimePanelSource::Recording, None) => CollapseScope::StreamsTree, + + (TimePanelSource::Blueprint, None) => CollapseScope::BlueprintStreamsTree, + + (TimePanelSource::Recording, Some(session_id)) => { + CollapseScope::StreamsTreeFiltered { session_id } + } + + (TimePanelSource::Blueprint, Some(session_id)) => { + CollapseScope::BlueprintStreamsTreeFiltered { session_id } + } + } + } } /// Draw the hovered/selected highlight background for a timeline row. diff --git a/crates/viewer/re_viewer_context/src/collapsed_id.rs b/crates/viewer/re_viewer_context/src/collapsed_id.rs index 9358c8ddc5cc..2eec7eb4c3d2 100644 --- a/crates/viewer/re_viewer_context/src/collapsed_id.rs +++ b/crates/viewer/re_viewer_context/src/collapsed_id.rs @@ -14,9 +14,15 @@ pub enum CollapseScope { /// Stream tree from the time panel StreamsTree, + /// Stream tree from the time panel, when the filter is active + StreamsTreeFiltered { session_id: egui::Id }, + /// The stream tree from the blueprint debug time panel BlueprintStreamsTree, + /// The stream tree from the blueprint debug time panel, when the filter is active + BlueprintStreamsTreeFiltered { session_id: egui::Id }, + /// Blueprint tree from the blueprint panel (left panel) BlueprintTree, } diff --git a/crates/viewer/re_viewer_context/src/selection_state.rs b/crates/viewer/re_viewer_context/src/selection_state.rs index 4f60c4bfeaad..14c9009370aa 100644 --- a/crates/viewer/re_viewer_context/src/selection_state.rs +++ b/crates/viewer/re_viewer_context/src/selection_state.rs @@ -40,6 +40,8 @@ pub enum ItemContext { StreamsTree { /// Which store does this streams tree correspond to? store_kind: StoreKind, + + filter_session_id: Option, }, } From ce8da78d5a2ca676ca7cc77daecd6d51e885879e Mon Sep 17 00:00:00 2001 From: Antoine Beyeler Date: Fri, 10 Jan 2025 14:56:24 +0100 Subject: [PATCH 04/10] Fix filtering implementation --- crates/viewer/re_time_panel/src/lib.rs | 43 +++++++++++++++++++------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/crates/viewer/re_time_panel/src/lib.rs b/crates/viewer/re_time_panel/src/lib.rs index 36341d791a02..def5b7afc5c9 100644 --- a/crates/viewer/re_time_panel/src/lib.rs +++ b/crates/viewer/re_time_panel/src/lib.rs @@ -1,10 +1,10 @@ //! Rerun Time Panel //! -//! This crate provides a panel that shows allows to control time & timelines, -//! as well as all necessary ui elements that make it up. +//! This crate provides a panel that shows all entities in the store and allows control of time and +//! timelines, as well as all necessary ui elements that make it up. // TODO(#6330): remove unwrap() -#![allow(clippy::unwrap_used)] +#![expect(clippy::unwrap_used)] mod data_density_graph; mod paint_ticks; @@ -572,7 +572,7 @@ impl TimePanel { } // All the entity rows and their data density graphs: - #[allow(clippy::too_many_arguments)] + #[expect(clippy::too_many_arguments)] fn tree_ui( &mut self, ctx: &ViewerContext<'_>, @@ -634,7 +634,7 @@ impl TimePanel { }); } - #[allow(clippy::too_many_arguments)] + #[expect(clippy::too_many_arguments)] fn show_tree( &mut self, ctx: &ViewerContext<'_>, @@ -648,13 +648,34 @@ impl TimePanel { ui: &mut egui::Ui, ) { // We traverse and display this tree only if it contains a matching entity part. - if !filter_matcher.matches_everything() // fast short-circuit - && tree + 'early_exit: { + // Filter is inactive or otherwise whitelisting everything. + if filter_matcher.matches_everything() { + break 'early_exit; + } + + // The current path is a match. + if tree + .path + .iter() + .any(|entity_part| filter_matcher.matches(&entity_part.ui_string())) + { + break 'early_exit; + } + + // Our subtree contains a match. + if tree .find_first_child_recursive(|entity_path| { - entity_path.iter().any(|entity_part| filter_matcher.matches(&entity_part.ui_string())) + entity_path + .last() + .is_some_and(|entity_part| filter_matcher.matches(&entity_part.ui_string())) }) - .is_none() - { + .is_some() + { + break 'early_exit; + } + + // No match to be found, so nothing to display. return; } @@ -822,7 +843,7 @@ impl TimePanel { } } - #[allow(clippy::too_many_arguments)] + #[expect(clippy::too_many_arguments)] fn show_children( &mut self, ctx: &ViewerContext<'_>, From 7042e38235f62ef08d7e0c4c92a21061231a5e62 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler Date: Fri, 10 Jan 2025 15:06:41 +0100 Subject: [PATCH 05/10] Don't persist the filter state --- crates/viewer/re_time_panel/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/viewer/re_time_panel/src/lib.rs b/crates/viewer/re_time_panel/src/lib.rs index def5b7afc5c9..9a399f4f7afd 100644 --- a/crates/viewer/re_time_panel/src/lib.rs +++ b/crates/viewer/re_time_panel/src/lib.rs @@ -139,6 +139,7 @@ pub struct TimePanel { source: TimePanelSource, /// The filter widget state + #[serde(skip)] filter_state: filter_widget::FilterState, } From d6b17efe7b2119e54bdc7e31bae19e1e0c5f6059 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler Date: Fri, 10 Jan 2025 16:29:47 +0100 Subject: [PATCH 06/10] invalidate/deactivate filter on recording change --- crates/viewer/re_time_panel/src/lib.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/crates/viewer/re_time_panel/src/lib.rs b/crates/viewer/re_time_panel/src/lib.rs index 9a399f4f7afd..0766882f467b 100644 --- a/crates/viewer/re_time_panel/src/lib.rs +++ b/crates/viewer/re_time_panel/src/lib.rs @@ -141,6 +141,13 @@ pub struct TimePanel { /// The filter widget state #[serde(skip)] filter_state: filter_widget::FilterState, + + /// The store id the filter widget relates to. + /// + /// Used to invalidate the filter state (aka deactivate it) when the user switch the current + /// recording. + #[serde(skip)] + filter_state_store_id: Option, } impl Default for TimePanel { @@ -155,6 +162,7 @@ impl Default for TimePanel { time_control_ui: TimeControlUi, source: TimePanelSource::Recording, filter_state: Default::default(), + filter_state_store_id: None, } } } @@ -190,6 +198,12 @@ impl TimePanel { return; } + // Invalidate the filter widget if the store id has changed. + if self.filter_state_store_id != Some(entity_db.store_id()) { + self.filter_state = Default::default(); + self.filter_state_store_id = Some(entity_db.store_id()); + } + self.data_density_graph_painter.begin_frame(ui.ctx()); // Naturally, many parts of the time panel need the time control. @@ -650,6 +664,10 @@ impl TimePanel { ) { // We traverse and display this tree only if it contains a matching entity part. 'early_exit: { + if filter_matcher.matches_nothing() { + return; + } + // Filter is inactive or otherwise whitelisting everything. if filter_matcher.matches_everything() { break 'early_exit; From 5424c39735126285325ca9ac77c0ebf09ead6a2d Mon Sep 17 00:00:00 2001 From: Antoine Beyeler Date: Fri, 10 Jan 2025 18:02:51 +0100 Subject: [PATCH 07/10] fixed vertical alignment and updated test snapshots --- Cargo.lock | 1 - crates/viewer/re_time_panel/Cargo.toml | 3 ++- crates/viewer/re_time_panel/src/lib.rs | 6 +++++- .../re_time_panel/tests/snapshots/time_panel_dense_data.png | 4 ++-- .../tests/snapshots/time_panel_two_sections.png | 4 ++-- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2dcf6f327137..b6db2dfeb715 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6428,7 +6428,6 @@ dependencies = [ "anyhow", "criterion", "egui", - "egui_kittest", "itertools 0.13.0", "nohash-hasher", "once_cell", diff --git a/crates/viewer/re_time_panel/Cargo.toml b/crates/viewer/re_time_panel/Cargo.toml index 307898a5982e..626c8fa8b575 100644 --- a/crates/viewer/re_time_panel/Cargo.toml +++ b/crates/viewer/re_time_panel/Cargo.toml @@ -41,9 +41,10 @@ serde.workspace = true vec1.workspace = true [dev-dependencies] +re_viewer_context = { workspace = true, features = ["testing"] } + anyhow.workspace = true criterion.workspace = true -egui_kittest.workspace = true rand.workspace = true [lib] diff --git a/crates/viewer/re_time_panel/src/lib.rs b/crates/viewer/re_time_panel/src/lib.rs index 0766882f467b..6543d561b7ce 100644 --- a/crates/viewer/re_time_panel/src/lib.rs +++ b/crates/viewer/re_time_panel/src/lib.rs @@ -444,11 +444,13 @@ impl TimePanel { let timeline_rect = { let top = ui.min_rect().bottom(); + ui.add_space(-4.0); // hack to vertically center the text + let size = egui::vec2(self.prev_col_width, 28.0); ui.allocate_ui_with_layout(size, egui::Layout::top_down(egui::Align::LEFT), |ui| { ui.set_min_size(size); ui.style_mut().wrap_mode = Some(egui::TextWrapMode::Extend); - ui.add_space(4.0); // hack to vertically center the text + ui.spacing_mut().item_spacing.y = 0.0; ui.full_span_scope(0.0..=time_x_left, |ui| { self.filter_state.ui( @@ -461,6 +463,8 @@ impl TimePanel { .strong(), ); }); + + ui.add_space(2.0); // hack to vertically center the text }) .response .on_hover_text( diff --git a/crates/viewer/re_time_panel/tests/snapshots/time_panel_dense_data.png b/crates/viewer/re_time_panel/tests/snapshots/time_panel_dense_data.png index 0afc9600de09..2d30e99a20b8 100644 --- a/crates/viewer/re_time_panel/tests/snapshots/time_panel_dense_data.png +++ b/crates/viewer/re_time_panel/tests/snapshots/time_panel_dense_data.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f1ef5ede53c243b9d9986f4a502f3b232da202815a24a325bab737b07a69e64e -size 27223 +oid sha256:da37f484f89f6e385fadfc6ffcbd8d4119dcbc6236bf5f91d16cc711074d5189 +size 25965 diff --git a/crates/viewer/re_time_panel/tests/snapshots/time_panel_two_sections.png b/crates/viewer/re_time_panel/tests/snapshots/time_panel_two_sections.png index 857e28cef367..ef2c4cc7a969 100644 --- a/crates/viewer/re_time_panel/tests/snapshots/time_panel_two_sections.png +++ b/crates/viewer/re_time_panel/tests/snapshots/time_panel_two_sections.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:877df4e6bc5be8caa89fb5e721e32527701260ba249fa8313cb78d7828573be9 -size 32092 +oid sha256:7e2086ecac13e41e291aa7780e006faf05a9cc9e9f26c3410f67af152603c963 +size 32001 From 8bab31f1b2a4e62971a3e5b71bc6370f0fee8902 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler Date: Mon, 13 Jan 2025 11:54:01 +0100 Subject: [PATCH 08/10] remove dead code --- crates/viewer/re_time_panel/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/viewer/re_time_panel/src/lib.rs b/crates/viewer/re_time_panel/src/lib.rs index 6543d561b7ce..9fd603b4c400 100644 --- a/crates/viewer/re_time_panel/src/lib.rs +++ b/crates/viewer/re_time_panel/src/lib.rs @@ -751,8 +751,6 @@ impl TimePanel { let is_short_path = tree.path.len() <= 1 && !tree.is_leaf(); let default_open = self.filter_state.session_id().is_some() || is_short_path; - //dbg!((collapse_scope, default_open)); - let list_item::ShowCollapsingResponse { item_response: response, body_response, From 913bbf5d55f72c11e7cf3e5d3625ae3cfa95df65 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler <49431240+abey79@users.noreply.github.com> Date: Mon, 13 Jan 2025 15:25:44 +0100 Subject: [PATCH 09/10] Update crates/viewer/re_time_panel/src/lib.rs Co-authored-by: Andreas Reich --- crates/viewer/re_time_panel/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/viewer/re_time_panel/src/lib.rs b/crates/viewer/re_time_panel/src/lib.rs index 9fd603b4c400..26dba6ad9b26 100644 --- a/crates/viewer/re_time_panel/src/lib.rs +++ b/crates/viewer/re_time_panel/src/lib.rs @@ -138,7 +138,7 @@ pub struct TimePanel { /// Which source is the time panel controlling? source: TimePanelSource, - /// The filter widget state + /// Filtering of entity paths shown in the panel (when expanded). #[serde(skip)] filter_state: filter_widget::FilterState, From 9b1d3dbe4ed02d6cf89884183439d5c7a69c4878 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler Date: Mon, 13 Jan 2025 15:45:34 +0100 Subject: [PATCH 10/10] invalidate filter against app id instead of recording id --- crates/viewer/re_time_panel/src/lib.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/viewer/re_time_panel/src/lib.rs b/crates/viewer/re_time_panel/src/lib.rs index 26dba6ad9b26..fafc93f5287f 100644 --- a/crates/viewer/re_time_panel/src/lib.rs +++ b/crates/viewer/re_time_panel/src/lib.rs @@ -26,8 +26,8 @@ use re_data_ui::DataUi as _; use re_data_ui::{item_ui::guess_instance_path_icon, sorted_component_list_for_ui}; use re_entity_db::{EntityDb, EntityTree, InstancePath}; use re_log_types::{ - external::re_types_core::ComponentName, ComponentPath, EntityPath, ResolvedTimeRange, TimeInt, - TimeReal, TimeType, + external::re_types_core::ComponentName, ApplicationId, ComponentPath, EntityPath, + ResolvedTimeRange, TimeInt, TimeReal, TimeType, }; use re_types::blueprint::components::PanelState; use re_ui::{filter_widget, list_item, ContextExt as _, DesignTokens, UiExt as _}; @@ -144,10 +144,10 @@ pub struct TimePanel { /// The store id the filter widget relates to. /// - /// Used to invalidate the filter state (aka deactivate it) when the user switch the current - /// recording. + /// Used to invalidate the filter state (aka deactivate it) when the user switches to a + /// recording with a different application id. #[serde(skip)] - filter_state_store_id: Option, + filter_state_app_id: Option, } impl Default for TimePanel { @@ -162,7 +162,7 @@ impl Default for TimePanel { time_control_ui: TimeControlUi, source: TimePanelSource::Recording, filter_state: Default::default(), - filter_state_store_id: None, + filter_state_app_id: None, } } } @@ -199,9 +199,9 @@ impl TimePanel { } // Invalidate the filter widget if the store id has changed. - if self.filter_state_store_id != Some(entity_db.store_id()) { + if self.filter_state_app_id.as_ref() != Some(&ctx.store_context.app_id) { self.filter_state = Default::default(); - self.filter_state_store_id = Some(entity_db.store_id()); + self.filter_state_app_id = Some(ctx.store_context.app_id.clone()); } self.data_density_graph_painter.begin_frame(ui.ctx());