1use serde::{Deserialize, Serialize};
4
5use crate::extras::icon::Icon;
6use crate::node::{ActionId, Common, IntoNode, Key, Node};
7use crate::text::Line;
8
9#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
11#[serde(rename_all = "camelCase")]
12pub struct TreeNode {
13 pub key: Key,
15 pub label: Line,
17 #[serde(default, skip_serializing_if = "Option::is_none")]
19 pub icon: Option<Icon>,
20 #[serde(default, skip_serializing_if = "Option::is_none")]
22 pub badge: Option<Line>,
23 #[serde(default, skip_serializing_if = "Vec::is_empty")]
25 pub children: Vec<TreeNode>,
26 #[serde(default, skip_serializing_if = "Option::is_none")]
28 pub expanded: Option<bool>,
29 #[serde(default, skip_serializing_if = "Option::is_none")]
31 pub lazy: Option<bool>,
32}
33
34impl TreeNode {
35 #[must_use]
37 pub fn new(key: impl Into<Key>, label: impl Into<Line>) -> Self {
38 Self {
39 key: key.into(),
40 label: label.into(),
41 icon: None,
42 badge: None,
43 children: Vec::new(),
44 expanded: None,
45 lazy: None,
46 }
47 }
48
49 #[must_use]
51 pub fn icon(mut self, icon: Icon) -> Self {
52 self.icon = Some(icon);
53 self
54 }
55
56 #[must_use]
58 pub fn badge(mut self, badge: impl Into<Line>) -> Self {
59 self.badge = Some(badge.into());
60 self
61 }
62
63 #[must_use]
65 pub fn children(mut self, children: impl IntoIterator<Item = TreeNode>) -> Self {
66 self.children = children.into_iter().collect();
67 self
68 }
69
70 #[must_use]
72 pub fn expanded(mut self, expanded: bool) -> Self {
73 self.expanded = Some(expanded);
74 self
75 }
76
77 #[must_use]
79 pub fn lazy(mut self, lazy: bool) -> Self {
80 self.lazy = Some(lazy);
81 self
82 }
83}
84
85#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
87#[serde(rename_all = "camelCase")]
88pub struct TreeState {
89 #[serde(default, skip_serializing_if = "Option::is_none")]
91 pub selected: Option<Key>,
92}
93
94impl TreeState {
95 #[must_use]
97 pub fn with_selected(key: impl Into<Key>) -> Self {
98 Self {
99 selected: Some(key.into()),
100 }
101 }
102}
103
104#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
106#[serde(rename_all = "camelCase")]
107pub struct Tree {
108 #[serde(flatten)]
110 pub common: Common,
111 pub nodes: Vec<TreeNode>,
113 #[serde(default, skip_serializing_if = "Option::is_none")]
115 pub state: Option<TreeState>,
116 #[serde(default, skip_serializing_if = "Option::is_none")]
118 pub on_select: Option<ActionId>,
119 #[serde(default, skip_serializing_if = "Option::is_none")]
121 pub on_activate: Option<ActionId>,
122 #[serde(default, skip_serializing_if = "Option::is_none")]
124 pub on_toggle: Option<ActionId>,
125}
126
127impl Tree {
128 #[must_use]
130 pub fn new(nodes: impl IntoIterator<Item = TreeNode>) -> Self {
131 Self {
132 nodes: nodes.into_iter().collect(),
133 ..Self::default()
134 }
135 }
136
137 #[must_use]
139 pub fn state(mut self, state: TreeState) -> Self {
140 self.state = Some(state);
141 self
142 }
143
144 #[must_use]
146 pub fn on_select(mut self, action: impl Into<ActionId>) -> Self {
147 self.on_select = Some(action.into());
148 self
149 }
150
151 #[must_use]
153 pub fn on_activate(mut self, action: impl Into<ActionId>) -> Self {
154 self.on_activate = Some(action.into());
155 self
156 }
157
158 #[must_use]
160 pub fn on_toggle(mut self, action: impl Into<ActionId>) -> Self {
161 self.on_toggle = Some(action.into());
162 self
163 }
164}
165
166impl IntoNode for Tree {}
167impl From<Tree> for Node {
168 fn from(t: Tree) -> Self {
169 Node::Tree(t)
170 }
171}