dear_imgui_rs/widget/tree/
builder.rs1use crate::Condition;
2use crate::sys;
3use crate::ui::Ui;
4
5use super::{TreeNodeFlags, TreeNodeId, TreeNodeToken};
6
7#[derive(Clone, Debug)]
9#[must_use]
10pub struct TreeNode<'a, T, L = &'static str> {
11 id: TreeNodeId<T>,
12 label: Option<L>,
13 opened: bool,
14 opened_cond: Option<Condition>,
15 flags: TreeNodeFlags,
16 ui: &'a Ui,
17}
18
19impl<'a, T: AsRef<str>> TreeNode<'a, T, &'static str> {
20 pub(super) fn new(id: TreeNodeId<T>, ui: &'a Ui) -> Self {
21 TreeNode {
22 id,
23 label: None,
24 opened: false,
25 opened_cond: None,
26 flags: TreeNodeFlags::NONE,
27 ui,
28 }
29 }
30
31 pub fn label<L: AsRef<str>>(self, label: L) -> TreeNode<'a, T, L> {
33 TreeNode {
34 id: self.id,
35 label: Some(label),
36 opened: self.opened,
37 opened_cond: self.opened_cond,
38 flags: self.flags,
39 ui: self.ui,
40 }
41 }
42}
43
44impl<'a, T: AsRef<str>, L: AsRef<str>> TreeNode<'a, T, L> {
45 pub fn opened(mut self, opened: bool, cond: Condition) -> Self {
47 self.opened = opened;
48 self.opened_cond = Some(cond);
49 self
50 }
51
52 pub fn selected(mut self, selected: bool) -> Self {
54 self.flags.set(TreeNodeFlags::SELECTED, selected);
55 self
56 }
57
58 pub fn framed(mut self, framed: bool) -> Self {
60 self.flags.set(TreeNodeFlags::FRAMED, framed);
61 self
62 }
63
64 pub fn allow_item_overlap(mut self, allow: bool) -> Self {
66 self.flags.set(TreeNodeFlags::ALLOW_ITEM_OVERLAP, allow);
67 self
68 }
69
70 pub fn no_tree_push_on_open(mut self, no_push: bool) -> Self {
72 self.flags.set(TreeNodeFlags::NO_TREE_PUSH_ON_OPEN, no_push);
73 self
74 }
75
76 pub fn no_auto_open_on_log(mut self, no_auto: bool) -> Self {
78 self.flags.set(TreeNodeFlags::NO_AUTO_OPEN_ON_LOG, no_auto);
79 self
80 }
81
82 pub fn default_open(mut self, default_open: bool) -> Self {
84 self.flags.set(TreeNodeFlags::DEFAULT_OPEN, default_open);
85 self
86 }
87
88 pub fn open_on_double_click(mut self, double_click: bool) -> Self {
90 self.flags
91 .set(TreeNodeFlags::OPEN_ON_DOUBLE_CLICK, double_click);
92 self
93 }
94
95 pub fn open_on_arrow(mut self, arrow_only: bool) -> Self {
97 self.flags.set(TreeNodeFlags::OPEN_ON_ARROW, arrow_only);
98 self
99 }
100
101 pub fn leaf(mut self, leaf: bool) -> Self {
103 self.flags.set(TreeNodeFlags::LEAF, leaf);
104 self
105 }
106
107 pub fn bullet(mut self, bullet: bool) -> Self {
109 self.flags.set(TreeNodeFlags::BULLET, bullet);
110 self
111 }
112
113 pub fn frame_padding(mut self, frame_padding: bool) -> Self {
115 self.flags.set(TreeNodeFlags::FRAME_PADDING, frame_padding);
116 self
117 }
118
119 pub fn span_avail_width(mut self, span: bool) -> Self {
121 self.flags.set(TreeNodeFlags::SPAN_AVAIL_WIDTH, span);
122 self
123 }
124
125 pub fn span_full_width(mut self, span: bool) -> Self {
127 self.flags.set(TreeNodeFlags::SPAN_FULL_WIDTH, span);
128 self
129 }
130
131 pub fn nav_left_jumps_back_here(mut self, nav: bool) -> Self {
133 self.flags.set(TreeNodeFlags::NAV_LEFT_JUMPS_BACK_HERE, nav);
134 self
135 }
136
137 pub fn push(self) -> Option<TreeNodeToken<'a>> {
144 let open = self.ui.run_with_bound_context(|| unsafe {
145 if let Some(opened_cond) = self.opened_cond {
146 sys::igSetNextItemOpen(self.opened, opened_cond as i32);
147 }
148
149 match &self.id {
150 TreeNodeId::Str(s) => {
151 if let Some(label) = self.label.as_ref() {
152 let (id_ptr, label_ptr) = self.ui.scratch_txt_two(s, label);
153 sys::igPushID_Str(id_ptr);
154 let open = sys::igTreeNodeEx_Str(label_ptr, self.flags.bits());
155 sys::igPopID();
156 open
157 } else {
158 let label_ptr = self.ui.scratch_txt(s);
159 sys::igTreeNodeEx_Str(label_ptr, self.flags.bits())
160 }
161 }
162 TreeNodeId::Ptr(ptr) => {
163 let label = self.label.as_ref().map_or("", |l| l.as_ref());
164 let label_ptr = self.ui.scratch_txt(label);
165 sys::igPushID_Ptr(*ptr as *const std::os::raw::c_void);
166 let open = sys::igTreeNodeEx_Str(label_ptr, self.flags.bits());
167 sys::igPopID();
168 open
169 }
170 TreeNodeId::Int(i) => {
171 let label = self.label.as_ref().map_or("", |l| l.as_ref());
172 let label_ptr = self.ui.scratch_txt(label);
173 sys::igPushID_Int(*i);
174 let open = sys::igTreeNodeEx_Str(label_ptr, self.flags.bits());
175 sys::igPopID();
176 open
177 }
178 }
179 });
180
181 if open {
182 Some(TreeNodeToken::new(self.ui))
183 } else {
184 None
185 }
186 }
187}