blockworx_editor/
content_path.rs1use crate::path::BlockPath;
11use blockworx_doc::{document::IndexedDocument, id::BlockId};
12
13type Doc<'a> = IndexedDocument<'a>;
16
17pub const SEPARATOR: char = '/';
19pub const SEPARATOR_STR: &str = "/";
21
22pub fn name_of(document: &Doc<'_>, id: BlockId) -> String {
26 document
27 .doc
28 .block(&id)
29 .map(|block| block.title.name.trim().to_owned())
30 .filter(|name| !name.is_empty())
31 .unwrap_or_else(|| id.to_string())
32}
33
34pub fn segments(document: &Doc<'_>, path: &BlockPath) -> Vec<String> {
43 path.segments()
44 .iter()
45 .map(|&id| name_of(document, id))
46 .collect()
47}
48
49pub fn to_string(document: &Doc<'_>, path: &BlockPath) -> String {
51 join(&segments(document, path))
52}
53
54pub fn join(segments: &[String]) -> String {
56 segments.join(&SEPARATOR.to_string())
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62 use crate::path::Scope;
63 use crate::widget::test_fixtures::{self as fx, Scene};
64 use blockworx_doc::fixtures::block_id;
65 use blockworx_geom::{Rect, pos2};
66
67 fn body() -> Rect {
68 Rect::from_min_max(pos2(0.0, 0.0), pos2(60.0, 60.0))
69 }
70
71 fn nested() -> (Scene, Vec<BlockId>) {
73 let scene = Scene::new(vec![
74 fx::block_in(1, Scope::Root, body()),
75 fx::titled(1, "top"),
76 fx::block_in(2, Scope::Block(block_id(1)), body()),
77 fx::titled(2, "Thing 1"),
78 fx::block_in(3, Scope::Block(block_id(2)), body()),
79 fx::titled(3, "Core"),
80 ]);
81 (scene, vec![block_id(1), block_id(2), block_id(3)])
82 }
83
84 fn path_of(ids: &[BlockId]) -> BlockPath {
85 let mut path = BlockPath::empty();
86 for &id in ids {
87 path.push(id);
88 }
89 path
90 }
91
92 #[test]
93 fn a_path_reads_as_names_from_the_root_down() {
94 let (mut scene, ids) = nested();
95 let indexed = scene.indexed();
96 assert_eq!(to_string(&indexed, &path_of(&ids)), "top/Thing 1/Core");
97 assert_eq!(
98 to_string(&indexed, &BlockPath::empty()),
99 "",
100 "the document root is the unnamed scope the path hangs from"
101 );
102 }
103
104 #[test]
107 fn an_untitled_block_falls_back_to_its_id() {
108 let id = block_id(1);
109 let mut scene = Scene::new(vec![
110 fx::block_in(1, Scope::Root, body()),
111 fx::titled(1, ""),
112 ]);
113 let indexed = scene.indexed();
114 let text = to_string(&indexed, &path_of(&[id]));
115 assert_eq!(text, id.to_string());
116 }
117
118 #[test]
121 fn the_root_contributes_no_segments() {
122 let (mut scene, _) = nested();
123 let indexed = scene.indexed();
124 assert!(segments(&indexed, &BlockPath::empty()).is_empty());
125 }
126}