1use promkit_core::{Pane, PaneFactory, grapheme::StyledGraphemes};
2
3pub mod node;
4use node::Kind;
5#[path = "tree/tree.rs"]
6mod inner;
7pub use inner::Tree;
8pub mod config;
9pub use config::Config;
10
11#[derive(Clone)]
19pub struct State {
20 pub tree: Tree,
21 pub config: Config,
23}
24
25impl PaneFactory for State {
26 fn create_pane(&self, width: u16, height: u16) -> Pane {
27 let symbol = |kind: &Kind| -> &str {
28 match kind {
29 Kind::Folded { .. } => &self.config.folded_symbol,
30 Kind::Unfolded { .. } => &self.config.unfolded_symbol,
31 }
32 };
33
34 let indent = |kind: &Kind| -> usize {
35 match kind {
36 Kind::Folded { path, .. } | Kind::Unfolded { path, .. } => {
37 path.len() * self.config.indent
38 }
39 }
40 };
41
42 let id = |kind: &Kind| -> String {
43 match kind {
44 Kind::Folded { id, .. } | Kind::Unfolded { id, .. } => id.clone(),
45 }
46 };
47
48 let height = match self.config.lines {
49 Some(lines) => lines.min(height as usize),
50 None => height as usize,
51 };
52
53 let matrix = self
54 .tree
55 .kinds()
56 .iter()
57 .enumerate()
58 .filter(|(i, _)| *i >= self.tree.position() && *i < self.tree.position() + height)
59 .map(|(i, kind)| {
60 if i == self.tree.position() {
61 StyledGraphemes::from_str(
62 format!("{}{}{}", symbol(kind), " ".repeat(indent(kind)), id(kind),),
63 self.config.active_item_style,
64 )
65 } else {
66 StyledGraphemes::from_str(
67 format!(
68 "{}{}{}",
69 " ".repeat(StyledGraphemes::from(symbol(kind)).widths()),
70 " ".repeat(indent(kind)),
71 id(kind),
72 ),
73 self.config.inactive_item_style,
74 )
75 }
76 })
77 .fold((vec![], 0), |(mut acc, pos), item| {
78 let rows = item.matrixify(width as usize, height, 0).0;
79 if pos < self.tree.position() + height {
80 acc.extend(rows);
81 }
82 (acc, pos + 1)
83 });
84
85 Pane::new(matrix.0, 0)
86 }
87}