Skip to main content

plot/lib/job/gens/
item_list.rs

1use crate::lib::job::ModeListForValidColumnItem;
2// pub fn draw_list(mode: &ModeListForValidColumnItem, node: &ScannedNode) -> String {
3// 	match mode {
4// 		ModeListForValidColumnItem::Flat => "•".to_string(),
5// 		ModeListForValidColumnItem::Tree => {
6// 			// Tier 1 (root) nie ma wcięcia, Tier 2 ma jedno, itd.
7// 			let indent = "│  ".repeat(node.tier.saturating_sub(1));
8// 			format!("{}├──", indent)
9// 		}
10// 		ModeListForValidColumnItem::None => unreachable!("None jest obsługiwane lokalnie przed wywołaniem"),
11// 	}
12// }
13use crate::lib::{job::ValidResultMainRow, logic::NodeIs};
14
15pub struct TreeLast;
16impl TreeLast {
17	pub const DIR_NO_CHILDREN: &'static str = "└───";
18	pub const DIR_WITH_CHILDREN: &'static str = "└──┬";
19	pub const FILE: &'static str = "└──•";
20	pub const INDENT: &'static str = "   ";
21	pub const BRIDGE_START: &'static str = "└──•";
22	pub const BRIDGE_NEXT: &'static str = "──•";
23	pub const BRIDGE_LAST: &'static str = "───";
24}
25
26pub struct TreeMid;
27impl TreeMid {
28	pub const DIR_NO_CHILDREN: &'static str = "├───";
29	pub const DIR_WITH_CHILDREN: &'static str = "├──┬";
30	pub const FILE: &'static str = "├──•";
31	pub const INDENT: &'static str = "│  ";
32	pub const BRIDGE_START: &'static str = "├──•";
33	pub const BRIDGE_NEXT: &'static str = "──•";
34	pub const BRIDGE_LAST: &'static str = "───";
35}
36
37pub struct DrawTree;
38impl DrawTree {
39	pub const ITEM_BETWEEN: &'static str = "  ├──•";
40	pub const ITEM_FIRST: &'static str = "  ┌──•";
41	pub const ITEM_LAST: &'static str = "  └──•";
42	pub const ITEM_ONEFOLD: &'static str = "   ──•";
43
44	pub fn list(index: usize, total: usize) -> &'static str {
45		if total <= 1 {
46			Self::ITEM_ONEFOLD
47		} else if index == 0 {
48			Self::ITEM_FIRST
49		} else if index == total - 1 {
50			Self::ITEM_LAST
51		} else {
52			Self::ITEM_BETWEEN
53		}
54	}
55}
56
57pub fn draw_list(
58	mode: &ModeListForValidColumnItem,
59	index: usize,
60	tab: &[ValidResultMainRow],
61	_tier_max: usize,
62) -> String {
63	match mode {
64		ModeListForValidColumnItem::Flat => DrawTree::list(index, tab.len()).to_string(),
65		ModeListForValidColumnItem::Tree => {
66			let node = &tab[index].node;
67			let t = node.tier;
68
69			// 1. Logika Lookahead O(1) - dzieci w tabeli
70			let is_dir = node.node == NodeIs::Dir;
71			let has_children = if is_dir {
72				if index + 1 < tab.len() { tab[index + 1].node.tier > t } else { false }
73			} else {
74				false
75			};
76
77			// 2. Logika Lookahead O(n) - obliczanie is_last
78			let mut is_last = vec![true; t + 1];
79			let mut active_levels = t;
80
81			for j in (index + 1)..tab.len() {
82				let next_tier = tab[j].node.tier;
83				if next_tier <= active_levels {
84					is_last[next_tier] = false;
85					active_levels = next_tier - 1;
86				}
87				if active_levels == 0 {
88					break;
89				}
90			}
91
92			// --- DETEKCJA NAJBLIŻSZEGO WIDOCZNEGO RODZICA (Dla mostka) ---
93			let mut vis_parent_tier = 0;
94			for i_prev in (0..index).rev() {
95				if node.path.str.starts_with(&tab[i_prev].node.path.str) && tab[i_prev].node.node == NodeIs::Dir {
96					vis_parent_tier = tab[i_prev].node.tier;
97					break;
98				}
99			}
100
101			let mut result = String::new();
102			let has_bridge = t > vis_parent_tier + 1;
103
104			// 3. Generujemy wcięcia LUB segmenty mostka (poziomy 1 do T-1)
105			for l in 1..t {
106				if has_bridge && l > vis_parent_tier {
107					// Rysujemy segmenty mostka (Jumping Bridge)
108					if l == vis_parent_tier + 1 {
109						result.push_str(if is_last[l] { TreeLast::BRIDGE_START } else { TreeMid::BRIDGE_START });
110					} else {
111						result.push_str(TreeMid::BRIDGE_NEXT);
112					}
113				} else {
114					// Twoja ORYGINALNA logika wcięć (Indents)
115					if is_last[l] {
116						result.push_str(TreeLast::INDENT);
117					} else {
118						result.push_str(TreeMid::INDENT);
119					}
120				}
121			}
122
123			// 4. Dobieramy odpowiedni symbol gałęzi końcowej (Twoja ORYGINALNA logika)
124			let am_i_last = is_last[t];
125			let branch = if is_dir {
126				match (am_i_last, has_children) {
127					(true, true) => TreeLast::DIR_WITH_CHILDREN,
128					(false, true) => TreeMid::DIR_WITH_CHILDREN,
129					(true, false) => TreeLast::DIR_NO_CHILDREN,
130					(false, false) => TreeMid::DIR_NO_CHILDREN,
131				}
132			} else if am_i_last {
133				TreeLast::FILE
134			} else {
135				TreeMid::FILE
136			};
137
138			// 5. Łączymy gałąź z ewentualnym mostkiem
139			if has_bridge {
140				let tail: String = branch.chars().skip(1).collect();
141				result.push_str(""); // błąd "─") // Łącznik łączący kropkę mostka z gałęzią
142				result.push_str(&tail);
143			} else {
144				result.push_str(branch);
145			}
146
147			result
148		}
149		ModeListForValidColumnItem::None => unreachable!("None jest obsługiwane lokalnie przed wywołaniem"),
150	}
151}