From 487c1ac9f3e40cd115958df2d050e927d7556d0c Mon Sep 17 00:00:00 2001 From: Antoine Beyeler Date: Wed, 5 Feb 2025 08:49:06 +0100 Subject: [PATCH 01/11] First draft with existing tests passing --- crates/viewer/re_blueprint_tree/src/data.rs | 242 +++--- .../query-ath_t/proj_with_placeholder.snap | 2 +- .../query-path/proj_with_placeholder.snap | 2 +- .../query-t/proj_with_placeholder.snap | 2 +- .../re_time_panel/src/streams_tree_data.rs | 97 ++- crates/viewer/re_ui/src/filter_widget.rs | 799 +++++++++++++++--- 6 files changed, 870 insertions(+), 274 deletions(-) diff --git a/crates/viewer/re_blueprint_tree/src/data.rs b/crates/viewer/re_blueprint_tree/src/data.rs index 986b522d89fb..f6fef8856078 100644 --- a/crates/viewer/re_blueprint_tree/src/data.rs +++ b/crates/viewer/re_blueprint_tree/src/data.rs @@ -17,7 +17,7 @@ use re_entity_db::InstancePath; use re_log_types::external::re_types_core::ViewClassIdentifier; use re_log_types::EntityPath; use re_types::blueprint::components::Visible; -use re_ui::filter_widget::FilterMatcher; +use re_ui::filter_widget::{FilterMatcher, HierarchyRanges}; use re_viewer_context::{ CollapseScope, ContainerId, Contents, ContentsName, DataQueryResult, DataResultNode, Item, ViewId, ViewerContext, VisitorControlFlow, @@ -216,6 +216,7 @@ impl ViewData { // let mut hierarchy = Vec::with_capacity(10); + let mut hierarchy_ranges = HierarchyRanges::default(); let origin_tree = DataResultData::from_data_result_and_filter( ctx, view_blueprint, @@ -223,12 +224,13 @@ impl ViewData { &DataResultNodeOrPath::from_path_lookup(result_tree, &view_blueprint.space_origin), false, &mut hierarchy, + &mut hierarchy_ranges, filter_matcher, - false, ); debug_assert!(hierarchy.is_empty()); hierarchy.clear(); + hierarchy_ranges.clear(); // // Data results outside the view origin subtree (a.k.a projections) @@ -266,12 +268,13 @@ impl ViewData { &DataResultNodeOrPath::DataResultNode(node), true, &mut hierarchy, + &mut hierarchy_ranges, filter_matcher, - false, ); debug_assert!(hierarchy.is_empty()); hierarchy.clear(); + hierarchy_ranges.clear(); projection_tree }) @@ -322,7 +325,7 @@ impl ViewData { // --- /// The various kind of things that may be represented in a data result tree. -#[derive(Debug)] +#[derive(Debug, PartialEq)] #[cfg_attr(feature = "testing", derive(serde::Serialize, serde::Deserialize))] pub enum DataResultKind { /// This is a regular entity part of a data result (or the tree that contains it). @@ -368,8 +371,8 @@ impl DataResultData { data_result_or_path: &DataResultNodeOrPath<'_>, projection: bool, hierarchy: &mut Vec, + hierarchy_ranges: &mut HierarchyRanges, filter_matcher: &FilterMatcher, - mut is_already_a_match: bool, ) -> Option { re_tracing::profile_function!(); @@ -395,108 +398,39 @@ impl DataResultData { }; // - // Filtering + // Figure out what sort of node this is. // - // We must special case origin placeholder in projection. Although it does show up (as, - // well, a placeholder), it shouldn't be considered for matching as its entity part is not - // displayed. - let is_origin_placeholder = projection && entity_path == view_blueprint.space_origin; - - if !is_already_a_match && !is_origin_placeholder { - let current_path_matches = - filter_matcher.matches_hierarchy(hierarchy.iter().map(|s| s.as_str())); - is_already_a_match |= current_path_matches; + enum LeafOrNot<'a> { + Leaf, + NotLeaf(&'a DataResultNode), } - // here are some highlights if we end up being a match - let highlight_sections = || -> SmallVec<_> { - if is_origin_placeholder { - SmallVec::new() - } else if let Some(entity_part_ui_string) = &entity_part_ui_string { - filter_matcher - .find_ranges_for_keywords(entity_part_ui_string) - .collect() - } else { - SmallVec::new() - } - }; - - // - // "Nominal" data result node (extracted for deduplication). - // - - let view_id = view_blueprint.id; - let mut from_data_result_node = - |data_result_node: &DataResultNode, entity_path: EntityPath, label, default_open| { - let mut children = data_result_node - .children - .iter() - .filter_map(|child_handle| { - let child_node = query_result.tree.lookup_node(*child_handle); - - debug_assert!( - child_node.is_some(), - "DataResultNode {data_result_node:?} has an invalid child" - ); - - child_node.and_then(|child_node| { - Self::from_data_result_and_filter( - ctx, - view_blueprint, - query_result, - &DataResultNodeOrPath::DataResultNode(child_node), - projection, - hierarchy, - filter_matcher, - is_already_a_match, - ) - }) - }) - .collect_vec(); - - // This is needed because `DataResultNode` stores children in a `SmallVec`, offering - // no guarantees about ordering. - children.sort_by(|a, b| a.entity_path.cmp(&b.entity_path)); - - (is_already_a_match || !children.is_empty()).then(|| Self { - kind: DataResultKind::EntityPart, - entity_path, - visible, - view_id, - label, - highlight_sections: highlight_sections(), - default_open, - children, - }) - }; - - // - // Handle all situations - // - - let result = if projection { - // projections are collapsed by default - let default_open = filter_matcher.is_active(); + struct NodeInfo<'a> { + leaf_or_not: LeafOrNot<'a>, + kind: DataResultKind, + default_open: bool, + } + let node_info = if projection { if entity_path == view_blueprint.space_origin { - is_already_a_match.then(|| Self { + Some(NodeInfo { + leaf_or_not: LeafOrNot::Leaf, kind: DataResultKind::OriginProjectionPlaceholder, - entity_path, - visible, - view_id, - label, - highlight_sections: highlight_sections(), - default_open, - children: vec![], + // not hierarchical anyway + default_open: false, }) } else if let Some(data_result_node) = data_result_node { - from_data_result_node( - data_result_node, - entity_path, - label, - filter_matcher.is_active(), - ) + Some(NodeInfo { + leaf_or_not: if data_result_node.children.is_empty() { + LeafOrNot::Leaf + } else { + LeafOrNot::NotLeaf(data_result_node) + }, + kind: DataResultKind::EntityPart, + // projections are collapsed by default + default_open: filter_matcher.is_active(), + }) } else { // TODO(ab): what are the circumstances for this? Should we warn about it? None @@ -504,28 +438,116 @@ impl DataResultData { } else { // empty origin case if entity_path == view_blueprint.space_origin && data_result_node.is_none() { - is_already_a_match.then(|| Self { + Some(NodeInfo { + leaf_or_not: LeafOrNot::Leaf, kind: DataResultKind::EmptyOriginPlaceholder, - entity_path, - visible, - view_id, - label, - highlight_sections: highlight_sections(), - default_open: false, // not hierarchical anyway - children: vec![], + // not hierarchical anyway + default_open: false, }) } else if let Some(data_result_node) = data_result_node { - let default_open = filter_matcher.is_active() - || default_open_for_data_result(data_result_node.children.len()); - - from_data_result_node(data_result_node, entity_path, label, default_open) + Some(NodeInfo { + leaf_or_not: if data_result_node.children.is_empty() { + LeafOrNot::Leaf + } else { + LeafOrNot::NotLeaf(data_result_node) + }, + kind: DataResultKind::EntityPart, + default_open: filter_matcher.is_active() + || default_open_for_data_result(data_result_node.children.len()), + }) } else { // TODO(ab): what are the circumstances for this? Should we warn about it? None } }; + // + // Handle the node accordingly. + // + + let result = node_info + .map(|node_info| { + let (is_this_a_match, children) = match node_info.leaf_or_not { + LeafOrNot::Leaf => { + //TODO: rename this + let hierarchy_highlights = filter_matcher + .matches_hierarchy_v2(hierarchy.iter().map(String::as_str)); + + let is_this_a_match = + if let Some(hierarchy_highlights) = hierarchy_highlights { + hierarchy_ranges.merge(hierarchy_highlights); + true + } else { + false + }; + + (is_this_a_match, vec![]) + } + + LeafOrNot::NotLeaf(data_result_node) => { + let mut children = data_result_node + .children + .iter() + .filter_map(|child_handle| { + let child_node = query_result.tree.lookup_node(*child_handle); + + debug_assert!( + child_node.is_some(), + "DataResultNode {data_result_node:?} has an invalid child" + ); + + child_node.and_then(|child_node| { + Self::from_data_result_and_filter( + ctx, + view_blueprint, + query_result, + &DataResultNodeOrPath::DataResultNode(child_node), + projection, + hierarchy, + hierarchy_ranges, + filter_matcher, + ) + }) + }) + .collect_vec(); + + // This is needed because `DataResultNode` stores children in a `SmallVec`, offering + // no guarantees about ordering. + children.sort_by(|a, b| a.entity_path.cmp(&b.entity_path)); + + let is_this_a_match = !children.is_empty(); + + (is_this_a_match, children) + } + }; + + let highlight_sections = hierarchy_ranges.remove(hierarchy.len().saturating_sub(1)); + + // never highlight the placeholder + let highlight_sections = + if node_info.kind == DataResultKind::OriginProjectionPlaceholder { + SmallVec::new() + } else { + highlight_sections + .map(Iterator::collect) + .unwrap_or_default() + }; + + is_this_a_match.then(|| Self { + kind: node_info.kind, + entity_path, + visible, + view_id: view_blueprint.id, + label, + highlight_sections, + default_open: node_info.default_open, + children, + }) + }) + .flatten(); + if should_pop { + hierarchy_ranges.remove(hierarchy.len().saturating_sub(1)); hierarchy.pop(); } diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_t/proj_with_placeholder.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_t/proj_with_placeholder.snap index c1c4ae6e3115..b47283d1f92c 100644 --- a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_t/proj_with_placeholder.snap +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_t/proj_with_placeholder.snap @@ -51,5 +51,5 @@ root_container: id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe label: to highlight_sections: [] - default_open: true + default_open: false children: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/proj_with_placeholder.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/proj_with_placeholder.snap index 47f2c260bd61..116076911965 100644 --- a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/proj_with_placeholder.snap +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/proj_with_placeholder.snap @@ -51,5 +51,5 @@ root_container: id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe label: to highlight_sections: [] - default_open: true + default_open: false children: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/proj_with_placeholder.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/proj_with_placeholder.snap index 137c51cdad6f..2d4db25f39d5 100644 --- a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/proj_with_placeholder.snap +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/proj_with_placeholder.snap @@ -142,5 +142,5 @@ root_container: id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe label: to highlight_sections: [] - default_open: true + default_open: false children: [] diff --git a/crates/viewer/re_time_panel/src/streams_tree_data.rs b/crates/viewer/re_time_panel/src/streams_tree_data.rs index 4d3b0b4e7301..b9c9af96280a 100644 --- a/crates/viewer/re_time_panel/src/streams_tree_data.rs +++ b/crates/viewer/re_time_panel/src/streams_tree_data.rs @@ -8,7 +8,7 @@ use re_data_ui::sorted_component_list_for_ui; use re_entity_db::{EntityTree, InstancePath}; use re_log_types::EntityPath; use re_types_core::ComponentName; -use re_ui::filter_widget::FilterMatcher; +use re_ui::filter_widget::{FilterMatcher, HierarchyRanges}; use re_viewer_context::{CollapseScope, Item, ViewerContext, VisitorControlFlow}; use crate::time_panel::TimePanelSource; @@ -32,7 +32,14 @@ impl StreamsTreeData { TimePanelSource::Blueprint => ctx.blueprint_db(), }; - let root_data = EntityData::from_entity_tree_and_filter(db.tree(), filter_matcher, false); + let mut hierarchy = Vec::default(); + let mut hierarchy_ranges = HierarchyRanges::default(); + let root_data = EntityData::from_entity_tree_and_filter( + db.tree(), + filter_matcher, + &mut hierarchy, + &mut hierarchy_ranges, + ); // We show "/" on top only for recording streams, because the `/` entity in blueprint // is always empty, so it's just lost space. This works around an issue where the @@ -96,7 +103,8 @@ impl EntityData { pub fn from_entity_tree_and_filter( entity_tree: &EntityTree, filter_matcher: &FilterMatcher, - mut is_already_a_match: bool, + hierarchy: &mut Vec, + hierarchy_ranges: &mut HierarchyRanges, ) -> Option { // Early out if filter_matcher.matches_nothing() { @@ -109,60 +117,72 @@ impl EntityData { .map(|entity_part| entity_part.ui_string()); let mut label = entity_part_ui_string.clone().unwrap_or("/".to_owned()); + let must_pop = if let Some(part) = &entity_part_ui_string { + hierarchy.push(part.clone()); + true + } else { + false + }; + // - // Filtering + // Recurse // - if !is_already_a_match { - let current_path_matches = filter_matcher - .matches_hierarchy(entity_tree.path.iter().map(|p| p.unescaped_str())); + let result = if entity_tree.children.is_empty() { + // We're a child node, so we must decide if the hierarchy matches the filter. - is_already_a_match |= current_path_matches; - } + //TODO: rename this + let hierarchy_highlights = + filter_matcher.matches_hierarchy_v2(hierarchy.iter().map(String::as_str)); - // here are some highlights if we end up being a match - let highlight_sections = || -> SmallVec<_> { - if let Some(entity_part_ui_string) = &entity_part_ui_string { - filter_matcher - .find_ranges_for_keywords(entity_part_ui_string) - .collect() - } else { - SmallVec::new() - } - }; + if let Some(hierarchy_highlights) = hierarchy_highlights { + hierarchy_ranges.merge(hierarchy_highlights); - // - // Recurse - // + let highlight_sections = hierarchy_ranges + .remove(hierarchy.len().saturating_sub(1)) + .map(Iterator::collect) + .unwrap_or_default(); - if entity_tree.children.is_empty() { - // Discard a leaf item unless it is already a match. - is_already_a_match.then(|| { // Leaf items are always collapsed by default, even when the filter is active. let default_open = false; - Self { + Some(Self { entity_path: entity_tree.path.clone(), label, - highlight_sections: highlight_sections(), + highlight_sections, default_open, children: vec![], - } - }) + }) + } else { + None + } } else { let children = entity_tree .children .values() .filter_map(|sub_tree| { - Self::from_entity_tree_and_filter(sub_tree, filter_matcher, is_already_a_match) + Self::from_entity_tree_and_filter( + sub_tree, + filter_matcher, + hierarchy, + hierarchy_ranges, + ) }) .collect_vec(); - (is_already_a_match || !children.is_empty()).then(|| { + if children.is_empty() { + None + } else { // Only top-level non-leaf entities are expanded by default, unless the filter is // active. let default_open = filter_matcher.is_active() || entity_tree.path.len() <= 1; - Self { + + let highlight_sections = hierarchy_ranges + .remove(hierarchy.len().saturating_sub(1)) + .map(Iterator::collect) + .unwrap_or_default(); + + Some(Self { entity_path: entity_tree.path.clone(), label: if children.is_empty() || entity_tree.path.is_root() { label @@ -171,12 +191,19 @@ impl EntityData { label.push('/'); label }, - highlight_sections: highlight_sections(), + highlight_sections, default_open, children, - } - }) + }) + } + }; + + if must_pop { + hierarchy_ranges.remove(hierarchy.len().saturating_sub(1)); + hierarchy.pop(); } + + result } /// Visit this entity, included its components in the provided store. diff --git a/crates/viewer/re_ui/src/filter_widget.rs b/crates/viewer/re_ui/src/filter_widget.rs index 486eacf0c8b9..5ff7eb8833d1 100644 --- a/crates/viewer/re_ui/src/filter_widget.rs +++ b/crates/viewer/re_ui/src/filter_widget.rs @@ -1,7 +1,9 @@ use std::ops::Range; use egui::{Color32, NumExt as _, Widget as _}; -use itertools::{Either, Itertools}; +use itertools::Itertools; + +use re_entity_db::external::re_chunk_store::external::re_chunk::external::nohash_hasher::IntMap; use crate::{list_item, UiExt as _}; @@ -145,9 +147,6 @@ impl FilterState { .lock_focus(true) .ui(ui); - //TODO(ab): is there a better way to do that? - inner_state.filter_query = inner_state.filter_query.replace('/', ""); - if self.request_focus { self.request_focus = false; response.request_focus(); @@ -184,13 +183,13 @@ pub struct FilterMatcher { /// /// If this is `None`, the filter is inactive and the matcher will accept everything. If this /// is `Some([])`, the matcher will reject any input. - keywords: Option>, + keywords: Option>, } impl FilterMatcher { fn new(query: Option<&str>) -> Self { Self { - keywords: query.map(|s| s.split_whitespace().map(str::to_lowercase).collect()), + keywords: query.map(|s| s.split_whitespace().map(Keyword::new).collect()), } } @@ -215,113 +214,476 @@ impl FilterMatcher { .is_some_and(|keywords| keywords.is_empty()) } - /// Does the given text match the filter? - pub fn matches(&self, text: &str) -> bool { + // /// Does the given text match the filter? + // pub fn matches(&self, text: &str) -> bool { + // match self.keywords.as_deref() { + // None => true, + // Some([]) => false, + // Some(keywords) => { + // let lowercase_input = text.to_lowercase(); + // keywords + // .iter() + // .all(|keyword| lowercase_input.contains(keyword)) + // } + // } + // } + + // /// Does the given hierarchy match the filter? + // /// + // /// To match, each of the keyword must be present in at least one of the parts of the hierarchy. + // pub fn matches_hierarchy<'a>(&self, hierarchy: impl IntoIterator) -> bool { + // match self.keywords.as_deref() { + // None => true, + // Some([]) => false, + // Some(keywords) => { + // let mut keyword_matches = vec![false; keywords.len()]; + // + // for part in hierarchy { + // let lowercase_input = part.to_lowercase(); + // for (i, keyword) in keywords.iter().enumerate() { + // if !keyword_matches[i] && lowercase_input.contains(keyword) { + // keyword_matches[i] = true; + // + // if keyword_matches.iter().all(|&b| b) { + // return true; + // } + // } + // } + // } + // + // false + // } + // } + // } + + //TODO + pub fn matches_hierarchy_v2<'a>( + &self, + hierarchy: impl IntoIterator, + ) -> Option { match self.keywords.as_deref() { - None => true, - Some([]) => false, + None => Some(HierarchyRanges::default()), + Some([]) => None, Some(keywords) => { - let lowercase_input = text.to_lowercase(); - keywords + let hierarchy = hierarchy.into_iter().map(str::to_lowercase).collect_vec(); + + let all_ranges = keywords .iter() - .all(|keyword| lowercase_input.contains(keyword)) + .map(|keyword| keyword.match_hierarchy(hierarchy.iter().map(String::as_str))) + .collect_vec(); + + // all keywords must match! + if all_ranges.iter().any(|ranges| ranges.is_empty()) { + None + } else { + let mut result = HierarchyRanges::default(); + for ranges in all_ranges { + result.merge(ranges); + } + Some(result) + } } } } - /// Does the given hierarchy match the filter? + // /// Match the input text and return match ranges if any. + // /// + // /// This function does apply the full matching semantics: + // /// - It returns `None` when there is no match. + // /// - It returns `Some` when the filter is inactive (and thus matches everything), or if there + // /// is an actual match. + // /// + // /// See [`format_matching_text`] for formatting text according to the returned ranges. + // pub fn find_matches(&self, text: &str) -> Option> + '_> { + // let keywords = match self.keywords.as_deref() { + // None => { + // return Some(Either::Left(std::iter::empty())); + // } + // Some([]) => { + // return None; + // } + // Some(keywords) => keywords, + // }; + // + // let lower_case_text = text.to_lowercase(); + // + // let mut all_ranges = vec![]; + // for keyword in keywords { + // if lower_case_text.contains(keyword) { + // all_ranges.extend(single_keyword_matches(&lower_case_text, keyword)); + // } else { + // return None; + // } + // } + // + // Some(Either::Right(MergeRanges::new(all_ranges))) + // } + + // /// Find match ranges for any of the keywords in the provided input. + // /// + // /// Note that this function does not perform any actual matching semantics. It just provides + // /// highlighting information for a hierarchy part that has already been tested for match using + // /// [`Self::matches_hierarchy`]. + // pub fn find_ranges_for_keywords(&self, text: &str) -> impl Iterator> + '_ { + // let keywords = match self.keywords.as_deref() { + // None | Some([]) => { + // return Either::Left(std::iter::empty()); + // } + // + // Some(keywords) => keywords, + // }; + // + // let lower_case_text = text.to_lowercase(); + // + // let all_ranges = keywords + // .iter() + // .flat_map(|keyword| single_keyword_matches(&lower_case_text, keyword)) + // .collect_vec(); + // + // Either::Right(MergeRanges::new(all_ranges)) + // } + + // /// Returns a formatted version of the text with the matching sections highlighted. + // /// + // /// Returns `None` when there is no match (so nothing should be displayed). + // /// Returns `Some` when the filter is inactive (and thus matches everything), or if there is an + // /// actual match. + // pub fn matches_formatted(&self, ctx: &egui::Context, text: &str) -> Option { + // self.find_matches(text) + // .map(|match_iter| format_matching_text(ctx, text, match_iter, None)) + // } +} + +// /// Full-text, case-insensitive matcher. +// pub struct FilterMatcher { +// /// Lowercase keywords. +// /// +// /// If this is `None`, the filter is inactive and the matcher will accept everything. If this +// /// is `Some([])`, the matcher will reject any input. +// keywords: Option>, +// } +// +// impl FilterMatcher { +// fn new(query: Option<&str>) -> Self { +// Self { +// keywords: query.map(|s| s.split_whitespace().map(str::to_lowercase).collect()), +// } +// } +// +// /// Is the filter currently active? +// pub fn is_active(&self) -> bool { +// self.keywords.is_some() +// } +// +// /// Is the filter set to match everything? +// /// +// /// Can be used by client code to short-circuit more expansive matching logic. +// pub fn matches_everything(&self) -> bool { +// self.keywords.is_none() +// } +// +// /// Is the filter set to match nothing? +// /// +// /// Can be used by client code to short-circuit more expansive matching logic. +// pub fn matches_nothing(&self) -> bool { +// self.keywords +// .as_ref() +// .is_some_and(|keywords| keywords.is_empty()) +// } +// +// /// Does the given text match the filter? +// pub fn matches(&self, text: &str) -> bool { +// match self.keywords.as_deref() { +// None => true, +// Some([]) => false, +// Some(keywords) => { +// let lowercase_input = text.to_lowercase(); +// keywords +// .iter() +// .all(|keyword| lowercase_input.contains(keyword)) +// } +// } +// } +// +// /// Does the given hierarchy match the filter? +// /// +// /// To match, each of the keyword must be present in at least one of the parts of the hierarchy. +// pub fn matches_hierarchy<'a>(&self, hierarchy: impl IntoIterator) -> bool { +// match self.keywords.as_deref() { +// None => true, +// Some([]) => false, +// Some(keywords) => { +// let mut keyword_matches = vec![false; keywords.len()]; +// +// for part in hierarchy { +// let lowercase_input = part.to_lowercase(); +// for (i, keyword) in keywords.iter().enumerate() { +// if !keyword_matches[i] && lowercase_input.contains(keyword) { +// keyword_matches[i] = true; +// +// if keyword_matches.iter().all(|&b| b) { +// return true; +// } +// } +// } +// } +// +// false +// } +// } +// } +// +// /// Match the input text and return match ranges if any. +// /// +// /// This function does apply the full matching semantics: +// /// - It returns `None` when there is no match. +// /// - It returns `Some` when the filter is inactive (and thus matches everything), or if there +// /// is an actual match. +// /// +// /// See [`format_matching_text`] for formatting text according to the returned ranges. +// pub fn find_matches(&self, text: &str) -> Option> + '_> { +// let keywords = match self.keywords.as_deref() { +// None => { +// return Some(Either::Left(std::iter::empty())); +// } +// Some([]) => { +// return None; +// } +// Some(keywords) => keywords, +// }; +// +// let lower_case_text = text.to_lowercase(); +// +// let mut all_ranges = vec![]; +// for keyword in keywords { +// if lower_case_text.contains(keyword) { +// all_ranges.extend(single_keyword_matches(&lower_case_text, keyword)); +// } else { +// return None; +// } +// } +// +// Some(Either::Right(MergeRanges::new(all_ranges))) +// } +// +// /// Find match ranges for any of the keywords in the provided input. +// /// +// /// Note that this function does not perform any actual matching semantics. It just provides +// /// highlighting information for a hierarchy part that has already been tested for match using +// /// [`Self::matches_hierarchy`]. +// pub fn find_ranges_for_keywords(&self, text: &str) -> impl Iterator> + '_ { +// let keywords = match self.keywords.as_deref() { +// None | Some([]) => { +// return Either::Left(std::iter::empty()); +// } +// +// Some(keywords) => keywords, +// }; +// +// let lower_case_text = text.to_lowercase(); +// +// let all_ranges = keywords +// .iter() +// .flat_map(|keyword| single_keyword_matches(&lower_case_text, keyword)) +// .collect_vec(); +// +// Either::Right(MergeRanges::new(all_ranges)) +// } +// +// /// Returns a formatted version of the text with the matching sections highlighted. +// /// +// /// Returns `None` when there is no match (so nothing should be displayed). +// /// Returns `Some` when the filter is inactive (and thus matches everything), or if there is an +// /// actual match. +// pub fn matches_formatted(&self, ctx: &egui::Context, text: &str) -> Option { +// self.find_matches(text) +// .map(|match_iter| format_matching_text(ctx, text, match_iter, None)) +// } +// } + +#[derive(Debug, Clone, PartialEq)] +struct Keyword { + parts: Vec, + + match_from_first_part_start: bool, + + match_to_last_part_end: bool, +} + +impl Keyword { + /// Create a [`Self`] based on a keyword string. /// - /// To match, each of the keyword must be present in at least one of the parts of the hierarchy. - pub fn matches_hierarchy<'a>(&self, hierarchy: impl IntoIterator) -> bool { - match self.keywords.as_deref() { - None => true, - Some([]) => false, - Some(keywords) => { - let mut keyword_matches = vec![false; keywords.len()]; + /// The string must not contain any whitespace! + fn new(mut keyword: &str) -> Self { + debug_assert!(!keyword.contains(char::is_whitespace)); - for part in hierarchy { - let lowercase_input = part.to_lowercase(); - for (i, keyword) in keywords.iter().enumerate() { - if !keyword_matches[i] && lowercase_input.contains(keyword) { - keyword_matches[i] = true; + let match_from_first_part_start = if let Some(k) = keyword.strip_prefix('/') { + keyword = k; + true + } else { + false + }; - if keyword_matches.iter().all(|&b| b) { - return true; - } - } - } - } + let match_to_last_part_end = if let Some(k) = keyword.strip_suffix('/') { + keyword = k; + true + } else { + false + }; - false - } + let parts = keyword.split('/').map(str::to_lowercase).collect(); + + Self { + parts, + match_from_first_part_start, + match_to_last_part_end, } } - /// Match the input text and return match ranges if any. - /// - /// This function does apply the full matching semantics: - /// - It returns `None` when there is no match. - /// - It returns `Some` when the filter is inactive (and thus matches everything), or if there - /// is an actual match. - /// - /// See [`format_matching_text`] for formatting text according to the returned ranges. - pub fn find_matches(&self, text: &str) -> Option> + '_> { - let keywords = match self.keywords.as_deref() { - None => { - return Some(Either::Left(std::iter::empty())); - } - Some([]) => { - return None; - } - Some(keywords) => keywords, - }; + //TODO: docstring / ranges are not sorted nor merged + fn match_hierarchy<'a>(&self, hierarchy: impl IntoIterator) -> HierarchyRanges { + let mut state_machines = vec![]; - let lower_case_text = text.to_lowercase(); + for (part_index, part) in hierarchy.into_iter().enumerate() { + let lowercase_part = part.to_lowercase(); - let mut all_ranges = vec![]; - for keyword in keywords { - if lower_case_text.contains(keyword) { - all_ranges.extend(single_keyword_matches(&lower_case_text, keyword)); - } else { - return None; + state_machines.push(MatchStateMachine::new(self)); + + for state_machine in &mut state_machines { + state_machine.step(&lowercase_part, part_index); } } - Some(Either::Right(MergeRanges::new(all_ranges))) + state_machines + .into_iter() + .filter_map(|state_machine| { + if state_machine.matches() { + Some(state_machine.ranges) + } else { + None + } + }) + .fold(HierarchyRanges::default(), |mut acc, ranges| { + acc.merge(ranges); + acc + }) } +} - /// Find match ranges for any of the keywords in the provided input. - /// - /// Note that this function does not perform any actual matching semantics. It just provides - /// highlighting information for a hierarchy part that has already been tested for match using - /// [`Self::matches_hierarchy`]. - pub fn find_ranges_for_keywords(&self, text: &str) -> impl Iterator> + '_ { - let keywords = match self.keywords.as_deref() { - None | Some([]) => { - return Either::Left(std::iter::empty()); - } +#[derive(Debug, Default)] +pub struct HierarchyRanges { + ranges: IntMap>>, +} - Some(keywords) => keywords, - }; +impl HierarchyRanges { + pub fn merge(&mut self, other: Self) { + for (part_index, part_ranges) in other.ranges { + self.ranges + .entry(part_index) + .or_default() + .extend(part_ranges); + } + } - let lower_case_text = text.to_lowercase(); + pub fn extend(&mut self, part_index: usize, ranges: impl IntoIterator>) { + self.ranges.entry(part_index).or_default().extend(ranges); + } - let all_ranges = keywords - .iter() - .flat_map(|keyword| single_keyword_matches(&lower_case_text, keyword)) - .collect_vec(); + pub fn push(&mut self, part_index: usize, range: Range) { + self.ranges.entry(part_index).or_default().push(range); + } - Either::Right(MergeRanges::new(all_ranges)) + pub fn remove(&mut self, part_index: usize) -> Option>> { + self.ranges + .remove(&part_index) + .map(|ranges| MergeRanges::new(ranges).into_iter()) } - /// Returns a formatted version of the text with the matching sections highlighted. - /// - /// Returns `None` when there is no match (so nothing should be displayed). - /// Returns `Some` when the filter is inactive (and thus matches everything), or if there is an - /// actual match. - pub fn matches_formatted(&self, ctx: &egui::Context, text: &str) -> Option { - self.find_matches(text) - .map(|match_iter| format_matching_text(ctx, text, match_iter, None)) + pub fn is_empty(&self) -> bool { + self.ranges.is_empty() + } + + pub fn clear(&mut self) { + self.ranges.clear(); + } +} + +#[derive(Debug)] +enum MatchState { + InProgress, + Match, + NoMatch, +} + +#[derive(Debug)] +struct MatchStateMachine<'a> { + keyword: &'a Keyword, + current_keyword_part: usize, + state: MatchState, + ranges: HierarchyRanges, +} + +impl<'a> MatchStateMachine<'a> { + fn new(keyword: &'a Keyword) -> Self { + Self { + keyword, + current_keyword_part: 0, + state: MatchState::InProgress, + ranges: Default::default(), + } + } + + fn matches(&self) -> bool { + matches!(self.state, MatchState::Match) + } + + fn step(&mut self, part: &str, part_index: usize) { + if matches!(self.state, MatchState::Match | MatchState::NoMatch) { + return; + } + + let keyword_part = &self.keyword.parts[self.current_keyword_part]; + + let has_part_after = self.current_keyword_part < self.keyword.parts.len() - 1; + let has_part_before = 0 < self.current_keyword_part; + let must_match_from_start = has_part_before || self.keyword.match_from_first_part_start; + let must_match_to_end = has_part_after || self.keyword.match_to_last_part_end; + + let mut ranges = vec![]; + match (must_match_from_start, must_match_to_end) { + (false, false) => { + ranges.extend(single_keyword_matches(part, keyword_part)); + } + + (true, false) => { + if part.starts_with(keyword_part) { + ranges.push(0..keyword_part.len()); + } + } + + (false, true) => { + if part.ends_with(keyword_part) { + ranges.push(part.len() - keyword_part.len()..part.len()); + } + } + + (true, true) => { + if part == keyword_part { + ranges.push(0..part.len()); + } + } + } + + if ranges.is_empty() { + self.state = MatchState::NoMatch; + } else { + self.ranges.extend(part_index, ranges); + self.current_keyword_part += 1; + } + + if self.current_keyword_part == self.keyword.parts.len() { + self.state = MatchState::Match; + } } } @@ -462,69 +824,254 @@ mod test { ); } + // #[test] + // fn test_match_all() { + // let inactive_matcher = FilterMatcher::new(None); + // + // assert_eq!( + // inactive_matcher.find_matches("haystack").unwrap().count(), + // 0 + // ); + // } + // + // #[test] + // fn test_match_nothing() { + // let inactive_matcher = FilterMatcher::new(Some("")); + // + // assert!(inactive_matcher.find_matches("haystack").is_none()); + // } + // + // #[test] + // fn test_match() { + // let matcher = FilterMatcher::new(Some("str tru re")); + // + // // filter active but doesn't match + // assert!(matcher.find_matches("struct").is_none()); + // + // assert_eq!( + // matcher.find_matches("structure").unwrap().collect_vec(), + // [0..4, 7..9] + // ); + // } + + // #[test] + // fn test_match_hierarchy() { + // let matcher = FilterMatcher::new(Some("one TWo three")); + // + // // matches + // assert!(matcher.matches_hierarchy(["oNe", "two", "three"])); + // assert!(matcher.matches_hierarchy(["tHRee", "One", "two"])); + // assert!(matcher.matches_hierarchy(["three", "one", "nothing", "two"])); + // assert!(matcher.matches_hierarchy(["thrEEone", "nothing", "TWO"])); + // assert!(matcher.matches_hierarchy(["three", "twONE"])); + // + // // doesn't match + // assert!(!matcher.matches_hierarchy(["one", "two", "four"])); + // } + // + // #[test] + // fn test_find_ranges_for_keywords() { + // let matcher = FilterMatcher::new(Some("one two three")); + // + // assert_eq!(matcher.find_ranges_for_keywords("haystack").count(), 0); + // assert_eq!( + // matcher.find_ranges_for_keywords("xxONExx").collect_vec(), + // [2..5] + // ); + // assert_eq!( + // matcher.find_ranges_for_keywords("xxTWonExx").collect_vec(), + // [2..7] + // ); + // assert_eq!( + // matcher + // .find_ranges_for_keywords("xxTWonExthree") + // .collect_vec(), + // [2..7, 8..13] + // ); + // } + #[test] - fn test_match_all() { - let inactive_matcher = FilterMatcher::new(None); + fn test_keyword() { + assert_eq!( + Keyword::new("a"), + Keyword { + parts: vec!["a".into()], + match_from_first_part_start: false, + match_to_last_part_end: false + } + ); assert_eq!( - inactive_matcher.find_matches("haystack").unwrap().count(), - 0 + Keyword::new("/a"), + Keyword { + parts: vec!["a".into()], + match_from_first_part_start: true, + match_to_last_part_end: false + } ); - } - #[test] - fn test_match_nothing() { - let inactive_matcher = FilterMatcher::new(Some("")); + assert_eq!( + Keyword::new("a/"), + Keyword { + parts: vec!["a".into()], + match_from_first_part_start: false, + match_to_last_part_end: true + } + ); - assert!(inactive_matcher.find_matches("haystack").is_none()); - } + assert_eq!( + Keyword::new("/a/"), + Keyword { + parts: vec!["a".into()], + match_from_first_part_start: true, + match_to_last_part_end: true + } + ); - #[test] - fn test_match() { - let matcher = FilterMatcher::new(Some("str tru re")); + assert_eq!( + Keyword::new("a/b"), + Keyword { + parts: vec!["a".into(), "b".into()], + match_from_first_part_start: false, + match_to_last_part_end: false + } + ); - // filter active but doesn't match - assert!(matcher.find_matches("struct").is_none()); + assert_eq!( + Keyword::new("a/b/"), + Keyword { + parts: vec!["a".into(), "b".into()], + match_from_first_part_start: false, + match_to_last_part_end: true + } + ); assert_eq!( - matcher.find_matches("structure").unwrap().collect_vec(), - [0..4, 7..9] + Keyword::new("/a/b/c/d"), + Keyword { + parts: vec!["a".into(), "b".into(), "c".into(), "d".into()], + match_from_first_part_start: true, + match_to_last_part_end: false + } ); } #[test] - fn test_match_hierarchy() { - let matcher = FilterMatcher::new(Some("one TWo three")); - - // matches - assert!(matcher.matches_hierarchy(["oNe", "two", "three"])); - assert!(matcher.matches_hierarchy(["tHRee", "One", "two"])); - assert!(matcher.matches_hierarchy(["three", "one", "nothing", "two"])); - assert!(matcher.matches_hierarchy(["thrEEone", "nothing", "TWO"])); - assert!(matcher.matches_hierarchy(["three", "twONE"])); - - // doesn't match - assert!(!matcher.matches_hierarchy(["one", "two", "four"])); + fn test_keyword_match_hierarchy() { + fn match_and_normalize(query: &str, hierarchy: &[&str]) -> Vec>> { + let keyword = Keyword::new(query); + let hierarchy = hierarchy.to_vec(); + + let mut ranges = keyword.match_hierarchy(hierarchy.clone()); + + let result = (0..hierarchy.len()) + .map(|i| { + ranges + .remove(i) + .map(|iter| iter.collect_vec()) + .unwrap_or_else(Vec::new) + }) + .collect(); + + assert!(ranges.is_empty()); + + result + } + + assert_eq!(match_and_normalize("a", &["a"]), vec![vec![0..1]]); + assert_eq!(match_and_normalize("a", &["aaa"]), vec![vec![0..3]]); + + assert_eq!( + match_and_normalize("A/", &["aaa", "aaa"]), + vec![vec![2..3], vec![2..3]] + ); + + assert_eq!( + match_and_normalize("/a", &["aaa", "aaa"]), + vec![vec![0..1], vec![0..1]] + ); + + assert_eq!( + match_and_normalize("/a", &["aaa", "bbb"]), + vec![vec![0..1], vec![]] + ); + + assert_eq!( + match_and_normalize("a/b", &["aaa", "bbb"]), + vec![vec![2..3], vec![0..1]] + ); + + assert_eq!( + match_and_normalize("a/b/c", &["aaa", "b", "cccc"]), + vec![vec![2..3], vec![0..1], vec![0..1]] + ); + + assert!( + match_and_normalize("/a/b/c", &["aaa", "b", "cccc"]) + .into_iter() + .flatten() + .count() + == 0, + ); + + assert!( + match_and_normalize("a/B/c/", &["aaa", "b", "cccc"]) + .into_iter() + .flatten() + .count() + == 0, + ); + + assert_eq!( + match_and_normalize("ab/cd", &["xxxAb", "cDaB", "Cdxxx"]), + vec![vec![3..5], vec![0..4], vec![0..2]] + ); + + assert_eq!( + match_and_normalize("ab/ab", &["xxxAb", "aB", "aBxxx"]), + vec![vec![3..5], vec![0..2], vec![0..2]] + ); } #[test] - fn test_find_ranges_for_keywords() { - let matcher = FilterMatcher::new(Some("one two three")); + fn test_matches_hierarchy_v2() { + fn match_and_normalize(query: &str, hierarchy: &[&str]) -> Option>>> { + let matcher = FilterMatcher::new(Some(query)); + let hierarchy = hierarchy.to_vec(); + + matcher + .matches_hierarchy_v2(hierarchy.clone()) + .map(|mut ranges| { + let result = (0..hierarchy.len()) + .map(|i| { + ranges + .remove(i) + .map(|iter| iter.collect_vec()) + .unwrap_or_else(Vec::new) + }) + .collect(); + + assert!(ranges.is_empty()); + + result + }) + } - assert_eq!(matcher.find_ranges_for_keywords("haystack").count(), 0); assert_eq!( - matcher.find_ranges_for_keywords("xxONExx").collect_vec(), - [2..5] + match_and_normalize("ab/cd", &["xxxAb", "cDaB", "Cdxxx"]), + Some(vec![vec![3..5], vec![0..4], vec![0..2]]) ); + assert_eq!( - matcher.find_ranges_for_keywords("xxTWonExx").collect_vec(), - [2..7] + match_and_normalize("ab/cd xx/", &["xxxAb", "cDaB", "Cdxxx"]), + Some(vec![vec![3..5], vec![0..4], vec![0..2, 3..5]]) ); + assert_eq!( - matcher - .find_ranges_for_keywords("xxTWonExthree") - .collect_vec(), - [2..7, 8..13] + match_and_normalize("ab/cd bla", &["xxxAb", "cDaB", "Cdxxx"]), + None ); + + //TODO: moar tests } } From 9d481f208a4f35d87590c60301a1e06b33c6fbed Mon Sep 17 00:00:00 2001 From: Antoine Beyeler Date: Wed, 5 Feb 2025 10:56:16 +0100 Subject: [PATCH 02/11] Dead code, re_ui_example update, and cleanup pass --- crates/viewer/re_blueprint_tree/src/data.rs | 144 ++++---- .../re_time_panel/src/streams_tree_data.rs | 2 +- .../re_ui/examples/re_ui_example/main.rs | 10 +- crates/viewer/re_ui/src/filter_widget.rs | 334 +----------------- 4 files changed, 86 insertions(+), 404 deletions(-) diff --git a/crates/viewer/re_blueprint_tree/src/data.rs b/crates/viewer/re_blueprint_tree/src/data.rs index f6fef8856078..cd104b7e676b 100644 --- a/crates/viewer/re_blueprint_tree/src/data.rs +++ b/crates/viewer/re_blueprint_tree/src/data.rs @@ -325,7 +325,7 @@ impl ViewData { // --- /// The various kind of things that may be represented in a data result tree. -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Eq)] #[cfg_attr(feature = "testing", derive(serde::Serialize, serde::Deserialize))] pub enum DataResultKind { /// This is a regular entity part of a data result (or the tree that contains it). @@ -412,6 +412,7 @@ impl DataResultData { default_open: bool, } + #[expect(clippy::manual_map)] let node_info = if projection { if entity_path == view_blueprint.space_origin { Some(NodeInfo { @@ -465,86 +466,83 @@ impl DataResultData { // Handle the node accordingly. // - let result = node_info - .map(|node_info| { - let (is_this_a_match, children) = match node_info.leaf_or_not { - LeafOrNot::Leaf => { - //TODO: rename this - let hierarchy_highlights = filter_matcher - .matches_hierarchy_v2(hierarchy.iter().map(String::as_str)); - - let is_this_a_match = - if let Some(hierarchy_highlights) = hierarchy_highlights { - hierarchy_ranges.merge(hierarchy_highlights); - true - } else { - false - }; - - (is_this_a_match, vec![]) - } + let result = node_info.and_then(|node_info| { + let (is_this_a_match, children) = match node_info.leaf_or_not { + LeafOrNot::Leaf => { + //TODO: rename this + let hierarchy_highlights = + filter_matcher.matches_hierarchy(hierarchy.iter().map(String::as_str)); - LeafOrNot::NotLeaf(data_result_node) => { - let mut children = data_result_node - .children - .iter() - .filter_map(|child_handle| { - let child_node = query_result.tree.lookup_node(*child_handle); - - debug_assert!( - child_node.is_some(), - "DataResultNode {data_result_node:?} has an invalid child" - ); - - child_node.and_then(|child_node| { - Self::from_data_result_and_filter( - ctx, - view_blueprint, - query_result, - &DataResultNodeOrPath::DataResultNode(child_node), - projection, - hierarchy, - hierarchy_ranges, - filter_matcher, - ) - }) - }) - .collect_vec(); + let is_this_a_match = if let Some(hierarchy_highlights) = hierarchy_highlights { + hierarchy_ranges.merge(hierarchy_highlights); + true + } else { + false + }; - // This is needed because `DataResultNode` stores children in a `SmallVec`, offering - // no guarantees about ordering. - children.sort_by(|a, b| a.entity_path.cmp(&b.entity_path)); + (is_this_a_match, vec![]) + } - let is_this_a_match = !children.is_empty(); + LeafOrNot::NotLeaf(data_result_node) => { + let mut children = data_result_node + .children + .iter() + .filter_map(|child_handle| { + let child_node = query_result.tree.lookup_node(*child_handle); + + debug_assert!( + child_node.is_some(), + "DataResultNode {data_result_node:?} has an invalid child" + ); + + child_node.and_then(|child_node| { + Self::from_data_result_and_filter( + ctx, + view_blueprint, + query_result, + &DataResultNodeOrPath::DataResultNode(child_node), + projection, + hierarchy, + hierarchy_ranges, + filter_matcher, + ) + }) + }) + .collect_vec(); - (is_this_a_match, children) - } - }; + // This is needed because `DataResultNode` stores children in a `SmallVec`, offering + // no guarantees about ordering. + children.sort_by(|a, b| a.entity_path.cmp(&b.entity_path)); - let highlight_sections = hierarchy_ranges.remove(hierarchy.len().saturating_sub(1)); + let is_this_a_match = !children.is_empty(); - // never highlight the placeholder - let highlight_sections = - if node_info.kind == DataResultKind::OriginProjectionPlaceholder { - SmallVec::new() - } else { - highlight_sections - .map(Iterator::collect) - .unwrap_or_default() - }; + (is_this_a_match, children) + } + }; + + let highlight_sections = hierarchy_ranges.remove(hierarchy.len().saturating_sub(1)); + + // never highlight the placeholder + let highlight_sections = + if node_info.kind == DataResultKind::OriginProjectionPlaceholder { + SmallVec::new() + } else { + highlight_sections + .map(Iterator::collect) + .unwrap_or_default() + }; - is_this_a_match.then(|| Self { - kind: node_info.kind, - entity_path, - visible, - view_id: view_blueprint.id, - label, - highlight_sections, - default_open: node_info.default_open, - children, - }) + is_this_a_match.then(|| Self { + kind: node_info.kind, + entity_path, + visible, + view_id: view_blueprint.id, + label, + highlight_sections, + default_open: node_info.default_open, + children, }) - .flatten(); + }); if should_pop { hierarchy_ranges.remove(hierarchy.len().saturating_sub(1)); diff --git a/crates/viewer/re_time_panel/src/streams_tree_data.rs b/crates/viewer/re_time_panel/src/streams_tree_data.rs index b9c9af96280a..81dc59d52584 100644 --- a/crates/viewer/re_time_panel/src/streams_tree_data.rs +++ b/crates/viewer/re_time_panel/src/streams_tree_data.rs @@ -133,7 +133,7 @@ impl EntityData { //TODO: rename this let hierarchy_highlights = - filter_matcher.matches_hierarchy_v2(hierarchy.iter().map(String::as_str)); + filter_matcher.matches_hierarchy(hierarchy.iter().map(String::as_str)); if let Some(hierarchy_highlights) = hierarchy_highlights { hierarchy_ranges.merge(hierarchy_highlights); diff --git a/crates/viewer/re_ui/examples/re_ui_example/main.rs b/crates/viewer/re_ui/examples/re_ui_example/main.rs index 4e573988cfeb..f8c42a365783 100644 --- a/crates/viewer/re_ui/examples/re_ui_example/main.rs +++ b/crates/viewer/re_ui/examples/re_ui_example/main.rs @@ -2,6 +2,7 @@ mod drag_and_drop; mod hierarchical_drag_and_drop; mod right_panel; +use re_ui::filter_widget::format_matching_text; use re_ui::notifications; use re_ui::{ filter_widget::FilterState, list_item, CommandPalette, ContextExt as _, DesignTokens, @@ -249,6 +250,7 @@ impl eframe::App for ExampleApp { }); }); + //TODO(ab): this demo could be slightly more interesting. ui.scope(|ui| { ui.spacing_mut().item_spacing.y = 0.0; @@ -264,7 +266,13 @@ impl eframe::App for ExampleApp { let filter = self.filter_state.filter(); for name in names { - if let Some(widget_text) = filter.matches_formatted(ui.ctx(), name) { + if let Some(mut hierarchy_ranges) = filter.matches_hierarchy([name]) { + let widget_text = format_matching_text( + ui.ctx(), + name, + hierarchy_ranges.remove(0).into_iter().flatten(), + None, + ); ui.list_item_flat_noninteractive(list_item::LabelContent::new(widget_text)); } } diff --git a/crates/viewer/re_ui/src/filter_widget.rs b/crates/viewer/re_ui/src/filter_widget.rs index 5ff7eb8833d1..b1ddc25fbd59 100644 --- a/crates/viewer/re_ui/src/filter_widget.rs +++ b/crates/viewer/re_ui/src/filter_widget.rs @@ -214,50 +214,8 @@ impl FilterMatcher { .is_some_and(|keywords| keywords.is_empty()) } - // /// Does the given text match the filter? - // pub fn matches(&self, text: &str) -> bool { - // match self.keywords.as_deref() { - // None => true, - // Some([]) => false, - // Some(keywords) => { - // let lowercase_input = text.to_lowercase(); - // keywords - // .iter() - // .all(|keyword| lowercase_input.contains(keyword)) - // } - // } - // } - - // /// Does the given hierarchy match the filter? - // /// - // /// To match, each of the keyword must be present in at least one of the parts of the hierarchy. - // pub fn matches_hierarchy<'a>(&self, hierarchy: impl IntoIterator) -> bool { - // match self.keywords.as_deref() { - // None => true, - // Some([]) => false, - // Some(keywords) => { - // let mut keyword_matches = vec![false; keywords.len()]; - // - // for part in hierarchy { - // let lowercase_input = part.to_lowercase(); - // for (i, keyword) in keywords.iter().enumerate() { - // if !keyword_matches[i] && lowercase_input.contains(keyword) { - // keyword_matches[i] = true; - // - // if keyword_matches.iter().all(|&b| b) { - // return true; - // } - // } - // } - // } - // - // false - // } - // } - // } - //TODO - pub fn matches_hierarchy_v2<'a>( + pub fn matches_hierarchy<'a>( &self, hierarchy: impl IntoIterator, ) -> Option { @@ -285,222 +243,8 @@ impl FilterMatcher { } } } - - // /// Match the input text and return match ranges if any. - // /// - // /// This function does apply the full matching semantics: - // /// - It returns `None` when there is no match. - // /// - It returns `Some` when the filter is inactive (and thus matches everything), or if there - // /// is an actual match. - // /// - // /// See [`format_matching_text`] for formatting text according to the returned ranges. - // pub fn find_matches(&self, text: &str) -> Option> + '_> { - // let keywords = match self.keywords.as_deref() { - // None => { - // return Some(Either::Left(std::iter::empty())); - // } - // Some([]) => { - // return None; - // } - // Some(keywords) => keywords, - // }; - // - // let lower_case_text = text.to_lowercase(); - // - // let mut all_ranges = vec![]; - // for keyword in keywords { - // if lower_case_text.contains(keyword) { - // all_ranges.extend(single_keyword_matches(&lower_case_text, keyword)); - // } else { - // return None; - // } - // } - // - // Some(Either::Right(MergeRanges::new(all_ranges))) - // } - - // /// Find match ranges for any of the keywords in the provided input. - // /// - // /// Note that this function does not perform any actual matching semantics. It just provides - // /// highlighting information for a hierarchy part that has already been tested for match using - // /// [`Self::matches_hierarchy`]. - // pub fn find_ranges_for_keywords(&self, text: &str) -> impl Iterator> + '_ { - // let keywords = match self.keywords.as_deref() { - // None | Some([]) => { - // return Either::Left(std::iter::empty()); - // } - // - // Some(keywords) => keywords, - // }; - // - // let lower_case_text = text.to_lowercase(); - // - // let all_ranges = keywords - // .iter() - // .flat_map(|keyword| single_keyword_matches(&lower_case_text, keyword)) - // .collect_vec(); - // - // Either::Right(MergeRanges::new(all_ranges)) - // } - - // /// Returns a formatted version of the text with the matching sections highlighted. - // /// - // /// Returns `None` when there is no match (so nothing should be displayed). - // /// Returns `Some` when the filter is inactive (and thus matches everything), or if there is an - // /// actual match. - // pub fn matches_formatted(&self, ctx: &egui::Context, text: &str) -> Option { - // self.find_matches(text) - // .map(|match_iter| format_matching_text(ctx, text, match_iter, None)) - // } } -// /// Full-text, case-insensitive matcher. -// pub struct FilterMatcher { -// /// Lowercase keywords. -// /// -// /// If this is `None`, the filter is inactive and the matcher will accept everything. If this -// /// is `Some([])`, the matcher will reject any input. -// keywords: Option>, -// } -// -// impl FilterMatcher { -// fn new(query: Option<&str>) -> Self { -// Self { -// keywords: query.map(|s| s.split_whitespace().map(str::to_lowercase).collect()), -// } -// } -// -// /// Is the filter currently active? -// pub fn is_active(&self) -> bool { -// self.keywords.is_some() -// } -// -// /// Is the filter set to match everything? -// /// -// /// Can be used by client code to short-circuit more expansive matching logic. -// pub fn matches_everything(&self) -> bool { -// self.keywords.is_none() -// } -// -// /// Is the filter set to match nothing? -// /// -// /// Can be used by client code to short-circuit more expansive matching logic. -// pub fn matches_nothing(&self) -> bool { -// self.keywords -// .as_ref() -// .is_some_and(|keywords| keywords.is_empty()) -// } -// -// /// Does the given text match the filter? -// pub fn matches(&self, text: &str) -> bool { -// match self.keywords.as_deref() { -// None => true, -// Some([]) => false, -// Some(keywords) => { -// let lowercase_input = text.to_lowercase(); -// keywords -// .iter() -// .all(|keyword| lowercase_input.contains(keyword)) -// } -// } -// } -// -// /// Does the given hierarchy match the filter? -// /// -// /// To match, each of the keyword must be present in at least one of the parts of the hierarchy. -// pub fn matches_hierarchy<'a>(&self, hierarchy: impl IntoIterator) -> bool { -// match self.keywords.as_deref() { -// None => true, -// Some([]) => false, -// Some(keywords) => { -// let mut keyword_matches = vec![false; keywords.len()]; -// -// for part in hierarchy { -// let lowercase_input = part.to_lowercase(); -// for (i, keyword) in keywords.iter().enumerate() { -// if !keyword_matches[i] && lowercase_input.contains(keyword) { -// keyword_matches[i] = true; -// -// if keyword_matches.iter().all(|&b| b) { -// return true; -// } -// } -// } -// } -// -// false -// } -// } -// } -// -// /// Match the input text and return match ranges if any. -// /// -// /// This function does apply the full matching semantics: -// /// - It returns `None` when there is no match. -// /// - It returns `Some` when the filter is inactive (and thus matches everything), or if there -// /// is an actual match. -// /// -// /// See [`format_matching_text`] for formatting text according to the returned ranges. -// pub fn find_matches(&self, text: &str) -> Option> + '_> { -// let keywords = match self.keywords.as_deref() { -// None => { -// return Some(Either::Left(std::iter::empty())); -// } -// Some([]) => { -// return None; -// } -// Some(keywords) => keywords, -// }; -// -// let lower_case_text = text.to_lowercase(); -// -// let mut all_ranges = vec![]; -// for keyword in keywords { -// if lower_case_text.contains(keyword) { -// all_ranges.extend(single_keyword_matches(&lower_case_text, keyword)); -// } else { -// return None; -// } -// } -// -// Some(Either::Right(MergeRanges::new(all_ranges))) -// } -// -// /// Find match ranges for any of the keywords in the provided input. -// /// -// /// Note that this function does not perform any actual matching semantics. It just provides -// /// highlighting information for a hierarchy part that has already been tested for match using -// /// [`Self::matches_hierarchy`]. -// pub fn find_ranges_for_keywords(&self, text: &str) -> impl Iterator> + '_ { -// let keywords = match self.keywords.as_deref() { -// None | Some([]) => { -// return Either::Left(std::iter::empty()); -// } -// -// Some(keywords) => keywords, -// }; -// -// let lower_case_text = text.to_lowercase(); -// -// let all_ranges = keywords -// .iter() -// .flat_map(|keyword| single_keyword_matches(&lower_case_text, keyword)) -// .collect_vec(); -// -// Either::Right(MergeRanges::new(all_ranges)) -// } -// -// /// Returns a formatted version of the text with the matching sections highlighted. -// /// -// /// Returns `None` when there is no match (so nothing should be displayed). -// /// Returns `Some` when the filter is inactive (and thus matches everything), or if there is an -// /// actual match. -// pub fn matches_formatted(&self, ctx: &egui::Context, text: &str) -> Option { -// self.find_matches(text) -// .map(|match_iter| format_matching_text(ctx, text, match_iter, None)) -// } -// } - #[derive(Debug, Clone, PartialEq)] struct Keyword { parts: Vec, @@ -594,9 +338,7 @@ impl HierarchyRanges { } pub fn remove(&mut self, part_index: usize) -> Option>> { - self.ranges - .remove(&part_index) - .map(|ranges| MergeRanges::new(ranges).into_iter()) + self.ranges.remove(&part_index).map(MergeRanges::new) } pub fn is_empty(&self) -> bool { @@ -824,72 +566,6 @@ mod test { ); } - // #[test] - // fn test_match_all() { - // let inactive_matcher = FilterMatcher::new(None); - // - // assert_eq!( - // inactive_matcher.find_matches("haystack").unwrap().count(), - // 0 - // ); - // } - // - // #[test] - // fn test_match_nothing() { - // let inactive_matcher = FilterMatcher::new(Some("")); - // - // assert!(inactive_matcher.find_matches("haystack").is_none()); - // } - // - // #[test] - // fn test_match() { - // let matcher = FilterMatcher::new(Some("str tru re")); - // - // // filter active but doesn't match - // assert!(matcher.find_matches("struct").is_none()); - // - // assert_eq!( - // matcher.find_matches("structure").unwrap().collect_vec(), - // [0..4, 7..9] - // ); - // } - - // #[test] - // fn test_match_hierarchy() { - // let matcher = FilterMatcher::new(Some("one TWo three")); - // - // // matches - // assert!(matcher.matches_hierarchy(["oNe", "two", "three"])); - // assert!(matcher.matches_hierarchy(["tHRee", "One", "two"])); - // assert!(matcher.matches_hierarchy(["three", "one", "nothing", "two"])); - // assert!(matcher.matches_hierarchy(["thrEEone", "nothing", "TWO"])); - // assert!(matcher.matches_hierarchy(["three", "twONE"])); - // - // // doesn't match - // assert!(!matcher.matches_hierarchy(["one", "two", "four"])); - // } - // - // #[test] - // fn test_find_ranges_for_keywords() { - // let matcher = FilterMatcher::new(Some("one two three")); - // - // assert_eq!(matcher.find_ranges_for_keywords("haystack").count(), 0); - // assert_eq!( - // matcher.find_ranges_for_keywords("xxONExx").collect_vec(), - // [2..5] - // ); - // assert_eq!( - // matcher.find_ranges_for_keywords("xxTWonExx").collect_vec(), - // [2..7] - // ); - // assert_eq!( - // matcher - // .find_ranges_for_keywords("xxTWonExthree") - // .collect_vec(), - // [2..7, 8..13] - // ); - // } - #[test] fn test_keyword() { assert_eq!( @@ -969,7 +645,7 @@ mod test { ranges .remove(i) .map(|iter| iter.collect_vec()) - .unwrap_or_else(Vec::new) + .unwrap_or_default() }) .collect(); @@ -1040,14 +716,14 @@ mod test { let hierarchy = hierarchy.to_vec(); matcher - .matches_hierarchy_v2(hierarchy.clone()) + .matches_hierarchy(hierarchy.clone()) .map(|mut ranges| { let result = (0..hierarchy.len()) .map(|i| { ranges .remove(i) .map(|iter| iter.collect_vec()) - .unwrap_or_else(Vec::new) + .unwrap_or_default() }) .collect(); From 5cc8e246d9f6c3f00ea65c17fee6dfc11aef41e5 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler Date: Wed, 5 Feb 2025 13:14:56 +0100 Subject: [PATCH 03/11] Renames and much, much cleanup --- Cargo.lock | 1 + crates/viewer/re_blueprint_tree/src/data.rs | 37 +++-- .../re_time_panel/src/streams_tree_data.rs | 117 +++++++------- crates/viewer/re_ui/Cargo.toml | 1 + .../re_ui/examples/re_ui_example/main.rs | 2 +- crates/viewer/re_ui/src/filter_widget.rs | 152 +++++++++++------- 6 files changed, 177 insertions(+), 133 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 050b91db4474..370c6bef872d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6713,6 +6713,7 @@ dependencies = [ "egui_tiles", "getrandom", "itertools 0.13.0", + "nohash-hasher", "once_cell", "parking_lot", "rand", diff --git a/crates/viewer/re_blueprint_tree/src/data.rs b/crates/viewer/re_blueprint_tree/src/data.rs index cd104b7e676b..950d5e61d099 100644 --- a/crates/viewer/re_blueprint_tree/src/data.rs +++ b/crates/viewer/re_blueprint_tree/src/data.rs @@ -17,7 +17,7 @@ use re_entity_db::InstancePath; use re_log_types::external::re_types_core::ViewClassIdentifier; use re_log_types::EntityPath; use re_types::blueprint::components::Visible; -use re_ui::filter_widget::{FilterMatcher, HierarchyRanges}; +use re_ui::filter_widget::{FilterMatcher, PathRanges}; use re_viewer_context::{ CollapseScope, ContainerId, Contents, ContentsName, DataQueryResult, DataResultNode, Item, ViewId, ViewerContext, VisitorControlFlow, @@ -216,7 +216,7 @@ impl ViewData { // let mut hierarchy = Vec::with_capacity(10); - let mut hierarchy_ranges = HierarchyRanges::default(); + let mut hierarchy_highlights = PathRanges::default(); let origin_tree = DataResultData::from_data_result_and_filter( ctx, view_blueprint, @@ -224,13 +224,13 @@ impl ViewData { &DataResultNodeOrPath::from_path_lookup(result_tree, &view_blueprint.space_origin), false, &mut hierarchy, - &mut hierarchy_ranges, + &mut hierarchy_highlights, filter_matcher, ); debug_assert!(hierarchy.is_empty()); hierarchy.clear(); - hierarchy_ranges.clear(); + hierarchy_highlights.clear(); // // Data results outside the view origin subtree (a.k.a projections) @@ -268,13 +268,13 @@ impl ViewData { &DataResultNodeOrPath::DataResultNode(node), true, &mut hierarchy, - &mut hierarchy_ranges, + &mut hierarchy_highlights, filter_matcher, ); debug_assert!(hierarchy.is_empty()); hierarchy.clear(); - hierarchy_ranges.clear(); + hierarchy_highlights.clear(); projection_tree }) @@ -371,7 +371,7 @@ impl DataResultData { data_result_or_path: &DataResultNodeOrPath<'_>, projection: bool, hierarchy: &mut Vec, - hierarchy_ranges: &mut HierarchyRanges, + hierarchy_highlights: &mut PathRanges, filter_matcher: &FilterMatcher, ) -> Option { re_tracing::profile_function!(); @@ -398,7 +398,7 @@ impl DataResultData { }; // - // Figure out what sort of node this is. + // Gather some info about the current node… // enum LeafOrNot<'a> { @@ -463,18 +463,21 @@ impl DataResultData { }; // - // Handle the node accordingly. + // …then handle the node accordingly. // let result = node_info.and_then(|node_info| { let (is_this_a_match, children) = match node_info.leaf_or_not { LeafOrNot::Leaf => { - //TODO: rename this - let hierarchy_highlights = - filter_matcher.matches_hierarchy(hierarchy.iter().map(String::as_str)); + // Key insight: we only ever need to match the hierarchy from the leaf nodes. + // Non-leaf nodes know they are a match if any child remains after walking their + // subtree. - let is_this_a_match = if let Some(hierarchy_highlights) = hierarchy_highlights { - hierarchy_ranges.merge(hierarchy_highlights); + let highlights = + filter_matcher.match_path(hierarchy.iter().map(String::as_str)); + + let is_this_a_match = if let Some(highlights) = highlights { + hierarchy_highlights.merge(highlights); true } else { false @@ -503,7 +506,7 @@ impl DataResultData { &DataResultNodeOrPath::DataResultNode(child_node), projection, hierarchy, - hierarchy_ranges, + hierarchy_highlights, filter_matcher, ) }) @@ -520,7 +523,7 @@ impl DataResultData { } }; - let highlight_sections = hierarchy_ranges.remove(hierarchy.len().saturating_sub(1)); + let highlight_sections = hierarchy_highlights.remove(hierarchy.len().saturating_sub(1)); // never highlight the placeholder let highlight_sections = @@ -545,7 +548,7 @@ impl DataResultData { }); if should_pop { - hierarchy_ranges.remove(hierarchy.len().saturating_sub(1)); + hierarchy_highlights.remove(hierarchy.len().saturating_sub(1)); hierarchy.pop(); } diff --git a/crates/viewer/re_time_panel/src/streams_tree_data.rs b/crates/viewer/re_time_panel/src/streams_tree_data.rs index 81dc59d52584..86491c9111f5 100644 --- a/crates/viewer/re_time_panel/src/streams_tree_data.rs +++ b/crates/viewer/re_time_panel/src/streams_tree_data.rs @@ -8,7 +8,7 @@ use re_data_ui::sorted_component_list_for_ui; use re_entity_db::{EntityTree, InstancePath}; use re_log_types::EntityPath; use re_types_core::ComponentName; -use re_ui::filter_widget::{FilterMatcher, HierarchyRanges}; +use re_ui::filter_widget::{FilterMatcher, PathRanges}; use re_viewer_context::{CollapseScope, Item, ViewerContext, VisitorControlFlow}; use crate::time_panel::TimePanelSource; @@ -33,12 +33,12 @@ impl StreamsTreeData { }; let mut hierarchy = Vec::default(); - let mut hierarchy_ranges = HierarchyRanges::default(); + let mut hierarchy_highlights = PathRanges::default(); let root_data = EntityData::from_entity_tree_and_filter( db.tree(), filter_matcher, &mut hierarchy, - &mut hierarchy_ranges, + &mut hierarchy_highlights, ); // We show "/" on top only for recording streams, because the `/` entity in blueprint @@ -104,7 +104,7 @@ impl EntityData { entity_tree: &EntityTree, filter_matcher: &FilterMatcher, hierarchy: &mut Vec, - hierarchy_ranges: &mut HierarchyRanges, + hierarchy_highlights: &mut PathRanges, ) -> Option { // Early out if filter_matcher.matches_nothing() { @@ -125,36 +125,35 @@ impl EntityData { }; // - // Recurse + // Gather some info about the current node… // - let result = if entity_tree.children.is_empty() { - // We're a child node, so we must decide if the hierarchy matches the filter. - - //TODO: rename this - let hierarchy_highlights = - filter_matcher.matches_hierarchy(hierarchy.iter().map(String::as_str)); - - if let Some(hierarchy_highlights) = hierarchy_highlights { - hierarchy_ranges.merge(hierarchy_highlights); + struct NodeInfo { + is_leaf: bool, + is_this_a_match: bool, + children: Vec, + default_open: bool, + } - let highlight_sections = hierarchy_ranges - .remove(hierarchy.len().saturating_sub(1)) - .map(Iterator::collect) - .unwrap_or_default(); + let node_info = if entity_tree.children.is_empty() { + // Key insight: we only ever need to match the hierarchy from the leaf nodes. + // Non-leaf nodes know they are a match if any child remains after walking their + // subtree. - // Leaf items are always collapsed by default, even when the filter is active. - let default_open = false; + let highlights = filter_matcher.match_path(hierarchy.iter().map(String::as_str)); - Some(Self { - entity_path: entity_tree.path.clone(), - label, - highlight_sections, - default_open, - children: vec![], - }) + let is_this_a_match = if let Some(highlights) = highlights { + hierarchy_highlights.merge(highlights); + true } else { - None + false + }; + + NodeInfo { + is_leaf: true, + is_this_a_match, + children: vec![], + default_open: false, } } else { let children = entity_tree @@ -165,41 +164,49 @@ impl EntityData { sub_tree, filter_matcher, hierarchy, - hierarchy_ranges, + hierarchy_highlights, ) }) .collect_vec(); - if children.is_empty() { - None - } else { - // Only top-level non-leaf entities are expanded by default, unless the filter is - // active. - let default_open = filter_matcher.is_active() || entity_tree.path.len() <= 1; - - let highlight_sections = hierarchy_ranges - .remove(hierarchy.len().saturating_sub(1)) - .map(Iterator::collect) - .unwrap_or_default(); - - Some(Self { - entity_path: entity_tree.path.clone(), - label: if children.is_empty() || entity_tree.path.is_root() { - label - } else { - // Indicate that we have children - label.push('/'); - label - }, - highlight_sections, - default_open, - children, - }) + let is_this_a_match = !children.is_empty(); + let default_open = filter_matcher.is_active() || entity_tree.path.len() <= 1; + + NodeInfo { + is_leaf: false, + is_this_a_match, + children, + default_open, } }; + // + // …then handle the node accordingly. + // + + let result = node_info.is_this_a_match.then(|| { + let highlight_sections = hierarchy_highlights + .remove(hierarchy.len().saturating_sub(1)) + .map(Iterator::collect) + .unwrap_or_default(); + + Self { + entity_path: entity_tree.path.clone(), + label: if node_info.is_leaf || entity_tree.path.is_root() { + label + } else { + // Indicate that we have children + label.push('/'); + label + }, + highlight_sections, + default_open: node_info.default_open, + children: node_info.children, + } + }); + if must_pop { - hierarchy_ranges.remove(hierarchy.len().saturating_sub(1)); + hierarchy_highlights.remove(hierarchy.len().saturating_sub(1)); hierarchy.pop(); } diff --git a/crates/viewer/re_ui/Cargo.toml b/crates/viewer/re_ui/Cargo.toml index f3dff6fd0f3c..d2e808192bbb 100644 --- a/crates/viewer/re_ui/Cargo.toml +++ b/crates/viewer/re_ui/Cargo.toml @@ -51,6 +51,7 @@ getrandom.workspace = true itertools.workspace = true once_cell.workspace = true parking_lot.workspace = true +nohash-hasher.workspace = true serde = { workspace = true, features = ["derive"] } serde_json.workspace = true smallvec.workspace = true diff --git a/crates/viewer/re_ui/examples/re_ui_example/main.rs b/crates/viewer/re_ui/examples/re_ui_example/main.rs index f8c42a365783..7fe4f32623d5 100644 --- a/crates/viewer/re_ui/examples/re_ui_example/main.rs +++ b/crates/viewer/re_ui/examples/re_ui_example/main.rs @@ -266,7 +266,7 @@ impl eframe::App for ExampleApp { let filter = self.filter_state.filter(); for name in names { - if let Some(mut hierarchy_ranges) = filter.matches_hierarchy([name]) { + if let Some(mut hierarchy_ranges) = filter.match_path([name]) { let widget_text = format_matching_text( ui.ctx(), name, diff --git a/crates/viewer/re_ui/src/filter_widget.rs b/crates/viewer/re_ui/src/filter_widget.rs index b1ddc25fbd59..d9adb8b5611e 100644 --- a/crates/viewer/re_ui/src/filter_widget.rs +++ b/crates/viewer/re_ui/src/filter_widget.rs @@ -2,8 +2,8 @@ use std::ops::Range; use egui::{Color32, NumExt as _, Widget as _}; use itertools::Itertools; - -use re_entity_db::external::re_chunk_store::external::re_chunk::external::nohash_hasher::IntMap; +use nohash_hasher::IntMap; +use smallvec::SmallVec; use crate::{list_item, UiExt as _}; @@ -178,6 +178,8 @@ impl FilterState { // -- /// Full-text, case-insensitive matcher. +/// +/// All keywords must match for the filter to match (`AND` semantics). pub struct FilterMatcher { /// Lowercase keywords. /// @@ -214,27 +216,28 @@ impl FilterMatcher { .is_some_and(|keywords| keywords.is_empty()) } - //TODO - pub fn matches_hierarchy<'a>( - &self, - hierarchy: impl IntoIterator, - ) -> Option { + /// Match a path and return the highlight ranges if any. + /// + /// `None`: the filter is active, but the path didn't match the keyword + /// `Some(ranges)`: either the filter is inactive (i.e., it matches everything), or it is active + /// and all keywords matched at least once. + pub fn match_path<'a>(&self, path: impl IntoIterator) -> Option { match self.keywords.as_deref() { - None => Some(HierarchyRanges::default()), + None => Some(PathRanges::default()), Some([]) => None, Some(keywords) => { - let hierarchy = hierarchy.into_iter().map(str::to_lowercase).collect_vec(); + let hierarchy = path.into_iter().map(str::to_lowercase).collect_vec(); let all_ranges = keywords .iter() - .map(|keyword| keyword.match_hierarchy(hierarchy.iter().map(String::as_str))) + .map(|keyword| keyword.match_path(hierarchy.iter().map(String::as_str))) .collect_vec(); // all keywords must match! if all_ranges.iter().any(|ranges| ranges.is_empty()) { None } else { - let mut result = HierarchyRanges::default(); + let mut result = PathRanges::default(); for ranges in all_ranges { result.merge(ranges); } @@ -245,12 +248,29 @@ impl FilterMatcher { } } +/// A single keyword from a query. +/// +/// ## Semantics +/// +/// If the keyword has a single part, it can match anywhere in any part of the tested path, unless +/// `match_from_first_part_start` and/or `match_to_last_part_end`, which have the same behavior as +/// regex's `^` and `$`. +/// +/// If the keyword has multiple parts, the tested path must have at least one instance of contiguous +/// parts which match the corresponding keyword parts. In that context, the keyword parts have the +/// following behavior: +/// - First keyword part: `^part$` if `match_from_first_part_start`, `part$` otherwise +/// - Last keyword part: `^part$` if `match_to_last_part_end`, `^part` otherwise +/// - Other keyword parts: `^part$` + #[derive(Debug, Clone, PartialEq)] struct Keyword { + /// The parts of a keyword. + /// + /// To match, a path needs to have some contiguous parts which each match the corresponding + /// keyword parts. parts: Vec, - match_from_first_part_start: bool, - match_to_last_part_end: bool, } @@ -284,11 +304,13 @@ impl Keyword { } } - //TODO: docstring / ranges are not sorted nor merged - fn match_hierarchy<'a>(&self, hierarchy: impl IntoIterator) -> HierarchyRanges { + /// Match the keyword against the provided path. + /// + /// An empty [`PathRanges`] means that the keyword didn't match the path. + fn match_path<'a>(&self, path: impl IntoIterator) -> PathRanges { let mut state_machines = vec![]; - for (part_index, part) in hierarchy.into_iter().enumerate() { + for (part_index, part) in path.into_iter().enumerate() { let lowercase_part = part.to_lowercase(); state_machines.push(MatchStateMachine::new(self)); @@ -301,25 +323,30 @@ impl Keyword { state_machines .into_iter() .filter_map(|state_machine| { - if state_machine.matches() { + if state_machine.did_match() { Some(state_machine.ranges) } else { None } }) - .fold(HierarchyRanges::default(), |mut acc, ranges| { + .fold(PathRanges::default(), |mut acc, ranges| { acc.merge(ranges); acc }) } } +/// Accumulates highlight ranges for the various parts of a path. +/// +/// The ranges are accumulated and stored unmerged and unordered, but are _always_ ordered and +/// merged when read, which only happens with [`Self::remove`]. #[derive(Debug, Default)] -pub struct HierarchyRanges { +pub struct PathRanges { ranges: IntMap>>, } -impl HierarchyRanges { +impl PathRanges { + /// Merge another [`Self`]. pub fn merge(&mut self, other: Self) { for (part_index, part_ranges) in other.ranges { self.ranges @@ -329,14 +356,17 @@ impl HierarchyRanges { } } + /// Add ranges to a given part index. pub fn extend(&mut self, part_index: usize, ranges: impl IntoIterator>) { self.ranges.entry(part_index).or_default().extend(ranges); } + /// Add a single range to a given part index. pub fn push(&mut self, part_index: usize, range: Range) { self.ranges.entry(part_index).or_default().push(range); } + /// Remove the ranges for the given part and (if any) return them sorted and merged. pub fn remove(&mut self, part_index: usize) -> Option>> { self.ranges.remove(&part_index).map(MergeRanges::new) } @@ -348,8 +378,26 @@ impl HierarchyRanges { pub fn clear(&mut self) { self.ranges.clear(); } + + /// Convert to a `Vec` based structure. + #[cfg(test)] + fn into_vec(mut self, length: usize) -> Vec>> { + let result = (0..length) + .map(|i| { + self.remove(i) + .map(|iter| iter.collect_vec()) + .unwrap_or_default() + }) + .collect(); + + debug_assert!(self.is_empty()); + + result + } } +// --- + #[derive(Debug)] enum MatchState { InProgress, @@ -357,12 +405,20 @@ enum MatchState { NoMatch, } +/// State machine used to test a given keyword against a given sequence of path parts. #[derive(Debug)] struct MatchStateMachine<'a> { + /// The keyword we're matching with. keyword: &'a Keyword, + + /// Which part of the keyword are we currently matching? current_keyword_part: usize, + + /// Our current state. state: MatchState, - ranges: HierarchyRanges, + + /// The highlight ranges we've gathered so far. + ranges: PathRanges, } impl<'a> MatchStateMachine<'a> { @@ -375,7 +431,7 @@ impl<'a> MatchStateMachine<'a> { } } - fn matches(&self) -> bool { + fn did_match(&self) -> bool { matches!(self.state, MatchState::Match) } @@ -391,7 +447,7 @@ impl<'a> MatchStateMachine<'a> { let must_match_from_start = has_part_before || self.keyword.match_from_first_part_start; let must_match_to_end = has_part_after || self.keyword.match_to_last_part_end; - let mut ranges = vec![]; + let mut ranges = SmallVec::<[Range; 2]>::new(); match (must_match_from_start, must_match_to_end) { (false, false) => { ranges.extend(single_keyword_matches(part, keyword_part)); @@ -429,6 +485,8 @@ impl<'a> MatchStateMachine<'a> { } } +// --- + /// Given a list of highlight sections defined by start/end indices and a string, produce a properly /// highlighted [`egui::WidgetText`]. pub fn format_matching_text( @@ -499,6 +557,8 @@ fn single_keyword_matches<'a>( }) } +// --- + /// Given a vector of ranges, iterate over the sorted, merged ranges. struct MergeRanges { ranges: Vec>, @@ -633,25 +693,11 @@ mod test { } #[test] - fn test_keyword_match_hierarchy() { - fn match_and_normalize(query: &str, hierarchy: &[&str]) -> Vec>> { + fn test_keyword_match_path() { + fn match_and_normalize(query: &str, path: &[&str]) -> Vec>> { let keyword = Keyword::new(query); - let hierarchy = hierarchy.to_vec(); - - let mut ranges = keyword.match_hierarchy(hierarchy.clone()); - - let result = (0..hierarchy.len()) - .map(|i| { - ranges - .remove(i) - .map(|iter| iter.collect_vec()) - .unwrap_or_default() - }) - .collect(); - - assert!(ranges.is_empty()); - - result + let path = path.to_vec(); + keyword.match_path(path.clone()).into_vec(path.len()) } assert_eq!(match_and_normalize("a", &["a"]), vec![vec![0..1]]); @@ -710,27 +756,13 @@ mod test { } #[test] - fn test_matches_hierarchy_v2() { - fn match_and_normalize(query: &str, hierarchy: &[&str]) -> Option>>> { + fn test_match_path() { + fn match_and_normalize(query: &str, path: &[&str]) -> Option>>> { let matcher = FilterMatcher::new(Some(query)); - let hierarchy = hierarchy.to_vec(); - + let path = path.to_vec(); matcher - .matches_hierarchy(hierarchy.clone()) - .map(|mut ranges| { - let result = (0..hierarchy.len()) - .map(|i| { - ranges - .remove(i) - .map(|iter| iter.collect_vec()) - .unwrap_or_default() - }) - .collect(); - - assert!(ranges.is_empty()); - - result - }) + .match_path(path.clone()) + .map(|ranges| ranges.into_vec(path.len())) } assert_eq!( From 94f339047868e230a285e848f2bb89c61348b9d7 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler Date: Wed, 5 Feb 2025 13:20:36 +0100 Subject: [PATCH 04/11] Moved insta snapshots next to kittest snapshot --- ...rs-ath_left.snap => various_filters-ath_left.snap} | 0 ..._filters-ath_t.snap => various_filters-ath_t.snap} | 0 ...us_filters-none.snap => various_filters-none.snap} | 0 ...us_filters-path.snap => various_filters-path.snap} | 0 ..._various_filters-t.snap => various_filters-t.snap} | 0 ...us_filters-void.snap => various_filters-void.snap} | 0 .../re_time_panel/tests/time_panel_filter_tests.rs | 11 ++++++++--- 7 files changed, 8 insertions(+), 3 deletions(-) rename crates/viewer/re_time_panel/tests/snapshots/{time_panel_filter_tests__various_filters-ath_left.snap => various_filters-ath_left.snap} (100%) rename crates/viewer/re_time_panel/tests/snapshots/{time_panel_filter_tests__various_filters-ath_t.snap => various_filters-ath_t.snap} (100%) rename crates/viewer/re_time_panel/tests/snapshots/{time_panel_filter_tests__various_filters-none.snap => various_filters-none.snap} (100%) rename crates/viewer/re_time_panel/tests/snapshots/{time_panel_filter_tests__various_filters-path.snap => various_filters-path.snap} (100%) rename crates/viewer/re_time_panel/tests/snapshots/{time_panel_filter_tests__various_filters-t.snap => various_filters-t.snap} (100%) rename crates/viewer/re_time_panel/tests/snapshots/{time_panel_filter_tests__various_filters-void.snap => various_filters-void.snap} (100%) diff --git a/crates/viewer/re_time_panel/tests/snapshots/time_panel_filter_tests__various_filters-ath_left.snap b/crates/viewer/re_time_panel/tests/snapshots/various_filters-ath_left.snap similarity index 100% rename from crates/viewer/re_time_panel/tests/snapshots/time_panel_filter_tests__various_filters-ath_left.snap rename to crates/viewer/re_time_panel/tests/snapshots/various_filters-ath_left.snap diff --git a/crates/viewer/re_time_panel/tests/snapshots/time_panel_filter_tests__various_filters-ath_t.snap b/crates/viewer/re_time_panel/tests/snapshots/various_filters-ath_t.snap similarity index 100% rename from crates/viewer/re_time_panel/tests/snapshots/time_panel_filter_tests__various_filters-ath_t.snap rename to crates/viewer/re_time_panel/tests/snapshots/various_filters-ath_t.snap diff --git a/crates/viewer/re_time_panel/tests/snapshots/time_panel_filter_tests__various_filters-none.snap b/crates/viewer/re_time_panel/tests/snapshots/various_filters-none.snap similarity index 100% rename from crates/viewer/re_time_panel/tests/snapshots/time_panel_filter_tests__various_filters-none.snap rename to crates/viewer/re_time_panel/tests/snapshots/various_filters-none.snap diff --git a/crates/viewer/re_time_panel/tests/snapshots/time_panel_filter_tests__various_filters-path.snap b/crates/viewer/re_time_panel/tests/snapshots/various_filters-path.snap similarity index 100% rename from crates/viewer/re_time_panel/tests/snapshots/time_panel_filter_tests__various_filters-path.snap rename to crates/viewer/re_time_panel/tests/snapshots/various_filters-path.snap diff --git a/crates/viewer/re_time_panel/tests/snapshots/time_panel_filter_tests__various_filters-t.snap b/crates/viewer/re_time_panel/tests/snapshots/various_filters-t.snap similarity index 100% rename from crates/viewer/re_time_panel/tests/snapshots/time_panel_filter_tests__various_filters-t.snap rename to crates/viewer/re_time_panel/tests/snapshots/various_filters-t.snap diff --git a/crates/viewer/re_time_panel/tests/snapshots/time_panel_filter_tests__various_filters-void.snap b/crates/viewer/re_time_panel/tests/snapshots/various_filters-void.snap similarity index 100% rename from crates/viewer/re_time_panel/tests/snapshots/time_panel_filter_tests__various_filters-void.snap rename to crates/viewer/re_time_panel/tests/snapshots/various_filters-void.snap diff --git a/crates/viewer/re_time_panel/tests/time_panel_filter_tests.rs b/crates/viewer/re_time_panel/tests/time_panel_filter_tests.rs index 276869a3ee4a..8934e2ee4e97 100644 --- a/crates/viewer/re_time_panel/tests/time_panel_filter_tests.rs +++ b/crates/viewer/re_time_panel/tests/time_panel_filter_tests.rs @@ -42,7 +42,7 @@ pub fn test_various_filter_ui_snapshot() { &format!( "various_filters-{}", filter_query - .map(|s| s.replace(' ', "_")) + .map(|s| s.replace(' ', "_").replace('/', "|")) .unwrap_or("none".to_owned()) ), ); @@ -71,11 +71,15 @@ pub fn test_various_filter_insta_snapshot() { let snapshot_name = format!( "various_filters-{}", filter_query - .map(|s| s.replace(' ', "_")) + .map(|s| s.replace(' ', "_").replace('/', "|")) .unwrap_or("none".to_owned()) ); - insta::assert_yaml_snapshot!(snapshot_name, streams_tree_data); + let mut settings = insta::Settings::clone_current(); + settings.set_prepend_module_to_snapshot(false); + settings.bind(|| { + insta::assert_yaml_snapshot!(snapshot_name, streams_tree_data); + }); } } @@ -85,6 +89,7 @@ fn prepare_test_context() -> TestContext { test_context.log_entity("/path/to/left".into(), add_point_to_chunk_builder); test_context.log_entity("/path/to/right".into(), add_point_to_chunk_builder); test_context.log_entity("/path/to/the/void".into(), add_point_to_chunk_builder); + //test_context.log_entity("/path/onto/their/coils".into(), add_point_to_chunk_builder); test_context.log_entity("/center/way".into(), add_point_to_chunk_builder); // also populate some "intermediate" entities so we see components From 945e3b413353a413c24776bc198136d6b3145db3 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler Date: Wed, 5 Feb 2025 13:23:46 +0100 Subject: [PATCH 05/11] Time panel test: more entities to make the test more interesting --- .../tests/snapshots/various_filters-ath_t.png | 4 +-- .../snapshots/various_filters-ath_t.snap | 28 +++++++++++++++++++ .../tests/snapshots/various_filters-none.png | 4 +-- .../tests/snapshots/various_filters-none.snap | 24 ++++++++++++++++ .../tests/snapshots/various_filters-path.png | 4 +-- .../tests/snapshots/various_filters-path.snap | 24 ++++++++++++++++ .../tests/snapshots/various_filters-t.png | 4 +-- .../tests/snapshots/various_filters-t.snap | 28 +++++++++++++++++++ .../tests/time_panel_filter_tests.rs | 2 +- 9 files changed, 113 insertions(+), 9 deletions(-) diff --git a/crates/viewer/re_time_panel/tests/snapshots/various_filters-ath_t.png b/crates/viewer/re_time_panel/tests/snapshots/various_filters-ath_t.png index 48690902d5fd..af83aab638bc 100644 --- a/crates/viewer/re_time_panel/tests/snapshots/various_filters-ath_t.png +++ b/crates/viewer/re_time_panel/tests/snapshots/various_filters-ath_t.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:58ba3576a314b3ac10e512ca5ee689cb73716824f666ac45a5cc70b31d00d751 -size 35316 +oid sha256:70c691304f9ac93111c2d8bc738b4bc29da7b276c80b0038e8ed65e870e75001 +size 39459 diff --git a/crates/viewer/re_time_panel/tests/snapshots/various_filters-ath_t.snap b/crates/viewer/re_time_panel/tests/snapshots/various_filters-ath_t.snap index e4b9a2bd79ce..17d360706469 100644 --- a/crates/viewer/re_time_panel/tests/snapshots/various_filters-ath_t.snap +++ b/crates/viewer/re_time_panel/tests/snapshots/various_filters-ath_t.snap @@ -16,6 +16,34 @@ children: end: 4 default_open: true children: + - entity_path: + - path + - onto + label: onto/ + highlight_sections: + - start: 2 + end: 3 + default_open: true + children: + - entity_path: + - path + - onto + - their + label: their/ + highlight_sections: + - start: 0 + end: 1 + default_open: true + children: + - entity_path: + - path + - onto + - their + - coils + label: coils + highlight_sections: [] + default_open: false + children: [] - entity_path: - path - to diff --git a/crates/viewer/re_time_panel/tests/snapshots/various_filters-none.png b/crates/viewer/re_time_panel/tests/snapshots/various_filters-none.png index fd83ed53f6b9..cd4d24d923cd 100644 --- a/crates/viewer/re_time_panel/tests/snapshots/various_filters-none.png +++ b/crates/viewer/re_time_panel/tests/snapshots/various_filters-none.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3b0ad1059d6222110d4ce32848348b72c2cc769a32cfc18bc4602b11871f87e3 -size 29024 +oid sha256:11b5407966a18ad2453677e96c994ce5e6c9022a7ef4b7f85b7416e0a27df23c +size 30442 diff --git a/crates/viewer/re_time_panel/tests/snapshots/various_filters-none.snap b/crates/viewer/re_time_panel/tests/snapshots/various_filters-none.snap index 90307d74c33a..1439321440d0 100644 --- a/crates/viewer/re_time_panel/tests/snapshots/various_filters-none.snap +++ b/crates/viewer/re_time_panel/tests/snapshots/various_filters-none.snap @@ -27,6 +27,30 @@ children: highlight_sections: [] default_open: true children: + - entity_path: + - path + - onto + label: onto/ + highlight_sections: [] + default_open: false + children: + - entity_path: + - path + - onto + - their + label: their/ + highlight_sections: [] + default_open: false + children: + - entity_path: + - path + - onto + - their + - coils + label: coils + highlight_sections: [] + default_open: false + children: [] - entity_path: - path - to diff --git a/crates/viewer/re_time_panel/tests/snapshots/various_filters-path.png b/crates/viewer/re_time_panel/tests/snapshots/various_filters-path.png index 6e3d4eb87251..f5a09d1dc4f8 100644 --- a/crates/viewer/re_time_panel/tests/snapshots/various_filters-path.png +++ b/crates/viewer/re_time_panel/tests/snapshots/various_filters-path.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a7ce31adfd6f52199195cab0736dc75c22475f9a0aa52dbe292a8c0259fd2a0c -size 35418 +oid sha256:c7c9b6c53a9ecd2eb7b35c45918777377522a5bc46c4bd235c190b728b8065a2 +size 39588 diff --git a/crates/viewer/re_time_panel/tests/snapshots/various_filters-path.snap b/crates/viewer/re_time_panel/tests/snapshots/various_filters-path.snap index 1eb8edba3eec..1a5760d0cb76 100644 --- a/crates/viewer/re_time_panel/tests/snapshots/various_filters-path.snap +++ b/crates/viewer/re_time_panel/tests/snapshots/various_filters-path.snap @@ -16,6 +16,30 @@ children: end: 4 default_open: true children: + - entity_path: + - path + - onto + label: onto/ + highlight_sections: [] + default_open: true + children: + - entity_path: + - path + - onto + - their + label: their/ + highlight_sections: [] + default_open: true + children: + - entity_path: + - path + - onto + - their + - coils + label: coils + highlight_sections: [] + default_open: false + children: [] - entity_path: - path - to diff --git a/crates/viewer/re_time_panel/tests/snapshots/various_filters-t.png b/crates/viewer/re_time_panel/tests/snapshots/various_filters-t.png index 23218510aa8c..2b36b0c4cab1 100644 --- a/crates/viewer/re_time_panel/tests/snapshots/various_filters-t.png +++ b/crates/viewer/re_time_panel/tests/snapshots/various_filters-t.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f3cde8683341cc19e592928a620e3588e5b188c0632fe8a1123a9496646aaaf5 -size 37954 +oid sha256:0f57e48897c36a5f2221d34f7f8121ea5698e728959fc0410c4e3200082fd706 +size 42097 diff --git a/crates/viewer/re_time_panel/tests/snapshots/various_filters-t.snap b/crates/viewer/re_time_panel/tests/snapshots/various_filters-t.snap index 881fe7010f5e..a65051295bea 100644 --- a/crates/viewer/re_time_panel/tests/snapshots/various_filters-t.snap +++ b/crates/viewer/re_time_panel/tests/snapshots/various_filters-t.snap @@ -31,6 +31,34 @@ children: end: 3 default_open: true children: + - entity_path: + - path + - onto + label: onto/ + highlight_sections: + - start: 2 + end: 3 + default_open: true + children: + - entity_path: + - path + - onto + - their + label: their/ + highlight_sections: + - start: 0 + end: 1 + default_open: true + children: + - entity_path: + - path + - onto + - their + - coils + label: coils + highlight_sections: [] + default_open: false + children: [] - entity_path: - path - to diff --git a/crates/viewer/re_time_panel/tests/time_panel_filter_tests.rs b/crates/viewer/re_time_panel/tests/time_panel_filter_tests.rs index 8934e2ee4e97..3b735f9b6ba6 100644 --- a/crates/viewer/re_time_panel/tests/time_panel_filter_tests.rs +++ b/crates/viewer/re_time_panel/tests/time_panel_filter_tests.rs @@ -89,7 +89,7 @@ fn prepare_test_context() -> TestContext { test_context.log_entity("/path/to/left".into(), add_point_to_chunk_builder); test_context.log_entity("/path/to/right".into(), add_point_to_chunk_builder); test_context.log_entity("/path/to/the/void".into(), add_point_to_chunk_builder); - //test_context.log_entity("/path/onto/their/coils".into(), add_point_to_chunk_builder); + test_context.log_entity("/path/onto/their/coils".into(), add_point_to_chunk_builder); test_context.log_entity("/center/way".into(), add_point_to_chunk_builder); // also populate some "intermediate" entities so we see components From 9056e19c3ff7f8fa2da6a11970718183a43f5b89 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler Date: Wed, 5 Feb 2025 13:59:13 +0100 Subject: [PATCH 06/11] Time panel test: more test cases + rename snapshot again --- .../various_filters-_path_to,_rig.png | 3 + .../various_filters-_path_to,_rig.snap | 37 ++++++++++ .../snapshots/various_filters-_to_the.png | 3 + .../snapshots/various_filters-_to_the.snap | 44 ++++++++++++ .../snapshots/various_filters-_to_the_.png | 3 + .../snapshots/various_filters-_to_the_.snap | 44 ++++++++++++ ..._left.png => various_filters-ath,left.png} | 0 ...eft.snap => various_filters-ath,left.snap} | 0 ...rs-ath_t.png => various_filters-ath,t.png} | 0 ...-ath_t.snap => various_filters-ath,t.snap} | 0 .../snapshots/various_filters-to_the,oid.png | 3 + .../snapshots/various_filters-to_the,oid.snap | 46 ++++++++++++ .../snapshots/various_filters-to_the.png | 3 + .../snapshots/various_filters-to_the.snap | 72 +++++++++++++++++++ .../snapshots/various_filters-to_the_.png | 3 + .../snapshots/various_filters-to_the_.snap | 44 ++++++++++++ .../tests/time_panel_filter_tests.rs | 10 ++- 17 files changed, 313 insertions(+), 2 deletions(-) create mode 100644 crates/viewer/re_time_panel/tests/snapshots/various_filters-_path_to,_rig.png create mode 100644 crates/viewer/re_time_panel/tests/snapshots/various_filters-_path_to,_rig.snap create mode 100644 crates/viewer/re_time_panel/tests/snapshots/various_filters-_to_the.png create mode 100644 crates/viewer/re_time_panel/tests/snapshots/various_filters-_to_the.snap create mode 100644 crates/viewer/re_time_panel/tests/snapshots/various_filters-_to_the_.png create mode 100644 crates/viewer/re_time_panel/tests/snapshots/various_filters-_to_the_.snap rename crates/viewer/re_time_panel/tests/snapshots/{various_filters-ath_left.png => various_filters-ath,left.png} (100%) rename crates/viewer/re_time_panel/tests/snapshots/{various_filters-ath_left.snap => various_filters-ath,left.snap} (100%) rename crates/viewer/re_time_panel/tests/snapshots/{various_filters-ath_t.png => various_filters-ath,t.png} (100%) rename crates/viewer/re_time_panel/tests/snapshots/{various_filters-ath_t.snap => various_filters-ath,t.snap} (100%) create mode 100644 crates/viewer/re_time_panel/tests/snapshots/various_filters-to_the,oid.png create mode 100644 crates/viewer/re_time_panel/tests/snapshots/various_filters-to_the,oid.snap create mode 100644 crates/viewer/re_time_panel/tests/snapshots/various_filters-to_the.png create mode 100644 crates/viewer/re_time_panel/tests/snapshots/various_filters-to_the.snap create mode 100644 crates/viewer/re_time_panel/tests/snapshots/various_filters-to_the_.png create mode 100644 crates/viewer/re_time_panel/tests/snapshots/various_filters-to_the_.snap diff --git a/crates/viewer/re_time_panel/tests/snapshots/various_filters-_path_to,_rig.png b/crates/viewer/re_time_panel/tests/snapshots/various_filters-_path_to,_rig.png new file mode 100644 index 000000000000..a70cb8816dfc --- /dev/null +++ b/crates/viewer/re_time_panel/tests/snapshots/various_filters-_path_to,_rig.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ec6c1d48866b9f5883b980209caca6647235b419646d7e74cbd1dac0c228469e +size 33127 diff --git a/crates/viewer/re_time_panel/tests/snapshots/various_filters-_path_to,_rig.snap b/crates/viewer/re_time_panel/tests/snapshots/various_filters-_path_to,_rig.snap new file mode 100644 index 000000000000..30a9f2ac658d --- /dev/null +++ b/crates/viewer/re_time_panel/tests/snapshots/various_filters-_path_to,_rig.snap @@ -0,0 +1,37 @@ +--- +source: crates/viewer/re_time_panel/tests/time_panel_filter_tests.rs +expression: streams_tree_data +--- +children: + - entity_path: [] + label: / + highlight_sections: [] + default_open: true + children: + - entity_path: + - path + label: path/ + highlight_sections: + - start: 0 + end: 4 + default_open: true + children: + - entity_path: + - path + - to + label: to/ + highlight_sections: + - start: 0 + end: 2 + default_open: true + children: + - entity_path: + - path + - to + - right + label: right + highlight_sections: + - start: 0 + end: 3 + default_open: false + children: [] diff --git a/crates/viewer/re_time_panel/tests/snapshots/various_filters-_to_the.png b/crates/viewer/re_time_panel/tests/snapshots/various_filters-_to_the.png new file mode 100644 index 000000000000..01f2a0f11563 --- /dev/null +++ b/crates/viewer/re_time_panel/tests/snapshots/various_filters-_to_the.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3c5692c81934debf29f7ea65744e0494eb90e711358c40665a4a1b5b781d797b +size 33454 diff --git a/crates/viewer/re_time_panel/tests/snapshots/various_filters-_to_the.snap b/crates/viewer/re_time_panel/tests/snapshots/various_filters-_to_the.snap new file mode 100644 index 000000000000..75fe39c8b86f --- /dev/null +++ b/crates/viewer/re_time_panel/tests/snapshots/various_filters-_to_the.snap @@ -0,0 +1,44 @@ +--- +source: crates/viewer/re_time_panel/tests/time_panel_filter_tests.rs +expression: streams_tree_data +--- +children: + - entity_path: [] + label: / + highlight_sections: [] + default_open: true + children: + - entity_path: + - path + label: path/ + highlight_sections: [] + default_open: true + children: + - entity_path: + - path + - to + label: to/ + highlight_sections: + - start: 0 + end: 2 + default_open: true + children: + - entity_path: + - path + - to + - the + label: the/ + highlight_sections: + - start: 0 + end: 3 + default_open: true + children: + - entity_path: + - path + - to + - the + - void + label: void + highlight_sections: [] + default_open: false + children: [] diff --git a/crates/viewer/re_time_panel/tests/snapshots/various_filters-_to_the_.png b/crates/viewer/re_time_panel/tests/snapshots/various_filters-_to_the_.png new file mode 100644 index 000000000000..1919487cb9dd --- /dev/null +++ b/crates/viewer/re_time_panel/tests/snapshots/various_filters-_to_the_.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e6ed3c7ce2c624cf2d89bb750839df6366012a6f4237ae272be75049aba82a14 +size 33632 diff --git a/crates/viewer/re_time_panel/tests/snapshots/various_filters-_to_the_.snap b/crates/viewer/re_time_panel/tests/snapshots/various_filters-_to_the_.snap new file mode 100644 index 000000000000..75fe39c8b86f --- /dev/null +++ b/crates/viewer/re_time_panel/tests/snapshots/various_filters-_to_the_.snap @@ -0,0 +1,44 @@ +--- +source: crates/viewer/re_time_panel/tests/time_panel_filter_tests.rs +expression: streams_tree_data +--- +children: + - entity_path: [] + label: / + highlight_sections: [] + default_open: true + children: + - entity_path: + - path + label: path/ + highlight_sections: [] + default_open: true + children: + - entity_path: + - path + - to + label: to/ + highlight_sections: + - start: 0 + end: 2 + default_open: true + children: + - entity_path: + - path + - to + - the + label: the/ + highlight_sections: + - start: 0 + end: 3 + default_open: true + children: + - entity_path: + - path + - to + - the + - void + label: void + highlight_sections: [] + default_open: false + children: [] diff --git a/crates/viewer/re_time_panel/tests/snapshots/various_filters-ath_left.png b/crates/viewer/re_time_panel/tests/snapshots/various_filters-ath,left.png similarity index 100% rename from crates/viewer/re_time_panel/tests/snapshots/various_filters-ath_left.png rename to crates/viewer/re_time_panel/tests/snapshots/various_filters-ath,left.png diff --git a/crates/viewer/re_time_panel/tests/snapshots/various_filters-ath_left.snap b/crates/viewer/re_time_panel/tests/snapshots/various_filters-ath,left.snap similarity index 100% rename from crates/viewer/re_time_panel/tests/snapshots/various_filters-ath_left.snap rename to crates/viewer/re_time_panel/tests/snapshots/various_filters-ath,left.snap diff --git a/crates/viewer/re_time_panel/tests/snapshots/various_filters-ath_t.png b/crates/viewer/re_time_panel/tests/snapshots/various_filters-ath,t.png similarity index 100% rename from crates/viewer/re_time_panel/tests/snapshots/various_filters-ath_t.png rename to crates/viewer/re_time_panel/tests/snapshots/various_filters-ath,t.png diff --git a/crates/viewer/re_time_panel/tests/snapshots/various_filters-ath_t.snap b/crates/viewer/re_time_panel/tests/snapshots/various_filters-ath,t.snap similarity index 100% rename from crates/viewer/re_time_panel/tests/snapshots/various_filters-ath_t.snap rename to crates/viewer/re_time_panel/tests/snapshots/various_filters-ath,t.snap diff --git a/crates/viewer/re_time_panel/tests/snapshots/various_filters-to_the,oid.png b/crates/viewer/re_time_panel/tests/snapshots/various_filters-to_the,oid.png new file mode 100644 index 000000000000..fe63b41ba1b7 --- /dev/null +++ b/crates/viewer/re_time_panel/tests/snapshots/various_filters-to_the,oid.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:979ae30732b5d0b0448fa8ff451e9f3ecc3c8c0a6259ab21c379f442f9484d59 +size 33820 diff --git a/crates/viewer/re_time_panel/tests/snapshots/various_filters-to_the,oid.snap b/crates/viewer/re_time_panel/tests/snapshots/various_filters-to_the,oid.snap new file mode 100644 index 000000000000..b1dbae3aa312 --- /dev/null +++ b/crates/viewer/re_time_panel/tests/snapshots/various_filters-to_the,oid.snap @@ -0,0 +1,46 @@ +--- +source: crates/viewer/re_time_panel/tests/time_panel_filter_tests.rs +expression: streams_tree_data +--- +children: + - entity_path: [] + label: / + highlight_sections: [] + default_open: true + children: + - entity_path: + - path + label: path/ + highlight_sections: [] + default_open: true + children: + - entity_path: + - path + - to + label: to/ + highlight_sections: + - start: 0 + end: 2 + default_open: true + children: + - entity_path: + - path + - to + - the + label: the/ + highlight_sections: + - start: 0 + end: 3 + default_open: true + children: + - entity_path: + - path + - to + - the + - void + label: void + highlight_sections: + - start: 1 + end: 4 + default_open: false + children: [] diff --git a/crates/viewer/re_time_panel/tests/snapshots/various_filters-to_the.png b/crates/viewer/re_time_panel/tests/snapshots/various_filters-to_the.png new file mode 100644 index 000000000000..4dabab9fc720 --- /dev/null +++ b/crates/viewer/re_time_panel/tests/snapshots/various_filters-to_the.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0b57212c9dd5327c2630f68515d758ca3045cbd508a01e8a84df1f7cf5d059eb +size 37416 diff --git a/crates/viewer/re_time_panel/tests/snapshots/various_filters-to_the.snap b/crates/viewer/re_time_panel/tests/snapshots/various_filters-to_the.snap new file mode 100644 index 000000000000..1f56863a016a --- /dev/null +++ b/crates/viewer/re_time_panel/tests/snapshots/various_filters-to_the.snap @@ -0,0 +1,72 @@ +--- +source: crates/viewer/re_time_panel/tests/time_panel_filter_tests.rs +expression: streams_tree_data +--- +children: + - entity_path: [] + label: / + highlight_sections: [] + default_open: true + children: + - entity_path: + - path + label: path/ + highlight_sections: [] + default_open: true + children: + - entity_path: + - path + - onto + label: onto/ + highlight_sections: + - start: 2 + end: 4 + default_open: true + children: + - entity_path: + - path + - onto + - their + label: their/ + highlight_sections: + - start: 0 + end: 3 + default_open: true + children: + - entity_path: + - path + - onto + - their + - coils + label: coils + highlight_sections: [] + default_open: false + children: [] + - entity_path: + - path + - to + label: to/ + highlight_sections: + - start: 0 + end: 2 + default_open: true + children: + - entity_path: + - path + - to + - the + label: the/ + highlight_sections: + - start: 0 + end: 3 + default_open: true + children: + - entity_path: + - path + - to + - the + - void + label: void + highlight_sections: [] + default_open: false + children: [] diff --git a/crates/viewer/re_time_panel/tests/snapshots/various_filters-to_the_.png b/crates/viewer/re_time_panel/tests/snapshots/various_filters-to_the_.png new file mode 100644 index 000000000000..3e7a24483adf --- /dev/null +++ b/crates/viewer/re_time_panel/tests/snapshots/various_filters-to_the_.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:086b777e8b55641eed80d61ea4a638950283f7f75cf1e4f8fc8ebc3276766777 +size 33479 diff --git a/crates/viewer/re_time_panel/tests/snapshots/various_filters-to_the_.snap b/crates/viewer/re_time_panel/tests/snapshots/various_filters-to_the_.snap new file mode 100644 index 000000000000..75fe39c8b86f --- /dev/null +++ b/crates/viewer/re_time_panel/tests/snapshots/various_filters-to_the_.snap @@ -0,0 +1,44 @@ +--- +source: crates/viewer/re_time_panel/tests/time_panel_filter_tests.rs +expression: streams_tree_data +--- +children: + - entity_path: [] + label: / + highlight_sections: [] + default_open: true + children: + - entity_path: + - path + label: path/ + highlight_sections: [] + default_open: true + children: + - entity_path: + - path + - to + label: to/ + highlight_sections: + - start: 0 + end: 2 + default_open: true + children: + - entity_path: + - path + - to + - the + label: the/ + highlight_sections: + - start: 0 + end: 3 + default_open: true + children: + - entity_path: + - path + - to + - the + - void + label: void + highlight_sections: [] + default_open: false + children: [] diff --git a/crates/viewer/re_time_panel/tests/time_panel_filter_tests.rs b/crates/viewer/re_time_panel/tests/time_panel_filter_tests.rs index 3b735f9b6ba6..f901d89bae50 100644 --- a/crates/viewer/re_time_panel/tests/time_panel_filter_tests.rs +++ b/crates/viewer/re_time_panel/tests/time_panel_filter_tests.rs @@ -20,6 +20,12 @@ fn filter_queries() -> impl Iterator> { Some("path"), Some("ath t"), Some("ath left"), + Some("to/the"), + Some("/to/the"), + Some("to/the/"), + Some("/to/the/"), + Some("to/the oid"), + Some("/path/to /rig"), ] .into_iter() } @@ -42,7 +48,7 @@ pub fn test_various_filter_ui_snapshot() { &format!( "various_filters-{}", filter_query - .map(|s| s.replace(' ', "_").replace('/', "|")) + .map(|s| s.replace(' ', ",").replace('/', "_")) .unwrap_or("none".to_owned()) ), ); @@ -71,7 +77,7 @@ pub fn test_various_filter_insta_snapshot() { let snapshot_name = format!( "various_filters-{}", filter_query - .map(|s| s.replace(' ', "_").replace('/', "|")) + .map(|s| s.replace(' ', ",").replace('/', "_")) .unwrap_or("none".to_owned()) ); From ec874c3d7527f53e06d8c536b3e4e00494852061 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler Date: Wed, 5 Feb 2025 14:05:18 +0100 Subject: [PATCH 07/11] Blueprint tree test: rename existing tests --- .../{query-ath_left => query-ath,left}/empty.png | 0 .../{query-ath_left => query-ath,left}/empty.snap | 0 .../{query-ath_left => query-ath,left}/multiple_proj.png | 0 .../{query-ath_left => query-ath,left}/multiple_proj.snap | 0 .../{query-ath_left => query-ath,left}/non_root_origin.png | 0 .../{query-ath_left => query-ath,left}/non_root_origin.snap | 0 .../proj_with_placeholder.png | 0 .../proj_with_placeholder.snap | 0 .../{query-ath_left => query-ath,left}/root_origin.png | 0 .../{query-ath_left => query-ath,left}/root_origin.snap | 0 .../{query-ath_left => query-ath,left}/single_proj.png | 0 .../{query-ath_left => query-ath,left}/single_proj.snap | 0 .../{query-ath_left => query-ath,left}/unknown_origin.png | 0 .../{query-ath_left => query-ath,left}/unknown_origin.snap | 0 .../{query-ath_t => query-ath,t}/empty.png | 0 .../{query-ath_t => query-ath,t}/empty.snap | 0 .../{query-ath_t => query-ath,t}/multiple_proj.png | 0 .../{query-ath_t => query-ath,t}/multiple_proj.snap | 0 .../{query-ath_t => query-ath,t}/non_root_origin.png | 0 .../{query-ath_t => query-ath,t}/non_root_origin.snap | 0 .../{query-ath_t => query-ath,t}/proj_with_placeholder.png | 0 .../{query-ath_t => query-ath,t}/proj_with_placeholder.snap | 0 .../{query-ath_t => query-ath,t}/root_origin.png | 0 .../{query-ath_t => query-ath,t}/root_origin.snap | 0 .../{query-ath_t => query-ath,t}/single_proj.png | 0 .../{query-ath_t => query-ath,t}/single_proj.snap | 0 .../{query-ath_t => query-ath,t}/unknown_origin.png | 0 .../{query-ath_t => query-ath,t}/unknown_origin.snap | 0 crates/viewer/re_blueprint_tree/tests/view_structure_test.rs | 4 ++-- 29 files changed, 2 insertions(+), 2 deletions(-) rename crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/{query-ath_left => query-ath,left}/empty.png (100%) rename crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/{query-ath_left => query-ath,left}/empty.snap (100%) rename crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/{query-ath_left => query-ath,left}/multiple_proj.png (100%) rename crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/{query-ath_left => query-ath,left}/multiple_proj.snap (100%) rename crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/{query-ath_left => query-ath,left}/non_root_origin.png (100%) rename crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/{query-ath_left => query-ath,left}/non_root_origin.snap (100%) rename crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/{query-ath_left => query-ath,left}/proj_with_placeholder.png (100%) rename crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/{query-ath_left => query-ath,left}/proj_with_placeholder.snap (100%) rename crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/{query-ath_left => query-ath,left}/root_origin.png (100%) rename crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/{query-ath_left => query-ath,left}/root_origin.snap (100%) rename crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/{query-ath_left => query-ath,left}/single_proj.png (100%) rename crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/{query-ath_left => query-ath,left}/single_proj.snap (100%) rename crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/{query-ath_left => query-ath,left}/unknown_origin.png (100%) rename crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/{query-ath_left => query-ath,left}/unknown_origin.snap (100%) rename crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/{query-ath_t => query-ath,t}/empty.png (100%) rename crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/{query-ath_t => query-ath,t}/empty.snap (100%) rename crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/{query-ath_t => query-ath,t}/multiple_proj.png (100%) rename crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/{query-ath_t => query-ath,t}/multiple_proj.snap (100%) rename crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/{query-ath_t => query-ath,t}/non_root_origin.png (100%) rename crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/{query-ath_t => query-ath,t}/non_root_origin.snap (100%) rename crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/{query-ath_t => query-ath,t}/proj_with_placeholder.png (100%) rename crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/{query-ath_t => query-ath,t}/proj_with_placeholder.snap (100%) rename crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/{query-ath_t => query-ath,t}/root_origin.png (100%) rename crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/{query-ath_t => query-ath,t}/root_origin.snap (100%) rename crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/{query-ath_t => query-ath,t}/single_proj.png (100%) rename crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/{query-ath_t => query-ath,t}/single_proj.snap (100%) rename crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/{query-ath_t => query-ath,t}/unknown_origin.png (100%) rename crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/{query-ath_t => query-ath,t}/unknown_origin.snap (100%) diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_left/empty.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,left/empty.png similarity index 100% rename from crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_left/empty.png rename to crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,left/empty.png diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_left/empty.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,left/empty.snap similarity index 100% rename from crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_left/empty.snap rename to crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,left/empty.snap diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_left/multiple_proj.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,left/multiple_proj.png similarity index 100% rename from crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_left/multiple_proj.png rename to crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,left/multiple_proj.png diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_left/multiple_proj.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,left/multiple_proj.snap similarity index 100% rename from crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_left/multiple_proj.snap rename to crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,left/multiple_proj.snap diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_left/non_root_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,left/non_root_origin.png similarity index 100% rename from crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_left/non_root_origin.png rename to crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,left/non_root_origin.png diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_left/non_root_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,left/non_root_origin.snap similarity index 100% rename from crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_left/non_root_origin.snap rename to crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,left/non_root_origin.snap diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_left/proj_with_placeholder.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,left/proj_with_placeholder.png similarity index 100% rename from crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_left/proj_with_placeholder.png rename to crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,left/proj_with_placeholder.png diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_left/proj_with_placeholder.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,left/proj_with_placeholder.snap similarity index 100% rename from crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_left/proj_with_placeholder.snap rename to crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,left/proj_with_placeholder.snap diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_left/root_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,left/root_origin.png similarity index 100% rename from crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_left/root_origin.png rename to crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,left/root_origin.png diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_left/root_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,left/root_origin.snap similarity index 100% rename from crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_left/root_origin.snap rename to crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,left/root_origin.snap diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_left/single_proj.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,left/single_proj.png similarity index 100% rename from crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_left/single_proj.png rename to crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,left/single_proj.png diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_left/single_proj.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,left/single_proj.snap similarity index 100% rename from crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_left/single_proj.snap rename to crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,left/single_proj.snap diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_left/unknown_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,left/unknown_origin.png similarity index 100% rename from crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_left/unknown_origin.png rename to crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,left/unknown_origin.png diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_left/unknown_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,left/unknown_origin.snap similarity index 100% rename from crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_left/unknown_origin.snap rename to crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,left/unknown_origin.snap diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_t/empty.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/empty.png similarity index 100% rename from crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_t/empty.png rename to crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/empty.png diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_t/empty.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/empty.snap similarity index 100% rename from crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_t/empty.snap rename to crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/empty.snap diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_t/multiple_proj.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/multiple_proj.png similarity index 100% rename from crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_t/multiple_proj.png rename to crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/multiple_proj.png diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_t/multiple_proj.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/multiple_proj.snap similarity index 100% rename from crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_t/multiple_proj.snap rename to crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/multiple_proj.snap diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_t/non_root_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/non_root_origin.png similarity index 100% rename from crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_t/non_root_origin.png rename to crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/non_root_origin.png diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_t/non_root_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/non_root_origin.snap similarity index 100% rename from crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_t/non_root_origin.snap rename to crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/non_root_origin.snap diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_t/proj_with_placeholder.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/proj_with_placeholder.png similarity index 100% rename from crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_t/proj_with_placeholder.png rename to crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/proj_with_placeholder.png diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_t/proj_with_placeholder.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/proj_with_placeholder.snap similarity index 100% rename from crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_t/proj_with_placeholder.snap rename to crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/proj_with_placeholder.snap diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_t/root_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/root_origin.png similarity index 100% rename from crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_t/root_origin.png rename to crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/root_origin.png diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_t/root_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/root_origin.snap similarity index 100% rename from crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_t/root_origin.snap rename to crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/root_origin.snap diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_t/single_proj.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/single_proj.png similarity index 100% rename from crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_t/single_proj.png rename to crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/single_proj.png diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_t/single_proj.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/single_proj.snap similarity index 100% rename from crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_t/single_proj.snap rename to crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/single_proj.snap diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_t/unknown_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/unknown_origin.png similarity index 100% rename from crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_t/unknown_origin.png rename to crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/unknown_origin.png diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_t/unknown_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/unknown_origin.snap similarity index 100% rename from crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath_t/unknown_origin.snap rename to crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/unknown_origin.snap diff --git a/crates/viewer/re_blueprint_tree/tests/view_structure_test.rs b/crates/viewer/re_blueprint_tree/tests/view_structure_test.rs index b5b1384fa2d7..1d2b948a1b86 100644 --- a/crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +++ b/crates/viewer/re_blueprint_tree/tests/view_structure_test.rs @@ -210,7 +210,7 @@ fn run_test_case(test_case: &TestCase, filter_query: Option<&str>) -> Result<(), let options = SnapshotOptions::default().output_path(format!( "tests/snapshots/view_structure_test/{}", filter_query - .map(|query| format!("query-{}", query.replace(' ', "_"))) + .map(|query| format!("query-{}", query.replace(' ', ",").replace('/', "_"))) .unwrap_or("no-query".to_owned()) )); harness.try_snapshot_options(test_case.name, &options) @@ -249,7 +249,7 @@ fn test_all_insta_test_cases() { settings.set_snapshot_path(format!( "snapshots/view_structure_test/{}", filter_query - .map(|query| format!("query-{}", query.replace(' ', "_"))) + .map(|query| format!("query-{}", query.replace(' ', ",").replace('/', "_"))) .unwrap_or("no-query".to_owned()) )); From aa30d0a62e43a8bea646a6303797b795aaa00948 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler Date: Wed, 5 Feb 2025 14:17:21 +0100 Subject: [PATCH 08/11] Blueprint tree test: make data store more interesting and update existing tests --- .../no-query/proj_with_placeholder.png | 4 +- .../no-query/proj_with_placeholder.snap | 36 +++++++++++++++++ .../no-query/root_origin.png | 4 +- .../no-query/root_origin.snap | 38 +++++++++++++++++- .../query-ath,t/proj_with_placeholder.png | 4 +- .../query-ath,t/proj_with_placeholder.snap | 40 +++++++++++++++++++ .../query-ath,t/root_origin.png | 4 +- .../query-ath,t/root_origin.snap | 40 +++++++++++++++++++ .../query-path/proj_with_placeholder.png | 4 +- .../query-path/proj_with_placeholder.snap | 36 +++++++++++++++++ .../query-path/root_origin.png | 4 +- .../query-path/root_origin.snap | 36 +++++++++++++++++ .../query-t/proj_with_placeholder.png | 4 +- .../query-t/proj_with_placeholder.snap | 40 +++++++++++++++++++ .../query-t/root_origin.png | 4 +- .../query-t/root_origin.snap | 40 +++++++++++++++++++ .../tests/view_structure_test.rs | 1 + 17 files changed, 322 insertions(+), 17 deletions(-) diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/proj_with_placeholder.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/proj_with_placeholder.png index 8a653346833e..cbd9ab1eb1a4 100644 --- a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/proj_with_placeholder.png +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/proj_with_placeholder.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9bd3c87b4f48556ccb9627909d4d39f122da06a3a45b87a01fbbcab3babdc1e2 -size 29455 +oid sha256:bd9d79f25cc28005da8bb48a0a21e76c21565b1e87198e208fb6b429ad838d9b +size 32955 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/proj_with_placeholder.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/proj_with_placeholder.snap index 358a6ce9c6fc..97a2449846b1 100644 --- a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/proj_with_placeholder.snap +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/proj_with_placeholder.snap @@ -121,6 +121,42 @@ root_container: highlight_sections: [] default_open: false children: + - kind: EntityPart + entity_path: + - path + - onto + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: onto + highlight_sections: [] + default_open: false + children: + - kind: EntityPart + entity_path: + - path + - onto + - their + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: their + highlight_sections: [] + default_open: false + children: + - kind: EntityPart + entity_path: + - path + - onto + - their + - coils + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: coils + highlight_sections: [] + default_open: false + children: [] - kind: OriginProjectionPlaceholder entity_path: - path diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/root_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/root_origin.png index c2b5d87226ff..834e5fcc0b51 100644 --- a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/root_origin.png +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/root_origin.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:39907858b535b567c22984aef9c247e0736595d99612aaf71a34f3f8b58d40df -size 24446 +oid sha256:ebbdfbab36a04ac4b97c4188301269e5a3d4a1b0aa5f3142e7342c761baa4235 +size 27946 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/root_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/root_origin.snap index 50a8535ede56..ab18a88a2561 100644 --- a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/root_origin.snap +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/no-query/root_origin.snap @@ -58,8 +58,44 @@ root_container: id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe label: path highlight_sections: [] - default_open: false + default_open: true children: + - kind: EntityPart + entity_path: + - path + - onto + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: onto + highlight_sections: [] + default_open: false + children: + - kind: EntityPart + entity_path: + - path + - onto + - their + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: their + highlight_sections: [] + default_open: false + children: + - kind: EntityPart + entity_path: + - path + - onto + - their + - coils + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: coils + highlight_sections: [] + default_open: false + children: [] - kind: EntityPart entity_path: - path diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/proj_with_placeholder.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/proj_with_placeholder.png index 4f23711003f0..24d066e9110f 100644 --- a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/proj_with_placeholder.png +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/proj_with_placeholder.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5691670357e66b9709a3b71c3b04aa09d8cb7886e21281436f1f1f0c4e8cb48c -size 21620 +oid sha256:5be0a52f036e1d705a1cb28370ff111d4668618a0f1943f92383b59dc94c7f4b +size 25183 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/proj_with_placeholder.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/proj_with_placeholder.snap index b47283d1f92c..92278ef167b7 100644 --- a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/proj_with_placeholder.snap +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/proj_with_placeholder.snap @@ -42,6 +42,46 @@ root_container: end: 4 default_open: true children: + - kind: EntityPart + entity_path: + - path + - onto + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: onto + highlight_sections: + - start: 2 + end: 3 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - onto + - their + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: their + highlight_sections: + - start: 0 + end: 1 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - onto + - their + - coils + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: coils + highlight_sections: [] + default_open: true + children: [] - kind: OriginProjectionPlaceholder entity_path: - path diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/root_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/root_origin.png index 4f5a3afb43e3..62a77e9ae9a9 100644 --- a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/root_origin.png +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/root_origin.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c55f740018f633c0ac734688c0fcd53ccc9657a41e3d9bc34a526dd2201458f2 -size 21656 +oid sha256:2431634a38ed4763cd573c0c8e2c4dd3f7b1ba899acd65c7524ab229b448d81e +size 25218 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/root_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/root_origin.snap index b01f10a3e902..36bad44fbc1e 100644 --- a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/root_origin.snap +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-ath,t/root_origin.snap @@ -41,6 +41,46 @@ root_container: end: 4 default_open: true children: + - kind: EntityPart + entity_path: + - path + - onto + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: onto + highlight_sections: + - start: 2 + end: 3 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - onto + - their + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: their + highlight_sections: + - start: 0 + end: 1 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - onto + - their + - coils + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: coils + highlight_sections: [] + default_open: true + children: [] - kind: EntityPart entity_path: - path diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/proj_with_placeholder.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/proj_with_placeholder.png index f881487b9da4..5e864e49eccc 100644 --- a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/proj_with_placeholder.png +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/proj_with_placeholder.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:748da1e6cfc868244ab4f8d1ee3c8d58a1ac7b1684aad7a5973288919312a469 -size 21655 +oid sha256:a4ed96956af8a032e23fa5cded5044613f80b4b47dc6f0ed1d6492ab600dcb12 +size 25155 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/proj_with_placeholder.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/proj_with_placeholder.snap index 116076911965..68d9547be773 100644 --- a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/proj_with_placeholder.snap +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/proj_with_placeholder.snap @@ -42,6 +42,42 @@ root_container: end: 4 default_open: true children: + - kind: EntityPart + entity_path: + - path + - onto + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: onto + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - onto + - their + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: their + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - onto + - their + - coils + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: coils + highlight_sections: [] + default_open: true + children: [] - kind: OriginProjectionPlaceholder entity_path: - path diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/root_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/root_origin.png index b80d493f84dd..72623b262f91 100644 --- a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/root_origin.png +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/root_origin.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b88962851daa462240175052eca367126d13197de9d3508439e408783ff9a9c9 -size 21560 +oid sha256:317a05283aba3e70052774961b81b9370e9252785cf84a3b8dab8c5b09a940b2 +size 25060 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/root_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/root_origin.snap index bfd26e4b5e73..55283ff2c6fa 100644 --- a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/root_origin.snap +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-path/root_origin.snap @@ -41,6 +41,42 @@ root_container: end: 4 default_open: true children: + - kind: EntityPart + entity_path: + - path + - onto + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: onto + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - onto + - their + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: their + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - onto + - their + - coils + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: coils + highlight_sections: [] + default_open: true + children: [] - kind: EntityPart entity_path: - path diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/proj_with_placeholder.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/proj_with_placeholder.png index 70bf63dac915..0a94832eaf0e 100644 --- a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/proj_with_placeholder.png +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/proj_with_placeholder.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b65af70a818490a01e260a32fc757a6f1b88dd9e917343ad60e3183d527badd8 -size 28795 +oid sha256:60d5eeb57ba851172c206e5332baec3dca63c287b6e51f96f2b3dafa59651241 +size 32358 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/proj_with_placeholder.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/proj_with_placeholder.snap index 2d4db25f39d5..051a7e86110f 100644 --- a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/proj_with_placeholder.snap +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/proj_with_placeholder.snap @@ -133,6 +133,46 @@ root_container: end: 3 default_open: true children: + - kind: EntityPart + entity_path: + - path + - onto + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: onto + highlight_sections: + - start: 2 + end: 3 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - onto + - their + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: their + highlight_sections: + - start: 0 + end: 1 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - onto + - their + - coils + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: coils + highlight_sections: [] + default_open: true + children: [] - kind: OriginProjectionPlaceholder entity_path: - path diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/root_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/root_origin.png index ba675fad44a6..445b2afbf557 100644 --- a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/root_origin.png +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/root_origin.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:547504b1fd0b02cb90b24844c018beeab2865f759eaa2c28908b32d6380c4017 -size 23786 +oid sha256:9017fd06a6c934bdc6d49c184c44dad457b8593c468fa18b889edc3df5f99282 +size 27349 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/root_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/root_origin.snap index bc93b1e4ac60..5dc1a3948ec0 100644 --- a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/root_origin.snap +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-t/root_origin.snap @@ -64,6 +64,46 @@ root_container: end: 3 default_open: true children: + - kind: EntityPart + entity_path: + - path + - onto + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: onto + highlight_sections: + - start: 2 + end: 3 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - onto + - their + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: their + highlight_sections: + - start: 0 + end: 1 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - onto + - their + - coils + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: coils + highlight_sections: [] + default_open: true + children: [] - kind: EntityPart entity_path: - path diff --git a/crates/viewer/re_blueprint_tree/tests/view_structure_test.rs b/crates/viewer/re_blueprint_tree/tests/view_structure_test.rs index 1d2b948a1b86..782b30b9749f 100644 --- a/crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +++ b/crates/viewer/re_blueprint_tree/tests/view_structure_test.rs @@ -111,6 +111,7 @@ fn test_context(test_case: &TestCase) -> TestContext { test_context.log_entity("/path/to/left".into(), add_point_to_chunk_builder); test_context.log_entity("/path/to/right".into(), add_point_to_chunk_builder); test_context.log_entity("/path/to/the/void".into(), add_point_to_chunk_builder); + test_context.log_entity("/path/onto/their/coils".into(), add_point_to_chunk_builder); test_context.log_entity("/center/way".into(), add_point_to_chunk_builder); } } From efb2b91baf5be0e8fc0053462c3b6c6aec2b4c65 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler Date: Wed, 5 Feb 2025 14:22:59 +0100 Subject: [PATCH 09/11] Blueprint tree test: Add more test cases --- .../query-_path_to,_rig/empty.png | 3 + .../query-_path_to,_rig/empty.snap | 5 + .../query-_path_to,_rig/multiple_proj.png | 3 + .../query-_path_to,_rig/multiple_proj.snap | 5 + .../query-_path_to,_rig/non_root_origin.png | 3 + .../query-_path_to,_rig/non_root_origin.snap | 5 + .../proj_with_placeholder.png | 3 + .../proj_with_placeholder.snap | 5 + .../query-_path_to,_rig/root_origin.png | 3 + .../query-_path_to,_rig/root_origin.snap | 71 ++++++++++ .../query-_path_to,_rig/single_proj.png | 3 + .../query-_path_to,_rig/single_proj.snap | 5 + .../query-_path_to,_rig/unknown_origin.png | 3 + .../query-_path_to,_rig/unknown_origin.snap | 5 + .../query-_path_to_th/empty.png | 3 + .../query-_path_to_th/empty.snap | 5 + .../query-_path_to_th/multiple_proj.png | 3 + .../query-_path_to_th/multiple_proj.snap | 5 + .../query-_path_to_th/non_root_origin.png | 3 + .../query-_path_to_th/non_root_origin.snap | 5 + .../proj_with_placeholder.png | 3 + .../proj_with_placeholder.snap | 5 + .../query-_path_to_th/root_origin.png | 3 + .../query-_path_to_th/root_origin.snap | 84 ++++++++++++ .../query-_path_to_th/single_proj.png | 3 + .../query-_path_to_th/single_proj.snap | 5 + .../query-_path_to_th/unknown_origin.png | 3 + .../query-_path_to_th/unknown_origin.snap | 5 + .../query-_to_the_/empty.png | 3 + .../query-_to_the_/empty.snap | 5 + .../query-_to_the_/multiple_proj.png | 3 + .../query-_to_the_/multiple_proj.snap | 5 + .../query-_to_the_/non_root_origin.png | 3 + .../query-_to_the_/non_root_origin.snap | 63 +++++++++ .../query-_to_the_/proj_with_placeholder.png | 3 + .../query-_to_the_/proj_with_placeholder.snap | 63 +++++++++ .../query-_to_the_/root_origin.png | 3 + .../query-_to_the_/root_origin.snap | 82 ++++++++++++ .../query-_to_the_/single_proj.png | 3 + .../query-_to_the_/single_proj.snap | 63 +++++++++ .../query-_to_the_/unknown_origin.png | 3 + .../query-_to_the_/unknown_origin.snap | 5 + .../query-to_the,oid/empty.png | 3 + .../query-to_the,oid/empty.snap | 5 + .../query-to_the,oid/multiple_proj.png | 3 + .../query-to_the,oid/multiple_proj.snap | 5 + .../query-to_the,oid/non_root_origin.png | 3 + .../query-to_the,oid/non_root_origin.snap | 65 ++++++++++ .../proj_with_placeholder.png | 3 + .../proj_with_placeholder.snap | 65 ++++++++++ .../query-to_the,oid/root_origin.png | 3 + .../query-to_the,oid/root_origin.snap | 84 ++++++++++++ .../query-to_the,oid/single_proj.png | 3 + .../query-to_the,oid/single_proj.snap | 65 ++++++++++ .../query-to_the,oid/unknown_origin.png | 3 + .../query-to_the,oid/unknown_origin.snap | 5 + .../query-to_the/empty.png | 3 + .../query-to_the/empty.snap | 5 + .../query-to_the/multiple_proj.png | 3 + .../query-to_the/multiple_proj.snap | 5 + .../query-to_the/non_root_origin.png | 3 + .../query-to_the/non_root_origin.snap | 63 +++++++++ .../query-to_the/proj_with_placeholder.png | 3 + .../query-to_the/proj_with_placeholder.snap | 122 ++++++++++++++++++ .../query-to_the/root_origin.png | 3 + .../query-to_the/root_origin.snap | 122 ++++++++++++++++++ .../query-to_the/single_proj.png | 3 + .../query-to_the/single_proj.snap | 63 +++++++++ .../query-to_the/unknown_origin.png | 3 + .../query-to_the/unknown_origin.snap | 5 + .../tests/view_structure_test.rs | 5 + 71 files changed, 1290 insertions(+) create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/empty.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/empty.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/multiple_proj.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/multiple_proj.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/non_root_origin.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/non_root_origin.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/proj_with_placeholder.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/proj_with_placeholder.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/root_origin.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/root_origin.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/single_proj.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/single_proj.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/unknown_origin.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/unknown_origin.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/empty.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/empty.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/multiple_proj.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/multiple_proj.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/non_root_origin.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/non_root_origin.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/proj_with_placeholder.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/proj_with_placeholder.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/root_origin.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/root_origin.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/single_proj.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/single_proj.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/unknown_origin.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/unknown_origin.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/empty.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/empty.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/multiple_proj.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/multiple_proj.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/non_root_origin.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/non_root_origin.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/proj_with_placeholder.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/proj_with_placeholder.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/root_origin.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/root_origin.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/single_proj.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/single_proj.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/unknown_origin.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/unknown_origin.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/empty.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/empty.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/multiple_proj.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/multiple_proj.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/non_root_origin.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/non_root_origin.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/proj_with_placeholder.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/proj_with_placeholder.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/root_origin.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/root_origin.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/single_proj.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/single_proj.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/unknown_origin.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/unknown_origin.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/empty.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/empty.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/multiple_proj.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/multiple_proj.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/non_root_origin.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/non_root_origin.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/proj_with_placeholder.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/proj_with_placeholder.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/root_origin.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/root_origin.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/single_proj.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/single_proj.snap create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/unknown_origin.png create mode 100644 crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/unknown_origin.snap diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/empty.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/empty.png new file mode 100644 index 000000000000..8dc5cf2ef645 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/empty.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f027fa14060cd5a6dea97421bb4ef9168235c196583e51e900679dfe1cae65f8 +size 11409 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/empty.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/empty.snap new file mode 100644 index 000000000000..6007f31692d5 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/empty.snap @@ -0,0 +1,5 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: ~ diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/multiple_proj.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/multiple_proj.png new file mode 100644 index 000000000000..8dc5cf2ef645 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/multiple_proj.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f027fa14060cd5a6dea97421bb4ef9168235c196583e51e900679dfe1cae65f8 +size 11409 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/multiple_proj.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/multiple_proj.snap new file mode 100644 index 000000000000..6007f31692d5 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/multiple_proj.snap @@ -0,0 +1,5 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: ~ diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/non_root_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/non_root_origin.png new file mode 100644 index 000000000000..8dc5cf2ef645 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/non_root_origin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f027fa14060cd5a6dea97421bb4ef9168235c196583e51e900679dfe1cae65f8 +size 11409 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/non_root_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/non_root_origin.snap new file mode 100644 index 000000000000..6007f31692d5 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/non_root_origin.snap @@ -0,0 +1,5 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: ~ diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/proj_with_placeholder.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/proj_with_placeholder.png new file mode 100644 index 000000000000..8dc5cf2ef645 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/proj_with_placeholder.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f027fa14060cd5a6dea97421bb4ef9168235c196583e51e900679dfe1cae65f8 +size 11409 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/proj_with_placeholder.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/proj_with_placeholder.snap new file mode 100644 index 000000000000..6007f31692d5 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/proj_with_placeholder.snap @@ -0,0 +1,5 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: ~ diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/root_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/root_origin.png new file mode 100644 index 000000000000..abe5ff9212fa --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/root_origin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:49d1f8f5e7893ce9b914fa12939888a8226dfb8061d7d1850c2dc4615e1d3dbc +size 19926 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/root_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/root_origin.snap new file mode 100644 index 000000000000..6c2ed3854d8b --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/root_origin.snap @@ -0,0 +1,71 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: / + visible: true + default_open: true + origin_tree: + kind: EntityPart + entity_path: [] + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: / (root) + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - path + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: path + highlight_sections: + - start: 0 + end: 4 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: to + highlight_sections: + - start: 0 + end: 2 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - right + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: right + highlight_sections: + - start: 0 + end: 3 + default_open: true + children: [] + projection_trees: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/single_proj.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/single_proj.png new file mode 100644 index 000000000000..8dc5cf2ef645 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/single_proj.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f027fa14060cd5a6dea97421bb4ef9168235c196583e51e900679dfe1cae65f8 +size 11409 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/single_proj.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/single_proj.snap new file mode 100644 index 000000000000..6007f31692d5 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/single_proj.snap @@ -0,0 +1,5 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: ~ diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/unknown_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/unknown_origin.png new file mode 100644 index 000000000000..8dc5cf2ef645 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/unknown_origin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f027fa14060cd5a6dea97421bb4ef9168235c196583e51e900679dfe1cae65f8 +size 11409 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/unknown_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/unknown_origin.snap new file mode 100644 index 000000000000..6007f31692d5 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to,_rig/unknown_origin.snap @@ -0,0 +1,5 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: ~ diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/empty.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/empty.png new file mode 100644 index 000000000000..754bf690159d --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/empty.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4374f8f28eaa33a6f8f01f4e412c72357679c2c6ad228f4402acee1511eab87c +size 11216 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/empty.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/empty.snap new file mode 100644 index 000000000000..6007f31692d5 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/empty.snap @@ -0,0 +1,5 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: ~ diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/multiple_proj.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/multiple_proj.png new file mode 100644 index 000000000000..754bf690159d --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/multiple_proj.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4374f8f28eaa33a6f8f01f4e412c72357679c2c6ad228f4402acee1511eab87c +size 11216 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/multiple_proj.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/multiple_proj.snap new file mode 100644 index 000000000000..6007f31692d5 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/multiple_proj.snap @@ -0,0 +1,5 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: ~ diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/non_root_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/non_root_origin.png new file mode 100644 index 000000000000..754bf690159d --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/non_root_origin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4374f8f28eaa33a6f8f01f4e412c72357679c2c6ad228f4402acee1511eab87c +size 11216 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/non_root_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/non_root_origin.snap new file mode 100644 index 000000000000..6007f31692d5 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/non_root_origin.snap @@ -0,0 +1,5 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: ~ diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/proj_with_placeholder.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/proj_with_placeholder.png new file mode 100644 index 000000000000..754bf690159d --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/proj_with_placeholder.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4374f8f28eaa33a6f8f01f4e412c72357679c2c6ad228f4402acee1511eab87c +size 11216 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/proj_with_placeholder.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/proj_with_placeholder.snap new file mode 100644 index 000000000000..6007f31692d5 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/proj_with_placeholder.snap @@ -0,0 +1,5 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: ~ diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/root_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/root_origin.png new file mode 100644 index 000000000000..a1dab7d3c372 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/root_origin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4ff463a51a5fbd342ba69bde70e59c3905b78da18279c23e76f807d28f84b513 +size 20756 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/root_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/root_origin.snap new file mode 100644 index 000000000000..c147e9eafd9e --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/root_origin.snap @@ -0,0 +1,84 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: / + visible: true + default_open: true + origin_tree: + kind: EntityPart + entity_path: [] + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: / (root) + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - path + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: path + highlight_sections: + - start: 0 + end: 4 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: to + highlight_sections: + - start: 0 + end: 2 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: the + highlight_sections: + - start: 0 + end: 2 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + - void + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: void + highlight_sections: [] + default_open: true + children: [] + projection_trees: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/single_proj.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/single_proj.png new file mode 100644 index 000000000000..754bf690159d --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/single_proj.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4374f8f28eaa33a6f8f01f4e412c72357679c2c6ad228f4402acee1511eab87c +size 11216 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/single_proj.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/single_proj.snap new file mode 100644 index 000000000000..6007f31692d5 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/single_proj.snap @@ -0,0 +1,5 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: ~ diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/unknown_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/unknown_origin.png new file mode 100644 index 000000000000..754bf690159d --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/unknown_origin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4374f8f28eaa33a6f8f01f4e412c72357679c2c6ad228f4402acee1511eab87c +size 11216 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/unknown_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/unknown_origin.snap new file mode 100644 index 000000000000..6007f31692d5 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_path_to_th/unknown_origin.snap @@ -0,0 +1,5 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: ~ diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/empty.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/empty.png new file mode 100644 index 000000000000..f77e82b0a3b4 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/empty.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:845c64af9be8b6210f7d170120e2da307266cf9c4089a5329e59b38a0c11c25a +size 10755 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/empty.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/empty.snap new file mode 100644 index 000000000000..6007f31692d5 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/empty.snap @@ -0,0 +1,5 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: ~ diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/multiple_proj.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/multiple_proj.png new file mode 100644 index 000000000000..f77e82b0a3b4 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/multiple_proj.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:845c64af9be8b6210f7d170120e2da307266cf9c4089a5329e59b38a0c11c25a +size 10755 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/multiple_proj.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/multiple_proj.snap new file mode 100644 index 000000000000..6007f31692d5 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/multiple_proj.snap @@ -0,0 +1,5 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: ~ diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/non_root_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/non_root_origin.png new file mode 100644 index 000000000000..637e999e14bc --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/non_root_origin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ae6533527fa65ae1a959cf3e9cc254d465675b4f80edb30a9011a71e2916713 +size 18629 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/non_root_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/non_root_origin.snap new file mode 100644 index 000000000000..52a7adb94202 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/non_root_origin.snap @@ -0,0 +1,63 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: path/to + visible: true + default_open: true + origin_tree: + kind: EntityPart + entity_path: + - path + - to + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: to + highlight_sections: + - start: 0 + end: 2 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: the + highlight_sections: + - start: 0 + end: 3 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + - void + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: void + highlight_sections: [] + default_open: true + children: [] + projection_trees: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/proj_with_placeholder.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/proj_with_placeholder.png new file mode 100644 index 000000000000..637e999e14bc --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/proj_with_placeholder.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ae6533527fa65ae1a959cf3e9cc254d465675b4f80edb30a9011a71e2916713 +size 18629 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/proj_with_placeholder.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/proj_with_placeholder.snap new file mode 100644 index 000000000000..52a7adb94202 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/proj_with_placeholder.snap @@ -0,0 +1,63 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: path/to + visible: true + default_open: true + origin_tree: + kind: EntityPart + entity_path: + - path + - to + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: to + highlight_sections: + - start: 0 + end: 2 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: the + highlight_sections: + - start: 0 + end: 3 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + - void + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: void + highlight_sections: [] + default_open: true + children: [] + projection_trees: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/root_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/root_origin.png new file mode 100644 index 000000000000..aa17aa0c7762 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/root_origin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d1d55417bc47eb34c4d7e03e1f615000d21e4f1661b323c40bf87f4dafd9a968 +size 20339 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/root_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/root_origin.snap new file mode 100644 index 000000000000..753b65b1ba59 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/root_origin.snap @@ -0,0 +1,82 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: / + visible: true + default_open: true + origin_tree: + kind: EntityPart + entity_path: [] + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: / (root) + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - path + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: path + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: to + highlight_sections: + - start: 0 + end: 2 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: the + highlight_sections: + - start: 0 + end: 3 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + - void + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: void + highlight_sections: [] + default_open: true + children: [] + projection_trees: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/single_proj.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/single_proj.png new file mode 100644 index 000000000000..183a66cfc750 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/single_proj.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d5c5be810b0b7049fc726fc2d9308d1f3bf59a229b158f2bd7b1fd4770229e3d +size 21248 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/single_proj.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/single_proj.snap new file mode 100644 index 000000000000..49a528cc8d5e --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/single_proj.snap @@ -0,0 +1,63 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: center/way + visible: true + default_open: true + origin_tree: ~ + projection_trees: + - kind: EntityPart + entity_path: + - path + - to + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: to + highlight_sections: + - start: 0 + end: 2 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: the + highlight_sections: + - start: 0 + end: 3 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + - void + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: void + highlight_sections: [] + default_open: true + children: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/unknown_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/unknown_origin.png new file mode 100644 index 000000000000..f77e82b0a3b4 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/unknown_origin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:845c64af9be8b6210f7d170120e2da307266cf9c4089a5329e59b38a0c11c25a +size 10755 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/unknown_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/unknown_origin.snap new file mode 100644 index 000000000000..6007f31692d5 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-_to_the_/unknown_origin.snap @@ -0,0 +1,5 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: ~ diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/empty.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/empty.png new file mode 100644 index 000000000000..fc76470e583d --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/empty.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0b82d3b997768e5bad6e1d223c84b35a3a643bf5304adff24ac3d83916fb29a7 +size 10960 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/empty.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/empty.snap new file mode 100644 index 000000000000..6007f31692d5 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/empty.snap @@ -0,0 +1,5 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: ~ diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/multiple_proj.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/multiple_proj.png new file mode 100644 index 000000000000..fc76470e583d --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/multiple_proj.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0b82d3b997768e5bad6e1d223c84b35a3a643bf5304adff24ac3d83916fb29a7 +size 10960 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/multiple_proj.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/multiple_proj.snap new file mode 100644 index 000000000000..6007f31692d5 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/multiple_proj.snap @@ -0,0 +1,5 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: ~ diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/non_root_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/non_root_origin.png new file mode 100644 index 000000000000..8eab4dae2057 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/non_root_origin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4572af9ec920149b0a91fb7d87c8a207958aae56f7b9dcd16705f5f6102fedc5 +size 18837 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/non_root_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/non_root_origin.snap new file mode 100644 index 000000000000..10c734d7a82d --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/non_root_origin.snap @@ -0,0 +1,65 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: path/to + visible: true + default_open: true + origin_tree: + kind: EntityPart + entity_path: + - path + - to + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: to + highlight_sections: + - start: 0 + end: 2 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: the + highlight_sections: + - start: 0 + end: 3 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + - void + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: void + highlight_sections: + - start: 1 + end: 4 + default_open: true + children: [] + projection_trees: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/proj_with_placeholder.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/proj_with_placeholder.png new file mode 100644 index 000000000000..8eab4dae2057 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/proj_with_placeholder.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4572af9ec920149b0a91fb7d87c8a207958aae56f7b9dcd16705f5f6102fedc5 +size 18837 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/proj_with_placeholder.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/proj_with_placeholder.snap new file mode 100644 index 000000000000..10c734d7a82d --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/proj_with_placeholder.snap @@ -0,0 +1,65 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: path/to + visible: true + default_open: true + origin_tree: + kind: EntityPart + entity_path: + - path + - to + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: to + highlight_sections: + - start: 0 + end: 2 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: the + highlight_sections: + - start: 0 + end: 3 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + - void + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: void + highlight_sections: + - start: 1 + end: 4 + default_open: true + children: [] + projection_trees: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/root_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/root_origin.png new file mode 100644 index 000000000000..943d40cc4f60 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/root_origin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f8f7080afef2e5930699dfd484877c06902d089e3af62bbbfa2c071fc4ef42bf +size 20548 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/root_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/root_origin.snap new file mode 100644 index 000000000000..b7c97c401c82 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/root_origin.snap @@ -0,0 +1,84 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: / + visible: true + default_open: true + origin_tree: + kind: EntityPart + entity_path: [] + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: / (root) + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - path + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: path + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: to + highlight_sections: + - start: 0 + end: 2 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: the + highlight_sections: + - start: 0 + end: 3 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + - void + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: void + highlight_sections: + - start: 1 + end: 4 + default_open: true + children: [] + projection_trees: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/single_proj.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/single_proj.png new file mode 100644 index 000000000000..4f5fdf5cf01b --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/single_proj.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e62b5617fbaee875595ad77a3622dfeea5c701bcefc621e419c606b9ce22fd1b +size 21456 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/single_proj.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/single_proj.snap new file mode 100644 index 000000000000..6d2be47df67e --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/single_proj.snap @@ -0,0 +1,65 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: center/way + visible: true + default_open: true + origin_tree: ~ + projection_trees: + - kind: EntityPart + entity_path: + - path + - to + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: to + highlight_sections: + - start: 0 + end: 2 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: the + highlight_sections: + - start: 0 + end: 3 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + - void + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: void + highlight_sections: + - start: 1 + end: 4 + default_open: true + children: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/unknown_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/unknown_origin.png new file mode 100644 index 000000000000..fc76470e583d --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/unknown_origin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0b82d3b997768e5bad6e1d223c84b35a3a643bf5304adff24ac3d83916fb29a7 +size 10960 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/unknown_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/unknown_origin.snap new file mode 100644 index 000000000000..6007f31692d5 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the,oid/unknown_origin.snap @@ -0,0 +1,5 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: ~ diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/empty.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/empty.png new file mode 100644 index 000000000000..faa7b7adba77 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/empty.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d67be91d9f61786f19efd0dc7cec43706763203b6d7f1004bcc53796700fb8ef +size 10413 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/empty.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/empty.snap new file mode 100644 index 000000000000..6007f31692d5 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/empty.snap @@ -0,0 +1,5 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: ~ diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/multiple_proj.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/multiple_proj.png new file mode 100644 index 000000000000..faa7b7adba77 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/multiple_proj.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d67be91d9f61786f19efd0dc7cec43706763203b6d7f1004bcc53796700fb8ef +size 10413 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/multiple_proj.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/multiple_proj.snap new file mode 100644 index 000000000000..6007f31692d5 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/multiple_proj.snap @@ -0,0 +1,5 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: ~ diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/non_root_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/non_root_origin.png new file mode 100644 index 000000000000..84353595d2da --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/non_root_origin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:274d67db90e1ddc41a73765f68552f643bc656a36cde16aae62e7ece064d4f0c +size 18287 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/non_root_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/non_root_origin.snap new file mode 100644 index 000000000000..52a7adb94202 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/non_root_origin.snap @@ -0,0 +1,63 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: path/to + visible: true + default_open: true + origin_tree: + kind: EntityPart + entity_path: + - path + - to + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: to + highlight_sections: + - start: 0 + end: 2 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: the + highlight_sections: + - start: 0 + end: 3 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + - void + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: void + highlight_sections: [] + default_open: true + children: [] + projection_trees: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/proj_with_placeholder.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/proj_with_placeholder.png new file mode 100644 index 000000000000..308b49c29666 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/proj_with_placeholder.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:560a1a987027f435d49a8346459ca1e302ce983b0a2404674b3bbbe6450a97f7 +size 26738 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/proj_with_placeholder.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/proj_with_placeholder.snap new file mode 100644 index 000000000000..4cd6c05bb682 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/proj_with_placeholder.snap @@ -0,0 +1,122 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: path/to + visible: true + default_open: true + origin_tree: + kind: EntityPart + entity_path: + - path + - to + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: to + highlight_sections: + - start: 0 + end: 2 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: the + highlight_sections: + - start: 0 + end: 3 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + - void + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: void + highlight_sections: [] + default_open: true + children: [] + projection_trees: + - kind: EntityPart + entity_path: [] + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: / (root) + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - path + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: path + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - onto + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: onto + highlight_sections: + - start: 2 + end: 4 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - onto + - their + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: their + highlight_sections: + - start: 0 + end: 3 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - onto + - their + - coils + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: coils + highlight_sections: [] + default_open: true + children: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/root_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/root_origin.png new file mode 100644 index 000000000000..ce193bb661be --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/root_origin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1f40a0bdd9a96b8cdeb7368d6d847cd594a3f38bbb5c050fd6e1a5f68343e8d8 +size 23501 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/root_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/root_origin.snap new file mode 100644 index 000000000000..26d831c3228d --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/root_origin.snap @@ -0,0 +1,122 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: / + visible: true + default_open: true + origin_tree: + kind: EntityPart + entity_path: [] + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: / (root) + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - path + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: path + highlight_sections: [] + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - onto + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: onto + highlight_sections: + - start: 2 + end: 4 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - onto + - their + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: their + highlight_sections: + - start: 0 + end: 3 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - onto + - their + - coils + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: coils + highlight_sections: [] + default_open: true + children: [] + - kind: EntityPart + entity_path: + - path + - to + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: to + highlight_sections: + - start: 0 + end: 2 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: the + highlight_sections: + - start: 0 + end: 3 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + - void + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: void + highlight_sections: [] + default_open: true + children: [] + projection_trees: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/single_proj.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/single_proj.png new file mode 100644 index 000000000000..d07dbd46f030 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/single_proj.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:579dfc0cb56b7ef03f09e334c9232a204f55883c2d629be7e7b549d4c6d9a169 +size 20906 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/single_proj.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/single_proj.snap new file mode 100644 index 000000000000..49a528cc8d5e --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/single_proj.snap @@ -0,0 +1,63 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: + id: + id: "" + name: + Placeholder: Grid + kind: Grid + visible: true + default_open: true + children: + - View: + id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + class_identifier: 3D + name: + Placeholder: center/way + visible: true + default_open: true + origin_tree: ~ + projection_trees: + - kind: EntityPart + entity_path: + - path + - to + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: to + highlight_sections: + - start: 0 + end: 2 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: the + highlight_sections: + - start: 0 + end: 3 + default_open: true + children: + - kind: EntityPart + entity_path: + - path + - to + - the + - void + visible: true + view_id: + id: 0864e1b8-cec4-1b82-5b17-b9d628b8f4fe + label: void + highlight_sections: [] + default_open: true + children: [] diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/unknown_origin.png b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/unknown_origin.png new file mode 100644 index 000000000000..faa7b7adba77 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/unknown_origin.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d67be91d9f61786f19efd0dc7cec43706763203b6d7f1004bcc53796700fb8ef +size 10413 diff --git a/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/unknown_origin.snap b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/unknown_origin.snap new file mode 100644 index 000000000000..6007f31692d5 --- /dev/null +++ b/crates/viewer/re_blueprint_tree/tests/snapshots/view_structure_test/query-to_the/unknown_origin.snap @@ -0,0 +1,5 @@ +--- +source: crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +expression: blueprint_tree_data +--- +root_container: ~ diff --git a/crates/viewer/re_blueprint_tree/tests/view_structure_test.rs b/crates/viewer/re_blueprint_tree/tests/view_structure_test.rs index 782b30b9749f..4a383efb33d6 100644 --- a/crates/viewer/re_blueprint_tree/tests/view_structure_test.rs +++ b/crates/viewer/re_blueprint_tree/tests/view_structure_test.rs @@ -96,6 +96,11 @@ fn filter_queries() -> impl Iterator> { Some("path"), Some("ath t"), Some("ath left"), + Some("to/the"), + Some("/to/the/"), + Some("to/the oid"), + Some("/path/to /rig"), + Some("/path/to/th"), ] .into_iter() } From 2b2dc087cffc3d8bdac045c568331e8599d3adb2 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler Date: Wed, 5 Feb 2025 14:23:21 +0100 Subject: [PATCH 10/11] lint --- crates/viewer/re_ui/src/filter_widget.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/viewer/re_ui/src/filter_widget.rs b/crates/viewer/re_ui/src/filter_widget.rs index d9adb8b5611e..9a93eeea669a 100644 --- a/crates/viewer/re_ui/src/filter_widget.rs +++ b/crates/viewer/re_ui/src/filter_widget.rs @@ -779,7 +779,5 @@ mod test { match_and_normalize("ab/cd bla", &["xxxAb", "cDaB", "Cdxxx"]), None ); - - //TODO: moar tests } } From ea2d4b0601ac60bc4a3ac125f829d56bcf47bf41 Mon Sep 17 00:00:00 2001 From: Antoine Beyeler Date: Wed, 5 Feb 2025 16:37:13 +0100 Subject: [PATCH 11/11] Review changes --- Cargo.lock | 2 +- crates/viewer/re_blueprint_tree/src/data.rs | 46 +++++++++------- .../re_time_panel/src/streams_tree_data.rs | 1 + crates/viewer/re_ui/Cargo.toml | 2 +- crates/viewer/re_ui/src/filter_widget.rs | 55 +++++++++++-------- 5 files changed, 59 insertions(+), 47 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 530b9666d24d..5447ea5468a4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6704,6 +6704,7 @@ dependencies = [ name = "re_ui" version = "0.22.0-alpha.1+dev" dependencies = [ + "ahash", "arrow", "eframe", "egui", @@ -6713,7 +6714,6 @@ dependencies = [ "egui_tiles", "getrandom", "itertools 0.13.0", - "nohash-hasher", "once_cell", "parking_lot", "rand", diff --git a/crates/viewer/re_blueprint_tree/src/data.rs b/crates/viewer/re_blueprint_tree/src/data.rs index 950d5e61d099..508fae83942c 100644 --- a/crates/viewer/re_blueprint_tree/src/data.rs +++ b/crates/viewer/re_blueprint_tree/src/data.rs @@ -406,6 +406,7 @@ impl DataResultData { NotLeaf(&'a DataResultNode), } + /// Temporary structure to hold local information. struct NodeInfo<'a> { leaf_or_not: LeafOrNot<'a>, kind: DataResultKind, @@ -523,27 +524,30 @@ impl DataResultData { } }; - let highlight_sections = hierarchy_highlights.remove(hierarchy.len().saturating_sub(1)); - - // never highlight the placeholder - let highlight_sections = - if node_info.kind == DataResultKind::OriginProjectionPlaceholder { - SmallVec::new() - } else { - highlight_sections - .map(Iterator::collect) - .unwrap_or_default() - }; - - is_this_a_match.then(|| Self { - kind: node_info.kind, - entity_path, - visible, - view_id: view_blueprint.id, - label, - highlight_sections, - default_open: node_info.default_open, - children, + is_this_a_match.then(|| { + let highlight_sections = + hierarchy_highlights.remove(hierarchy.len().saturating_sub(1)); + + // never highlight the placeholder + let highlight_sections = + if node_info.kind == DataResultKind::OriginProjectionPlaceholder { + SmallVec::new() + } else { + highlight_sections + .map(Iterator::collect) + .unwrap_or_default() + }; + + Self { + kind: node_info.kind, + entity_path, + visible, + view_id: view_blueprint.id, + label, + highlight_sections, + default_open: node_info.default_open, + children, + } }) }); diff --git a/crates/viewer/re_time_panel/src/streams_tree_data.rs b/crates/viewer/re_time_panel/src/streams_tree_data.rs index 86491c9111f5..6de4d701782d 100644 --- a/crates/viewer/re_time_panel/src/streams_tree_data.rs +++ b/crates/viewer/re_time_panel/src/streams_tree_data.rs @@ -128,6 +128,7 @@ impl EntityData { // Gather some info about the current node… // + /// Temporary structure to hold local information. struct NodeInfo { is_leaf: bool, is_this_a_match: bool, diff --git a/crates/viewer/re_ui/Cargo.toml b/crates/viewer/re_ui/Cargo.toml index d2e808192bbb..76b263e5f69c 100644 --- a/crates/viewer/re_ui/Cargo.toml +++ b/crates/viewer/re_ui/Cargo.toml @@ -41,6 +41,7 @@ re_log.workspace = true re_log_types.workspace = true # syntax-highlighting for EntityPath re_tracing.workspace = true +ahash.workspace = true arrow = { workspace = true, optional = true } eframe = { workspace = true, default-features = false, features = ["wgpu"] } egui_commonmark = { workspace = true, features = ["pulldown_cmark"] } @@ -51,7 +52,6 @@ getrandom.workspace = true itertools.workspace = true once_cell.workspace = true parking_lot.workspace = true -nohash-hasher.workspace = true serde = { workspace = true, features = ["derive"] } serde_json.workspace = true smallvec.workspace = true diff --git a/crates/viewer/re_ui/src/filter_widget.rs b/crates/viewer/re_ui/src/filter_widget.rs index 9a93eeea669a..74d3c9ea76c2 100644 --- a/crates/viewer/re_ui/src/filter_widget.rs +++ b/crates/viewer/re_ui/src/filter_widget.rs @@ -2,7 +2,6 @@ use std::ops::Range; use egui::{Color32, NumExt as _, Widget as _}; use itertools::Itertools; -use nohash_hasher::IntMap; use smallvec::SmallVec; use crate::{list_item, UiExt as _}; @@ -226,11 +225,11 @@ impl FilterMatcher { None => Some(PathRanges::default()), Some([]) => None, Some(keywords) => { - let hierarchy = path.into_iter().map(str::to_lowercase).collect_vec(); + let path = path.into_iter().map(str::to_lowercase).collect_vec(); let all_ranges = keywords .iter() - .map(|keyword| keyword.match_path(hierarchy.iter().map(String::as_str))) + .map(|keyword| keyword.match_path(path.iter().map(String::as_str))) .collect_vec(); // all keywords must match! @@ -256,13 +255,12 @@ impl FilterMatcher { /// `match_from_first_part_start` and/or `match_to_last_part_end`, which have the same behavior as /// regex's `^` and `$`. /// -/// If the keyword has multiple parts, the tested path must have at least one instance of contiguous +/// If the keyword has multiple parts, e.g. "first/second", the tested path must have at least one instance of contiguous /// parts which match the corresponding keyword parts. In that context, the keyword parts have the /// following behavior: /// - First keyword part: `^part$` if `match_from_first_part_start`, `part$` otherwise /// - Last keyword part: `^part$` if `match_to_last_part_end`, `^part` otherwise /// - Other keyword parts: `^part$` - #[derive(Debug, Clone, PartialEq)] struct Keyword { /// The parts of a keyword. @@ -279,6 +277,8 @@ impl Keyword { /// /// The string must not contain any whitespace! fn new(mut keyword: &str) -> Self { + // Invariant: keywords are not empty + debug_assert!(!keyword.is_empty()); debug_assert!(!keyword.contains(char::is_whitespace)); let match_from_first_part_start = if let Some(k) = keyword.strip_prefix('/') { @@ -307,16 +307,25 @@ impl Keyword { /// Match the keyword against the provided path. /// /// An empty [`PathRanges`] means that the keyword didn't match the path. - fn match_path<'a>(&self, path: impl IntoIterator) -> PathRanges { + /// + /// Implementation notes: + /// - This function is akin to a "sliding window" of the keyword parts against the path parts, + /// trying to find some "alignment" yielding a match. + /// - We must be thorough as we want to find _all_ match highlights (i.e., we don't early out as + /// soon as we find a match). + fn match_path<'a>(&self, lowercase_path: impl ExactSizeIterator) -> PathRanges { let mut state_machines = vec![]; - for (part_index, part) in path.into_iter().enumerate() { - let lowercase_part = part.to_lowercase(); + let path_length = lowercase_path.len(); - state_machines.push(MatchStateMachine::new(self)); + for (path_part_index, path_part) in lowercase_path.into_iter().enumerate() { + // Only start a new state machine if it has a chance to be matched entirely. + if self.parts.len() <= (path_length - path_part_index) { + state_machines.push(MatchStateMachine::new(self)); + } for state_machine in &mut state_machines { - state_machine.step(&lowercase_part, part_index); + state_machine.process_next_path_part(path_part, path_part_index); } } @@ -342,7 +351,7 @@ impl Keyword { /// merged when read, which only happens with [`Self::remove`]. #[derive(Debug, Default)] pub struct PathRanges { - ranges: IntMap>>, + ranges: ahash::HashMap>>, } impl PathRanges { @@ -435,7 +444,7 @@ impl<'a> MatchStateMachine<'a> { matches!(self.state, MatchState::Match) } - fn step(&mut self, part: &str, part_index: usize) { + fn process_next_path_part(&mut self, part: &str, part_index: usize) { if matches!(self.state, MatchState::Match | MatchState::NoMatch) { return; } @@ -694,17 +703,17 @@ mod test { #[test] fn test_keyword_match_path() { - fn match_and_normalize(query: &str, path: &[&str]) -> Vec>> { - let keyword = Keyword::new(query); - let path = path.to_vec(); - keyword.match_path(path.clone()).into_vec(path.len()) + fn match_and_normalize(query: &str, lowercase_path: &[&str]) -> Vec>> { + Keyword::new(query) + .match_path(lowercase_path.iter().copied()) + .into_vec(lowercase_path.len()) } assert_eq!(match_and_normalize("a", &["a"]), vec![vec![0..1]]); assert_eq!(match_and_normalize("a", &["aaa"]), vec![vec![0..3]]); assert_eq!( - match_and_normalize("A/", &["aaa", "aaa"]), + match_and_normalize("a/", &["aaa", "aaa"]), vec![vec![2..3], vec![2..3]] ); @@ -737,7 +746,7 @@ mod test { ); assert!( - match_and_normalize("a/B/c/", &["aaa", "b", "cccc"]) + match_and_normalize("a/b/c/", &["aaa", "b", "cccc"]) .into_iter() .flatten() .count() @@ -745,12 +754,12 @@ mod test { ); assert_eq!( - match_and_normalize("ab/cd", &["xxxAb", "cDaB", "Cdxxx"]), + match_and_normalize("ab/cd", &["xxxab", "cdab", "cdxxx"]), vec![vec![3..5], vec![0..4], vec![0..2]] ); assert_eq!( - match_and_normalize("ab/ab", &["xxxAb", "aB", "aBxxx"]), + match_and_normalize("ab/ab", &["xxxab", "ab", "abxxx"]), vec![vec![3..5], vec![0..2], vec![0..2]] ); } @@ -758,10 +767,8 @@ mod test { #[test] fn test_match_path() { fn match_and_normalize(query: &str, path: &[&str]) -> Option>>> { - let matcher = FilterMatcher::new(Some(query)); - let path = path.to_vec(); - matcher - .match_path(path.clone()) + FilterMatcher::new(Some(query)) + .match_path(path.iter().copied()) .map(|ranges| ranges.into_vec(path.len())) }