fltk/
tree.rs

1use crate::enums::{Color, Font, FrameType, Key};
2use crate::image::Image;
3use crate::prelude::*;
4use crate::utils::FlString;
5use crate::widget::Widget;
6use fltk_sys::tree::*;
7use std::{
8    ffi::{CStr, CString},
9    mem,
10    os::raw,
11};
12
13/// Defines the Tree sort order
14#[repr(i32)]
15#[derive(Debug, Copy, Clone, PartialEq, Eq)]
16pub enum TreeSort {
17    /// Don't sort
18    None = 0,
19    /// Sort ascending
20    Ascending = 1,
21    /// Sort descending
22    Descending = 2,
23}
24
25/// Defines the Tree's connector sort order
26#[repr(i32)]
27#[derive(Debug, Copy, Clone, PartialEq, Eq)]
28pub enum TreeConnectorStyle {
29    /// No line
30    None = 0,
31    /// Dotted line
32    Dotted = 1,
33    /// Solid line
34    Solid = 2,
35}
36
37/// Defines the Tree select mode
38#[repr(i32)]
39#[derive(Debug, Copy, Clone, PartialEq, Eq)]
40pub enum TreeSelect {
41    /// Select none
42    None = 0,
43    /// Select single
44    Single = 1,
45    /// Select multi
46    Multi = 2,
47    /// Select single and make draggable
48    SingleDraggable = 3,
49}
50
51/// Defines the `TreeItem`'s select mode
52#[repr(i32)]
53#[derive(Debug, Copy, Clone, PartialEq, Eq)]
54pub enum TreeItemSelect {
55    /// Deselect when clicked
56    Deselect = 0,
57    /// Selected when clicked
58    Select = 1,
59    /// Toggle when clicked
60    Toggle = 2,
61}
62
63/// Defines the Tree's callback reason
64#[repr(i32)]
65#[derive(Debug, Copy, Clone, PartialEq, Eq)]
66pub enum TreeReason {
67    /// No callback trigger
68    None = 0,
69    /// Trigger callback when selected
70    Selected,
71    /// Trigger callback when deselected
72    Deselected,
73    /// Trigger callback when reselected
74    Reselected,
75    /// Trigger callback when opened
76    Opened,
77    /// Trigger callback when closed
78    Closed,
79    /// Trigger callback when dragged
80    Dragged,
81}
82
83/// Defines the `TreeItem`'s reselect mode
84#[repr(i32)]
85#[derive(Debug, Copy, Clone, PartialEq, Eq)]
86pub enum TreeItemReselectMode {
87    /// Reselect once
88    Once = 0,
89    /// Always reselect
90    Always,
91}
92
93/// Defines the `TreeItem`'s draw mode
94#[repr(i32)]
95#[derive(Debug, Copy, Clone, PartialEq, Eq)]
96pub enum TreeItemDrawMode {
97    /// Default draw mode
98    Default = 0,
99    /// Draws label and widget
100    LabelAndWidget = 1,
101    /// Draws the height from widget
102    HeightFromWidget = 2,
103}
104
105/// Defines a tree widget
106#[derive(Debug)]
107pub struct Tree {
108    inner: crate::widget::WidgetTracker,
109    is_derived: bool,
110}
111
112crate::macros::widget::impl_widget_ext!(Tree, Fl_Tree);
113crate::macros::widget::impl_widget_base!(Tree, Fl_Tree);
114crate::macros::widget::impl_widget_default!(Tree, Fl_Tree);
115
116/// Defines a tree item
117#[derive(Debug, Clone)]
118pub struct TreeItem {
119    inner: *mut Fl_Tree_Item,
120    parent: *const Fl_Tree_Item,
121    tree: Tree,
122    is_root: bool,
123    is_derived: bool,
124}
125
126/// Defines a tree item array
127#[derive(Debug)]
128struct TreeItemArray {
129    inner: *mut Fl_Tree_Item_Array,
130}
131
132impl Tree {
133    /// Creates a Tree from a raw `Fl_Tree pointer`
134    /// # Safety
135    /// The pointer must be valid
136    pub unsafe fn from_raw(ptr: *mut Fl_Tree) -> Option<Tree> {
137        if ptr.is_null() {
138            None
139        } else {
140            let inner = crate::widget::WidgetTracker::new(ptr as _);
141            let x = Tree {
142                inner,
143                is_derived: false,
144            };
145            Some(x)
146        }
147    }
148
149    /// Begins the Tree widget
150    pub fn begin(&self) {
151        unsafe { Fl_Tree_begin(self.inner.widget() as _) }
152    }
153
154    /// Ends the Tree widget
155    pub fn end(&self) {
156        unsafe { Fl_Tree_end(self.inner.widget() as _) }
157    }
158
159    /// Shows the Tree widget
160    pub fn show_self(&mut self) {
161        unsafe { Fl_Tree_show_self(self.inner.widget() as _) }
162    }
163
164    /// Sets the root label
165    pub fn set_root_label(&mut self, new_label: &str) {
166        let new_label = CString::safe_new(new_label);
167        unsafe { Fl_Tree_root_label(self.inner.widget() as _, new_label.as_ptr()) }
168    }
169
170    /// Gets the Tree's root
171    pub fn root(&self) -> Option<TreeItem> {
172        unsafe { TreeItem::from_raw(Fl_Tree_root(self.inner.widget() as _)) }
173    }
174
175    /// Sets the Tree's root
176    pub fn set_root(&mut self, new_item: Option<TreeItem>) {
177        let ptr = match new_item {
178            None => std::ptr::null_mut(),
179            Some(item) => item.inner,
180        };
181        unsafe { Fl_Tree_set_root(self.inner.widget() as _, ptr) }
182    }
183
184    /// Adds a `TreeItem`
185    pub fn add(&mut self, path: &str) -> Option<TreeItem> {
186        let path = CString::safe_new(path);
187        unsafe {
188            let x = Fl_Tree_add(self.inner.widget() as _, path.as_ptr() as *mut raw::c_char);
189            TreeItem::from_raw(x)
190        }
191    }
192
193    /// Adds a `TreeItem`
194    pub fn add_item(&mut self, path: &str, item: &TreeItem) -> Option<TreeItem> {
195        let path = CString::safe_new(path);
196        unsafe {
197            let x = Fl_Tree_add_item(
198                self.inner.widget() as _,
199                path.as_ptr() as *mut raw::c_char,
200                item.inner,
201            );
202            TreeItem::from_raw(x)
203        }
204    }
205
206    /// Inserts a `TreeItem` above another tree item
207    pub fn insert_above(&mut self, above: &TreeItem, name: &str) -> Option<TreeItem> {
208        if above.inner.is_null() {
209            return None;
210        }
211        let name = CString::safe_new(name);
212        unsafe {
213            let x = Fl_Tree_insert_above(
214                self.inner.widget() as _,
215                above.inner,
216                name.as_ptr() as *mut raw::c_char,
217            );
218            TreeItem::from_raw(x)
219        }
220    }
221
222    /// Inserts a `TreeItem` at a position `pos`
223    pub fn insert(&mut self, item: &TreeItem, name: &str, pos: i32) -> Option<TreeItem> {
224        if item.inner.is_null() {
225            return None;
226        }
227        let name = CString::safe_new(name);
228        unsafe {
229            let x = Fl_Tree_insert(
230                self.inner.widget() as _,
231                item.inner,
232                name.as_ptr() as *mut raw::c_char,
233                pos,
234            );
235            TreeItem::from_raw(x)
236        }
237    }
238
239    /// Removes a `TreeItem`
240    /// # Errors
241    /// Errors on failure to remove item
242    pub fn remove(&mut self, item: &TreeItem) -> Result<(), FltkError> {
243        if item.inner.is_null() {
244            return Err(FltkError::Internal(FltkErrorKind::FailedOperation));
245        }
246        unsafe {
247            match Fl_Tree_remove(self.inner.widget() as _, item.inner) {
248                0 => Ok(()),
249                _ => Err(FltkError::Internal(FltkErrorKind::FailedOperation)),
250            }
251        }
252    }
253
254    /// Clears a tree
255    pub fn clear(&mut self) {
256        unsafe { Fl_Tree_clear(self.inner.widget() as _) }
257    }
258
259    /// Clears all children
260    pub fn clear_children(&mut self, item: &TreeItem) {
261        assert!(!item.inner.is_null());
262        unsafe { Fl_Tree_clear_children(self.inner.widget() as *mut Fl_Tree, item.inner) }
263    }
264
265    /// Finds a tree item
266    pub fn find_item(&self, path: &str) -> Option<TreeItem> {
267        let path = CString::safe_new(path);
268        unsafe {
269            let x = Fl_Tree_find_item(self.inner.widget() as _, path.as_ptr() as *mut raw::c_char);
270            if x.is_null() {
271                None
272            } else {
273                TreeItem::from_raw(x as *mut Fl_Tree_Item)
274            }
275        }
276    }
277
278    /// finds a clicked item
279    pub fn find_clicked(&self, yonly: bool) -> Option<TreeItem> {
280        unsafe {
281            TreeItem::from_raw(
282                Fl_Tree_find_clicked(self.inner.widget() as _, i32::from(yonly))
283                    as *mut Fl_Tree_Item,
284            )
285        }
286    }
287
288    /// Gets the first tree item
289    pub fn first(&self) -> Option<TreeItem> {
290        unsafe { TreeItem::from_raw(Fl_Tree_first(self.inner.widget() as _)) }
291    }
292
293    /// Gets the first visible tree item
294    pub fn first_visible_item(&self) -> Option<TreeItem> {
295        unsafe { TreeItem::from_raw(Fl_Tree_first_visible_item(self.inner.widget() as _)) }
296    }
297
298    /// Gets the next tree item
299    pub fn next(&self, item: &TreeItem) -> Option<TreeItem> {
300        if item.inner.is_null() {
301            return None;
302        }
303        unsafe { TreeItem::from_raw(Fl_Tree_next(self.inner.widget() as _, item.inner)) }
304    }
305
306    /// Gets the previous tree item
307    pub fn prev(&self, item: &TreeItem) -> Option<TreeItem> {
308        if item.inner.is_null() {
309            return None;
310        }
311        unsafe { TreeItem::from_raw(Fl_Tree_prev(self.inner.widget() as _, item.inner)) }
312    }
313
314    /// Gets the last tree item
315    pub fn last(&self) -> Option<TreeItem> {
316        unsafe { TreeItem::from_raw(Fl_Tree_last(self.inner.widget() as _)) }
317    }
318
319    /// Gets the last visible tree item
320    pub fn last_visible_item(&self) -> Option<TreeItem> {
321        unsafe { TreeItem::from_raw(Fl_Tree_last_visible_item(self.inner.widget() as _)) }
322    }
323
324    /// Gets the next visible tree item
325    pub fn next_visible_item(&self, start: &TreeItem, direction_key: Key) -> Option<TreeItem> {
326        if start.inner.is_null() {
327            return None;
328        }
329        unsafe {
330            TreeItem::from_raw(Fl_Tree_next_visible_item(
331                self.inner.widget() as _,
332                start.inner,
333                direction_key.bits(),
334            ))
335        }
336    }
337
338    /// Gets the first selected tree item
339    pub fn first_selected_item(&self) -> Option<TreeItem> {
340        unsafe { TreeItem::from_raw(Fl_Tree_first_selected_item(self.inner.widget() as _)) }
341    }
342
343    /// Gets the last selected tree item
344    pub fn last_selected_item(&self) -> Option<TreeItem> {
345        unsafe { TreeItem::from_raw(Fl_Tree_last_selected_item(self.inner.widget() as _)) }
346    }
347
348    /// Gets the next tree item, `direction_key` is by default [`Key::Down`](`crate::enums::Key::Down`)
349    pub fn next_item(
350        &self,
351        item: &TreeItem,
352        direction_key: Key,
353        visible: bool,
354    ) -> Option<TreeItem> {
355        if item.inner.is_null() {
356            return None;
357        }
358        unsafe {
359            TreeItem::from_raw(Fl_Tree_next_item(
360                self.inner.widget() as _,
361                item.inner,
362                direction_key.bits(),
363                i32::from(visible),
364            ))
365        }
366    }
367
368    /// Gets the next selected tree item, `direction_key` is by default [`Key::Down`](`crate::enums::Key::Down`)
369    pub fn next_selected_item(&mut self, item: &TreeItem, direction_key: Key) -> Option<TreeItem> {
370        if item.inner.is_null() {
371            return None;
372        }
373        unsafe {
374            TreeItem::from_raw(Fl_Tree_next_selected_item(
375                self.inner.widget() as _,
376                item.inner,
377                direction_key.bits(),
378            ))
379        }
380    }
381
382    /// Gets the selected tree items
383    pub fn get_selected_items(&self) -> Option<Vec<TreeItem>> {
384        unsafe {
385            let mut items = TreeItemArray {
386                inner: std::ptr::null_mut(),
387            };
388            let ret = Fl_Tree_get_selected_items(self.inner.widget() as _, &mut items.inner);
389            if ret == 0 { None } else { items.into_vec() }
390        }
391    }
392
393    /// Gets the all tree items
394    pub fn get_items(&self) -> Option<Vec<TreeItem>> {
395        unsafe {
396            let mut items = TreeItemArray {
397                inner: std::ptr::null_mut(),
398            };
399            let ret = Fl_Tree_get_items(self.inner.widget() as _, &mut items.inner);
400            if ret == 0 { None } else { items.into_vec() }
401        }
402    }
403
404    /// Opens a tree item, causing the children to be shown
405    /// # Errors
406    /// Errors on failure to open an item
407    pub fn open(&mut self, path: &str, do_callback: bool) -> Result<(), FltkError> {
408        let path = CString::safe_new(path);
409        unsafe {
410            match Fl_Tree_open(
411                self.inner.widget() as _,
412                path.as_ptr() as *mut raw::c_char,
413                i32::from(do_callback),
414            ) {
415                0 | 1 => Ok(()),
416                _ => Err(FltkError::Internal(FltkErrorKind::FailedOperation)),
417            }
418        }
419    }
420
421    /// Toggle the open state
422    pub fn open_toggle(&mut self, item: &TreeItem, do_callback: bool) {
423        assert!(!item.inner.is_null());
424        unsafe { Fl_Tree_open_toggle(self.inner.widget() as _, item.inner, i32::from(do_callback)) }
425    }
426
427    /// Close a tree item, causing the children to be hidden
428    /// # Errors
429    /// Errors on failure to close an item
430    pub fn close(&mut self, path: &str, do_callback: bool) -> Result<(), FltkError> {
431        let path = CString::safe_new(path);
432        unsafe {
433            match Fl_Tree_close(
434                self.inner.widget() as _,
435                path.as_ptr() as *mut raw::c_char,
436                i32::from(do_callback),
437            ) {
438                -1 => Err(FltkError::Internal(FltkErrorKind::FailedOperation)),
439                _ => Ok(()),
440            }
441        }
442    }
443
444    /// Returns whether an item is open
445    pub fn is_open(&self, path: &str) -> bool {
446        let path = CString::safe_new(path);
447        unsafe { Fl_Tree_is_open(self.inner.widget() as _, path.as_ptr() as *mut raw::c_char) != 0 }
448    }
449
450    /// Returns whether an item is closed
451    pub fn is_close(&self, path: &str) -> bool {
452        let path = CString::safe_new(path);
453        unsafe {
454            Fl_Tree_is_close(self.inner.widget() as _, path.as_ptr() as *mut raw::c_char) != 0
455        }
456    }
457
458    /// Select a tree item
459    /// # Errors
460    /// Errors on failure to select an item
461    pub fn select(&mut self, path: &str, do_callback: bool) -> Result<(), FltkError> {
462        let path = CString::safe_new(path);
463        unsafe {
464            match Fl_Tree_select(
465                self.inner.widget() as _,
466                path.as_ptr() as *mut raw::c_char,
467                i32::from(do_callback),
468            ) {
469                0 => Ok(()),
470                _ => Err(FltkError::Internal(FltkErrorKind::FailedOperation)),
471            }
472        }
473    }
474
475    /// Toggle the select state of the specified
476    pub fn select_toggle(&mut self, item: &TreeItem, do_callback: bool) {
477        assert!(!item.inner.is_null());
478        unsafe {
479            Fl_Tree_select_toggle(self.inner.widget() as _, item.inner, i32::from(do_callback));
480        }
481    }
482
483    /// Deselect an item at `path` and determine whether to do the callback
484    /// # Errors
485    /// Errors on failure to deselect item
486    pub fn deselect(&mut self, path: &str, do_callback: bool) -> Result<(), FltkError> {
487        let path = CString::safe_new(path);
488        unsafe {
489            match Fl_Tree_deselect(
490                self.inner.widget() as _,
491                path.as_ptr() as *mut raw::c_char,
492                i32::from(do_callback),
493            ) {
494                0 => Ok(()),
495                _ => Err(FltkError::Internal(FltkErrorKind::FailedOperation)),
496            }
497        }
498    }
499
500    /// Deselect all items
501    /// # Errors
502    /// Errors on failure to deselect all items
503    pub fn deselect_all(&mut self, item: &TreeItem, do_callback: bool) -> Result<(), FltkError> {
504        if item.inner.is_null() {
505            return Err(FltkError::Internal(FltkErrorKind::FailedOperation));
506        }
507        unsafe {
508            match Fl_Tree_deselect_all(self.inner.widget() as _, item.inner, i32::from(do_callback))
509            {
510                0 => Ok(()),
511                _ => Err(FltkError::Internal(FltkErrorKind::FailedOperation)),
512            }
513        }
514    }
515
516    /// Select only the specified item, deselecting all others that might be selected.
517    /// # Errors
518    /// Errors on failure to select an item
519    pub fn select_only(
520        &mut self,
521        selected_item: &TreeItem,
522        do_callback: bool,
523    ) -> Result<(), FltkError> {
524        if selected_item.inner.is_null() {
525            return Err(FltkError::Internal(FltkErrorKind::FailedOperation));
526        }
527        unsafe {
528            match Fl_Tree_select_only(
529                self.inner.widget() as _,
530                selected_item.inner,
531                i32::from(do_callback),
532            ) {
533                0 => Ok(()),
534                _ => Err(FltkError::Internal(FltkErrorKind::FailedOperation)),
535            }
536        }
537    }
538
539    /// Select all items
540    /// # Errors
541    /// Errors on failure to select an item
542    pub fn select_all(&mut self, item: &TreeItem, do_callback: bool) -> Result<(), FltkError> {
543        if item.inner.is_null() {
544            return Err(FltkError::Internal(FltkErrorKind::FailedOperation));
545        }
546        unsafe {
547            match Fl_Tree_select_all(self.inner.widget() as _, item.inner, i32::from(do_callback)) {
548                0 => Ok(()),
549                _ => Err(FltkError::Internal(FltkErrorKind::FailedOperation)),
550            }
551        }
552    }
553
554    /// Extend the selection between and including `from` and `to` in a certain direction
555    /// # Errors
556    /// Errors on failure to extend selection in direction
557    pub fn extend_selection_dir(
558        &mut self,
559        from: &TreeItem,
560        to: &TreeItem,
561        direction_key: Key,
562        val: TreeItemSelect,
563        visible: bool,
564    ) -> Result<(), FltkError> {
565        if from.inner.is_null() || to.inner.is_null() {
566            return Err(FltkError::Internal(FltkErrorKind::FailedOperation));
567        }
568        unsafe {
569            match Fl_Tree_extend_selection_dir(
570                self.inner.widget() as _,
571                from.inner,
572                to.inner,
573                direction_key.bits(),
574                val as i32,
575                i32::from(visible),
576            ) {
577                0 => Ok(()),
578                _ => Err(FltkError::Internal(FltkErrorKind::FailedOperation)),
579            }
580        }
581    }
582
583    /// Extend the selection between and including `from` and `to`
584    /// # Errors
585    /// Errors on failure to extend selection
586    pub fn extend_selection(
587        &mut self,
588        from: &TreeItem,
589        to: &TreeItem,
590        val: TreeItemSelect,
591        visible: bool,
592    ) -> Result<(), FltkError> {
593        if from.inner.is_null() || to.inner.is_null() {
594            return Err(FltkError::Internal(FltkErrorKind::FailedOperation));
595        }
596        unsafe {
597            match Fl_Tree_extend_selection(
598                self.inner.widget() as _,
599                from.inner,
600                to.inner,
601                val as i32,
602                i32::from(visible),
603            ) {
604                0 => Ok(()),
605                _ => Err(FltkError::Internal(FltkErrorKind::FailedOperation)),
606            }
607        }
608    }
609
610    /// Set the item that currently should have keyboard focus
611    pub fn set_item_focus(&mut self, item: &TreeItem) {
612        assert!(!item.inner.is_null());
613        unsafe { Fl_Tree_set_item_focus(self.inner.widget() as _, item.inner) }
614    }
615
616    /// Get the item that currently has keyboard focus
617    pub fn get_item_focus(&self) -> Option<TreeItem> {
618        unsafe { TreeItem::from_raw(Fl_Tree_get_item_focus(self.inner.widget() as _)) }
619    }
620
621    /// Returns whether an item is selected
622    pub fn is_selected(&self, path: &str) -> bool {
623        let path = CString::safe_new(path);
624        unsafe {
625            Fl_Tree_is_selected(self.inner.widget() as _, path.as_ptr() as *mut raw::c_char) != 0
626        }
627    }
628
629    /// Gets the items' label font
630    pub fn item_label_font(&self) -> Font {
631        unsafe { mem::transmute(Fl_Tree_item_labelfont(self.inner.widget() as _)) }
632    }
633
634    /// Sets the items' label font
635    pub fn set_item_label_font(&mut self, val: Font) {
636        unsafe { Fl_Tree_set_item_labelfont(self.inner.widget() as _, val.bits()) }
637    }
638
639    /// Gets the items' label size
640    pub fn item_label_size(&self) -> i32 {
641        unsafe { Fl_Tree_item_labelsize(self.inner.widget() as _) }
642    }
643
644    /// Sets the items' label size
645    pub fn set_item_label_size(&mut self, val: i32) {
646        let val = if val < 1 { 1 } else { val };
647        unsafe { Fl_Tree_set_item_labelsize(self.inner.widget() as _, val) }
648    }
649
650    /// Gets the items' foreground color
651    pub fn item_label_fgcolor(&self) -> Color {
652        unsafe { mem::transmute(Fl_Tree_item_labelfgcolor(self.inner.widget() as _)) }
653    }
654
655    /// Sets the items' foreground color
656    pub fn set_item_label_fgcolor(&mut self, val: Color) {
657        unsafe { Fl_Tree_set_item_labelfgcolor(self.inner.widget() as _, val.bits()) }
658    }
659
660    /// Gets the items' background color
661    pub fn item_label_bgcolor(&self) -> Color {
662        unsafe { mem::transmute(Fl_Tree_item_labelbgcolor(self.inner.widget() as _)) }
663    }
664
665    /// Sets the items' foreground color
666    pub fn set_item_label_bgcolor(&mut self, val: Color) {
667        unsafe { Fl_Tree_set_item_labelbgcolor(self.inner.widget() as _, val.bits()) }
668    }
669
670    /// Gets the items' connector color
671    pub fn connector_color(&self) -> Color {
672        unsafe { mem::transmute(Fl_Tree_connectorcolor(self.inner.widget() as _)) }
673    }
674
675    /// Sets the items' foreground color
676    pub fn set_connector_color(&mut self, val: Color) {
677        unsafe { Fl_Tree_set_connectorcolor(self.inner.widget() as _, val.bits()) }
678    }
679
680    /// Gets the left margin
681    pub fn margin_left(&self) -> i32 {
682        unsafe { Fl_Tree_marginleft(self.inner.widget() as _) }
683    }
684
685    /// Sets the left margin
686    pub fn set_margin_left(&mut self, val: i32) {
687        unsafe { Fl_Tree_set_marginleft(self.inner.widget() as _, val) }
688    }
689
690    /// Gets the top margin
691    pub fn margin_top(&self) -> i32 {
692        unsafe { Fl_Tree_margintop(self.inner.widget() as _) }
693    }
694
695    /// Sets the top margin
696    pub fn set_margin_top(&mut self, val: i32) {
697        unsafe { Fl_Tree_set_margintop(self.inner.widget() as _, val) }
698    }
699
700    /// Gets the bottom margin
701    pub fn margin_bottom(&self) -> i32 {
702        unsafe { Fl_Tree_marginbottom(self.inner.widget() as _) }
703    }
704
705    /// Sets the bottom margin
706    pub fn set_margin_bottom(&mut self, val: i32) {
707        unsafe { Fl_Tree_set_marginbottom(self.inner.widget() as _, val) }
708    }
709
710    /// Gets the line spacing
711    pub fn line_spacing(&self) -> i32 {
712        unsafe { Fl_Tree_linespacing(self.inner.widget() as _) }
713    }
714
715    /// Sets the line spacing
716    pub fn set_line_spacing(&mut self, val: i32) {
717        unsafe { Fl_Tree_set_linespacing(self.inner.widget() as _, val) }
718    }
719
720    /// Gets the open child bottom margin
721    pub fn open_child_margin_bottom(&self) -> i32 {
722        unsafe { Fl_Tree_openchild_marginbottom(self.inner.widget() as _) }
723    }
724
725    /// Sets the open child bottom margin
726    pub fn set_open_child_margin_bottom(&mut self, val: i32) {
727        unsafe { Fl_Tree_set_openchild_marginbottom(self.inner.widget() as _, val) }
728    }
729
730    /// Gets the user icon left margin
731    pub fn user_icon_margin_left(&self) -> i32 {
732        unsafe { Fl_Tree_usericonmarginleft(self.inner.widget() as _) }
733    }
734
735    /// Sets the user icon left margin
736    pub fn set_user_icon_margin_left(&mut self, val: i32) {
737        unsafe { Fl_Tree_set_usericonmarginleft(self.inner.widget() as _, val) }
738    }
739
740    /// Gets the label's left margin
741    pub fn label_margin_left(&self) -> i32 {
742        unsafe { Fl_Tree_labelmarginleft(self.inner.widget() as _) }
743    }
744
745    /// Sets the label's left margin
746    pub fn set_label_margin_left(&mut self, val: i32) {
747        unsafe { Fl_Tree_set_labelmarginleft(self.inner.widget() as _, val) }
748    }
749
750    /// Gets the widget's left margin
751    pub fn widget_margin_left(&self) -> i32 {
752        unsafe { Fl_Tree_widgetmarginleft(self.inner.widget() as _) }
753    }
754
755    /// Sets the widget's left margin
756    pub fn set_widget_margin_left(&mut self, val: i32) {
757        unsafe { Fl_Tree_set_widgetmarginleft(self.inner.widget() as _, val) }
758    }
759
760    /// Gets the connector's width
761    pub fn connector_width(&self) -> i32 {
762        unsafe { Fl_Tree_connectorwidth(self.inner.widget() as _) }
763    }
764
765    /// Sets the connector's width
766    pub fn set_connector_width(&mut self, val: i32) {
767        unsafe { Fl_Tree_set_connectorwidth(self.inner.widget() as _, val) }
768    }
769
770    /// Gets the user icon
771    pub fn user_icon(&self) -> Option<Box<dyn ImageExt>> {
772        unsafe {
773            let image_ptr = Fl_Tree_usericon(self.inner.widget() as _);
774            if image_ptr.is_null() {
775                None
776            } else {
777                Some(Box::new(Image::from_image_ptr(
778                    image_ptr as *mut fltk_sys::image::Fl_Image,
779                )))
780            }
781        }
782    }
783
784    /// Sets the user icon
785    pub fn set_user_icon<Img: ImageExt>(&mut self, image: Option<Img>) {
786        if let Some(image) = image {
787            assert!(!image.was_deleted());
788            unsafe {
789                Fl_Tree_set_usericon(self.inner.widget() as _, image.as_image_ptr() as *mut _);
790            }
791        } else {
792            unsafe {
793                Fl_Tree_set_usericon(
794                    self.inner.widget() as _,
795                    std::ptr::null_mut::<raw::c_void>(),
796                );
797            }
798        }
799    }
800
801    /// Gets the open icon
802    pub fn open_icon(&self) -> Option<Box<dyn ImageExt>> {
803        unsafe {
804            let image_ptr = Fl_Tree_openicon(self.inner.widget() as _);
805            if image_ptr.is_null() {
806                None
807            } else {
808                Some(Box::new(Image::from_image_ptr(
809                    image_ptr as *mut fltk_sys::image::Fl_Image,
810                )))
811            }
812        }
813    }
814
815    /// Sets the open icon
816    pub fn set_open_icon<Img: ImageExt>(&mut self, image: Option<Img>) {
817        if let Some(image) = image {
818            assert!(!image.was_deleted());
819            unsafe {
820                Fl_Tree_set_openicon(self.inner.widget() as _, image.as_image_ptr() as *mut _);
821            }
822        } else {
823            unsafe {
824                Fl_Tree_set_openicon(
825                    self.inner.widget() as _,
826                    std::ptr::null_mut::<raw::c_void>(),
827                );
828            }
829        }
830    }
831
832    /// Gets the close icon
833    pub fn close_icon(&self) -> Option<Box<dyn ImageExt>> {
834        unsafe {
835            let image_ptr = Fl_Tree_closeicon(self.inner.widget() as _);
836            if image_ptr.is_null() {
837                None
838            } else {
839                Some(Box::new(Image::from_image_ptr(
840                    image_ptr as *mut fltk_sys::image::Fl_Image,
841                )))
842            }
843        }
844    }
845
846    /// Sets the close icon
847    pub fn set_close_icon<Img: ImageExt>(&mut self, image: Option<Img>) {
848        if let Some(image) = image {
849            assert!(!image.was_deleted());
850            unsafe {
851                Fl_Tree_set_closeicon(self.inner.widget() as _, image.as_image_ptr() as *mut _);
852            }
853        } else {
854            unsafe {
855                Fl_Tree_set_closeicon(
856                    self.inner.widget() as _,
857                    std::ptr::null_mut::<raw::c_void>(),
858                );
859            }
860        }
861    }
862
863    /// Returns true if the collapse icon is enabled, false if not.
864    pub fn show_collapse(&self) -> bool {
865        unsafe { Fl_Tree_showcollapse(self.inner.widget() as _) != 0 }
866    }
867
868    /// Sets whether the collapse icon is enabled
869    pub fn set_show_collapse(&mut self, flag: bool) {
870        unsafe { Fl_Tree_set_showcollapse(self.inner.widget() as _, i32::from(flag)) }
871    }
872
873    /// Returns whether the root is shown
874    pub fn show_root(&self) -> bool {
875        unsafe { Fl_Tree_showroot(self.inner.widget() as _) != 0 }
876    }
877
878    /// Sets whether the root is shown
879    pub fn set_show_root(&mut self, flag: bool) {
880        unsafe { Fl_Tree_set_showroot(self.inner.widget() as _, i32::from(flag)) }
881    }
882
883    /// Gets the connector style
884    pub fn connector_style(&self) -> TreeConnectorStyle {
885        unsafe { mem::transmute(Fl_Tree_connectorstyle(self.inner.widget() as _)) }
886    }
887
888    /// Sets the connector style
889    pub fn set_connector_style(&mut self, val: TreeConnectorStyle) {
890        unsafe { Fl_Tree_set_connectorstyle(self.inner.widget() as _, val as i32) }
891    }
892
893    /// Gets the sort order
894    pub fn sort_order(&self) -> TreeSort {
895        unsafe { mem::transmute(Fl_Tree_sortorder(self.inner.widget() as _)) }
896    }
897
898    /// Sets the sort order
899    pub fn set_sort_order(&mut self, val: TreeSort) {
900        unsafe { Fl_Tree_set_sortorder(self.inner.widget() as _, val as i32) }
901    }
902
903    /// Gets the select frame
904    pub fn select_frame(&self) -> FrameType {
905        unsafe { FrameType::from_i32(Fl_Tree_selectbox(self.inner.widget() as _)) }
906    }
907
908    /// Sets the select frame
909    pub fn set_select_frame(&mut self, val: FrameType) {
910        unsafe { Fl_Tree_set_selectbox(self.inner.widget() as _, val.as_i32()) }
911    }
912
913    /// Gets the Tree select mode
914    pub fn select_mode(&self) -> TreeSelect {
915        unsafe { mem::transmute(Fl_Tree_selectmode(self.inner.widget() as _)) }
916    }
917
918    /// Sets the Tree select mode
919    pub fn set_select_mode(&mut self, val: TreeSelect) {
920        unsafe { Fl_Tree_set_selectmode(self.inner.widget() as _, val as i32) }
921    }
922
923    /// Gets the Tree item's reselect mode
924    pub fn item_reselect_mode(&self) -> TreeItemReselectMode {
925        unsafe { mem::transmute(Fl_Tree_item_reselect_mode(self.inner.widget() as _)) }
926    }
927
928    /// Sets the Tree item's reselect mode
929    pub fn set_item_reselect_mode(&mut self, mode: TreeItemReselectMode) {
930        unsafe { Fl_Tree_set_item_reselect_mode(self.inner.widget() as _, mode as i32) }
931    }
932
933    /// Gets the Tree item's draw mode
934    pub fn item_draw_mode(&self) -> TreeItemDrawMode {
935        unsafe { mem::transmute(Fl_Tree_item_draw_mode(self.inner.widget() as _)) }
936    }
937
938    /// Sets the Tree item's draw mode
939    pub fn set_item_draw_mode(&mut self, mode: TreeItemDrawMode) {
940        unsafe { Fl_Tree_set_item_draw_mode(self.inner.widget() as _, mode as i32) }
941    }
942
943    /// Recalculate widget dimensions and scrollbar visibility, normally done automatically
944    pub fn calc_dimensions(&mut self) {
945        unsafe { Fl_Tree_calc_dimensions(self.inner.widget() as _) }
946    }
947
948    /// Recalculates the tree's sizes and scrollbar visibility, normally done automatically
949    pub fn calc_tree(&mut self) {
950        unsafe { Fl_Tree_calc_tree(self.inner.widget() as _) }
951    }
952
953    /// Recalculates the tree's sizes and scrollbar visibility, normally done automatically
954    pub fn recalc_tree(&mut self) {
955        unsafe { Fl_Tree_recalc_tree(self.inner.widget() as _) }
956    }
957
958    /// Returns whether an item is displayed
959    pub fn displayed(&mut self, item: &TreeItem) -> bool {
960        assert!(!item.inner.is_null());
961        unsafe { Fl_Tree_displayed(self.inner.widget() as _, item.inner) != 0 }
962    }
963
964    /// Shows an item
965    pub fn show_item(&mut self, item: &TreeItem, y_offset: i32) {
966        assert!(!item.inner.is_null());
967        unsafe { Fl_Tree_show_item(self.inner.widget() as _, item.inner, y_offset) }
968    }
969
970    /// Adjust the vertical scrollbar so that `item` is visible
971    pub fn show_item_top(&mut self, item: &TreeItem) {
972        assert!(!item.inner.is_null());
973        unsafe { Fl_Tree_show_item_top(self.inner.widget() as _, item.inner) }
974    }
975
976    /// Adjust the vertical scrollbar so that `item` is in the middle of the display
977    pub fn show_item_middle(&mut self, item: &TreeItem) {
978        assert!(!item.inner.is_null());
979        unsafe { Fl_Tree_show_item_middle(self.inner.widget() as _, item.inner) }
980    }
981
982    /// Adjust the vertical scrollbar so that the is at the bottom of the display.
983    pub fn show_item_bottom(&mut self, item: &TreeItem) {
984        assert!(!item.inner.is_null());
985        unsafe { Fl_Tree_show_item_bottom(self.inner.widget() as _, item.inner) }
986    }
987
988    /// Display the item
989    pub fn display(&mut self, item: &TreeItem) {
990        assert!(!item.inner.is_null());
991        unsafe { Fl_Tree_display(self.inner.widget() as _, item.inner) }
992    }
993
994    /// Gets the vertical position of the item
995    pub fn vposition(&self) -> i32 {
996        unsafe { Fl_Tree_vposition(self.inner.widget() as _) }
997    }
998
999    /// Sets the vertical position of the item
1000    pub fn set_vposition(&mut self, pos: i32) {
1001        unsafe { Fl_Tree_set_vposition(self.inner.widget() as _, pos) }
1002    }
1003
1004    /// Gets the horizontal position of the item
1005    pub fn hposition(&self) -> i32 {
1006        unsafe { Fl_Tree_hposition(self.inner.widget() as _) }
1007    }
1008
1009    /// Sets the horizontal position of the item
1010    pub fn set_hposition(&mut self, pos: i32) {
1011        unsafe { Fl_Tree_set_hposition(self.inner.widget() as _, pos) }
1012    }
1013
1014    /// Returns whether the widget is a scrollbar
1015    pub fn is_scrollbar<W: WidgetExt>(&mut self, w: &W) -> bool {
1016        unsafe {
1017            Fl_Tree_is_scrollbar(
1018                self.inner.widget() as _,
1019                w.as_widget_ptr() as *mut Fl_Widget,
1020            ) != 0
1021        }
1022    }
1023
1024    /// Gets the scrollbar size
1025    pub fn scrollbar_size(&self) -> i32 {
1026        unsafe { Fl_Tree_scrollbar_size(self.inner.widget() as _) }
1027    }
1028
1029    /// Sets the scrollbar size
1030    pub fn set_scrollbar_size(&mut self, sz: i32) {
1031        unsafe { Fl_Tree_set_scrollbar_size(self.inner.widget() as _, sz) }
1032    }
1033
1034    /// Returns whether vertical scrolling is visible
1035    pub fn is_vscroll_visible(&self) -> bool {
1036        unsafe { Fl_Tree_is_vscroll_visible(self.inner.widget() as _) != 0 }
1037    }
1038
1039    /// Returns whether horizontal scrolling is visible
1040    pub fn is_hscroll_visible(&self) -> bool {
1041        unsafe { Fl_Tree_is_hscroll_visible(self.inner.widget() as _) != 0 }
1042    }
1043
1044    /// Set the callback item
1045    pub fn set_callback_item(&mut self, item: &TreeItem) {
1046        assert!(!item.inner.is_null());
1047        unsafe { Fl_Tree_set_callback_item(self.inner.widget() as _, item.inner) }
1048    }
1049
1050    /// Get the callback item
1051    pub fn callback_item(&self) -> Option<TreeItem> {
1052        unsafe { TreeItem::from_raw(Fl_Tree_callback_item(self.inner.widget() as _)) }
1053    }
1054
1055    /// Set the callback reason
1056    pub fn set_callback_reason(&mut self, reason: TreeReason) {
1057        unsafe { Fl_Tree_set_callback_reason(self.inner.widget() as _, reason as i32) }
1058    }
1059
1060    /// Get the callback reason
1061    pub fn callback_reason(&self) -> TreeReason {
1062        unsafe { mem::transmute(Fl_Tree_callback_reason(self.inner.widget() as _)) }
1063    }
1064
1065    /// Get an item's pathname
1066    pub fn item_pathname(&self, item: &TreeItem) -> Result<String, FltkError> {
1067        let mut temp = vec![0u8; 256];
1068        unsafe {
1069            let ret = Fl_Tree_item_pathname(
1070                self.inner.widget() as _,
1071                temp.as_mut_ptr() as _,
1072                256,
1073                item.inner,
1074            );
1075            if ret == 0 {
1076                if let Some(pos) = temp.iter().position(|x| *x == 0) {
1077                    temp = temp.split_at(pos).0.to_vec();
1078                }
1079                Ok(String::from_utf8_lossy(&temp).to_string())
1080            } else {
1081                Err(FltkError::Internal(FltkErrorKind::FailedOperation))
1082            }
1083        }
1084    }
1085}
1086
1087impl IntoIterator for Tree {
1088    type Item = TreeItem;
1089    type IntoIter = std::vec::IntoIter<Self::Item>;
1090
1091    fn into_iter(self) -> Self::IntoIter {
1092        self.get_items().map_or_else(
1093            || Vec::with_capacity(0).into_iter(),
1094            std::iter::IntoIterator::into_iter,
1095        )
1096    }
1097}
1098
1099impl TreeItem {
1100    /// Create a `TreeItem` from a raw pointer
1101    /// # Safety
1102    /// The pointer must be valid
1103    pub unsafe fn from_raw(ptr: *mut Fl_Tree_Item) -> Option<TreeItem> {
1104        unsafe {
1105            if ptr.is_null() {
1106                None
1107            } else {
1108                let w = Fl_Tree_Item_tree(ptr) as *mut Fl_Tree;
1109                let inner = crate::widget::WidgetTracker::new(w as _);
1110                let tree = Tree {
1111                    inner,
1112                    is_derived: false,
1113                };
1114                let parent = Fl_Tree_Item_parent(ptr);
1115                let is_root = Fl_Tree_Item_is_root(ptr) != 0;
1116                Some(TreeItem {
1117                    inner: ptr,
1118                    parent,
1119                    tree,
1120                    is_root,
1121                    is_derived: false,
1122                })
1123            }
1124        }
1125    }
1126
1127    /// Creates a new `TreeItem`
1128    pub fn new(tree: &Tree, label: &str) -> Self {
1129        let label = CString::safe_new(label);
1130        unsafe {
1131            let ptr = Fl_Tree_Item_new(tree.inner.widget() as _, label.as_ptr());
1132            assert!(!ptr.is_null());
1133            Self {
1134                inner: ptr,
1135                parent: ptr,
1136                tree: tree.clone(),
1137                is_root: true,
1138                is_derived: true,
1139            }
1140        }
1141    }
1142
1143    /**
1144    Overrides the `draw_item_content` method
1145    Example usage:
1146       ```rust,no_run
1147       use fltk::{draw, enums::*, tree};
1148       let mut tree = tree::Tree::default();
1149       let mut item = tree::TreeItem::new(&tree, "Hello");
1150       item.draw_item_content(|item, render| {
1151           // Our item's dimensions + text content
1152           let x = item.label_x();
1153           let y = item.label_y();
1154           let w = item.label_w();
1155           let h = item.label_h();
1156           let txt = if let Some(txt) = item.label() {
1157               txt
1158           } else {
1159               String::new()
1160           };
1161           if render {
1162               // Draw bg -- a filled rectangle
1163               draw::draw_rect_fill(x, y, w, h, item.label_bgcolor());
1164               // Draw label
1165               draw::set_font(Font::Helvetica, 14);
1166               draw::set_draw_color(Color::Foreground); // use recommended fg color
1167               draw::draw_text_boxed(&txt, x, y, w, h, Align::Left); // draw the item's label
1168           }
1169           // Rendered or not, we must calculate content's max X position
1170           let (lw, _) = draw::measure(&txt, true); // get width of label text
1171           return x + lw; // return X + label width
1172       });
1173       // Add our custom item to a path
1174       let _third = tree.add_item("first/second/thrid", &item).unwrap();
1175       ```
1176    */
1177    pub fn draw_item_content<F: FnMut(&mut Self, bool) -> i32>(&mut self, cb: F) {
1178        assert!(self.is_derived);
1179        unsafe {
1180            unsafe extern "C" fn shim(
1181                item: *mut Fl_Tree_Item,
1182                render: i32,
1183                data: *mut raw::c_void,
1184            ) -> i32 {
1185                unsafe {
1186                    let mut item = TreeItem::from_raw(item).unwrap();
1187                    let a = data as *mut Box<dyn FnMut(&mut TreeItem, bool) -> i32>;
1188                    let f: &mut (dyn FnMut(&mut TreeItem, bool) -> i32) = &mut **a;
1189                    std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
1190                        f(&mut item, render != 0)
1191                    }))
1192                    .unwrap_or_default()
1193                }
1194            }
1195            #[allow(clippy::type_complexity)]
1196            let a: *mut Box<dyn FnMut(&mut Self, bool) -> i32> =
1197                Box::into_raw(Box::new(Box::new(cb)));
1198            let data: *mut raw::c_void = a as *mut raw::c_void;
1199            let callback: Option<
1200                unsafe extern "C" fn(
1201                    self_: *mut Fl_Tree_Item,
1202                    arg1: i32,
1203                    arg2: *mut raw::c_void,
1204                ) -> i32,
1205            > = Some(shim);
1206            Fl_Tree_Item_draw_item_content(self.inner, callback, data);
1207        }
1208    }
1209
1210    /// Set the internal data of the tree item
1211    /// # Warning
1212    /// This method doesn't store the type information of the passed data
1213    pub fn set_user_data<T: Clone + 'static>(&mut self, data: T) {
1214        unsafe {
1215            Fl_Tree_Item_set_user_data(self.inner, Box::into_raw(Box::from(data)) as _);
1216        }
1217    }
1218
1219    /// Get the stored data in the tree item
1220    /// # Safety
1221    /// Setting the user data doesn't store type information, as such it's on the developer to maintain the correct type
1222    pub unsafe fn user_data<T: Clone + 'static>(&self) -> Option<T> {
1223        unsafe {
1224            let ptr = Fl_Tree_Item_user_data(self.inner);
1225            if ptr.is_null() {
1226                None
1227            } else {
1228                let data = ptr as *const _ as *mut T;
1229                Some((*data).clone())
1230            }
1231        }
1232    }
1233
1234    /// Gets the x position
1235    pub fn x(&self) -> i32 {
1236        unsafe { Fl_Tree_Item_x(self.inner) }
1237    }
1238
1239    /// Gets the y position
1240    pub fn y(&self) -> i32 {
1241        unsafe { Fl_Tree_Item_y(self.inner) }
1242    }
1243
1244    /// Gets the width
1245    pub fn w(&self) -> i32 {
1246        unsafe { Fl_Tree_Item_w(self.inner) }
1247    }
1248
1249    /// Gets the height
1250    pub fn h(&self) -> i32 {
1251        unsafe { Fl_Tree_Item_h(self.inner) }
1252    }
1253
1254    /// Gets the label's x position
1255    pub fn label_x(&self) -> i32 {
1256        unsafe { Fl_Tree_Item_label_x(self.inner) }
1257    }
1258
1259    /// Gets the label's y position
1260    pub fn label_y(&self) -> i32 {
1261        unsafe { Fl_Tree_Item_label_y(self.inner) }
1262    }
1263
1264    /// Gets the label's width
1265    pub fn label_w(&self) -> i32 {
1266        unsafe { Fl_Tree_Item_label_w(self.inner) }
1267    }
1268
1269    /// Gets the label's height
1270    pub fn label_h(&self) -> i32 {
1271        unsafe { Fl_Tree_Item_label_h(self.inner) }
1272    }
1273
1274    /// Shows the tree item
1275    pub fn show_self(&self, indent: &str) {
1276        let indent = CString::safe_new(indent);
1277        unsafe { Fl_Tree_Item_show_self(self.inner, indent.as_ptr() as *mut raw::c_char) }
1278    }
1279
1280    /// Sets the label of the tree item
1281    pub fn set_label(&mut self, val: &str) {
1282        let val = CString::safe_new(val);
1283        unsafe { Fl_Tree_set_Item_label(self.inner, val.as_ptr() as *mut raw::c_char) }
1284    }
1285
1286    /// Gets the label of the tree item
1287    pub fn label(&self) -> Option<String> {
1288        unsafe {
1289            let x = Fl_Tree_Item_label(self.inner);
1290            if x.is_null() {
1291                None
1292            } else {
1293                Some(
1294                    CStr::from_ptr(x as *mut raw::c_char)
1295                        .to_string_lossy()
1296                        .to_string(),
1297                )
1298            }
1299        }
1300    }
1301
1302    /// Sets the label's font
1303    pub fn set_label_font(&mut self, val: Font) {
1304        unsafe { Fl_Tree_Item_set_labelfont(self.inner, val.bits()) }
1305    }
1306
1307    /// Gets the label's font
1308    pub fn label_font(&self) -> Font {
1309        unsafe { mem::transmute(Fl_Tree_Item_labelfont(self.inner)) }
1310    }
1311
1312    /// Sets the label's size
1313    pub fn set_label_size(&mut self, sz: i32) {
1314        let sz = if sz < 1 { 1 } else { sz };
1315        unsafe { Fl_Tree_Item_set_labelsize(self.inner, sz) }
1316    }
1317
1318    /// Gets the label's size
1319    pub fn label_size(&self) -> i32 {
1320        unsafe { Fl_Tree_Item_labelsize(self.inner) }
1321    }
1322
1323    /// Sets the label's foreground color
1324    pub fn set_label_fgcolor(&mut self, val: Color) {
1325        unsafe { Fl_Tree_Item_set_labelfgcolor(self.inner, val.bits()) }
1326    }
1327
1328    /// Gets the label's foreground color
1329    pub fn label_fgcolor(&self) -> Color {
1330        unsafe { mem::transmute(Fl_Tree_Item_labelfgcolor(self.inner)) }
1331    }
1332
1333    /// Sets the label's color
1334    pub fn set_label_color(&mut self, val: Color) {
1335        unsafe { Fl_Tree_Item_set_labelcolor(self.inner, val.bits()) }
1336    }
1337
1338    /// Gets the label's color
1339    pub fn label_color(&self) -> Color {
1340        unsafe { mem::transmute(Fl_Tree_Item_labelcolor(self.inner)) }
1341    }
1342
1343    /// Sets the label's background color
1344    pub fn set_label_bgcolor(&mut self, val: Color) {
1345        unsafe { Fl_Tree_Item_set_labelbgcolor(self.inner, val.bits()) }
1346    }
1347
1348    /// Gets the label's foreground color
1349    pub fn label_bgcolor(&self) -> Color {
1350        unsafe { mem::transmute(Fl_Tree_Item_labelbgcolor(self.inner)) }
1351    }
1352
1353    /// Sets the item's associated widget
1354    pub fn set_widget<W: WidgetExt>(&mut self, val: &W) {
1355        unsafe { Fl_Tree_Item_set_widget(self.inner, val.as_widget_ptr() as *mut Fl_Widget) }
1356    }
1357
1358    /// Gets the item's associated widget
1359    pub fn widget(&self) -> Option<impl WidgetExt> {
1360        unsafe {
1361            let ptr = Fl_Tree_Item_widget(self.inner) as *mut fltk_sys::widget::Fl_Widget;
1362            if ptr.is_null() {
1363                None
1364            } else {
1365                Some(Widget::from_widget_ptr(ptr))
1366            }
1367        }
1368    }
1369
1370    /// Gets the children count
1371    pub fn children(&self) -> i32 {
1372        unsafe { Fl_Tree_Item_children(self.inner) }
1373    }
1374
1375    /// Gets the child item at idx position
1376    pub fn child(&self, idx: i32) -> Option<TreeItem> {
1377        if idx < 0 || idx >= self.children() {
1378            return None;
1379        }
1380
1381        unsafe { TreeItem::from_raw(Fl_Tree_Item_child(self.inner, idx) as *mut Fl_Tree_Item) }
1382    }
1383
1384    /// Returns whether the item has children
1385    pub fn has_children(&self) -> bool {
1386        unsafe { Fl_Tree_Item_has_children(self.inner) != 0 }
1387    }
1388
1389    /// Find a child using its name, returns index result
1390    /// # Errors
1391    /// Errors on failure to find child
1392    pub fn find_child(&mut self, name: &str) -> Result<i32, FltkError> {
1393        let name = CString::safe_new(name);
1394        unsafe {
1395            let x = Fl_Tree_Item_find_child(self.inner, name.as_ptr());
1396            if x == -1 {
1397                Err(FltkError::Internal(FltkErrorKind::FailedOperation))
1398            } else {
1399                Ok(x)
1400            }
1401        }
1402    }
1403
1404    /// Remove child using its name
1405    /// # Errors
1406    /// Errors on failure to remove child
1407    pub fn remove_child(&mut self, new_label: &str) -> Result<(), FltkError> {
1408        let new_label = CString::safe_new(new_label);
1409        unsafe {
1410            match Fl_Tree_Item_remove_child(self.inner, new_label.as_ptr()) {
1411                0 => Ok(()),
1412                _ => Err(FltkError::Internal(FltkErrorKind::FailedOperation)),
1413            }
1414        }
1415    }
1416
1417    /// Remove all children
1418    pub fn clear_children(&mut self) {
1419        unsafe { Fl_Tree_Item_clear_children(self.inner) }
1420    }
1421
1422    /// Swap children a and b
1423    /// # Errors
1424    /// Errors on failure to swap children
1425    pub fn swap_children(&mut self, a: &TreeItem, b: &TreeItem) -> Result<(), FltkError> {
1426        assert!(!self.was_deleted() && !a.was_deleted() && !b.was_deleted());
1427        unsafe {
1428            match Fl_Tree_Item_swap_children(self.inner, a.inner, b.inner) {
1429                0 => Ok(()),
1430                _ => Err(FltkError::Internal(FltkErrorKind::FailedOperation)),
1431            }
1432        }
1433    }
1434
1435    /// Find child by name, returns option of the item
1436    pub fn find_child_item(&self, name: &str) -> Option<TreeItem> {
1437        let name = CString::safe_new(name);
1438        unsafe {
1439            TreeItem::from_raw(
1440                Fl_Tree_Item_find_child_item(self.inner, name.as_ptr()) as *mut Fl_Tree_Item
1441            )
1442        }
1443    }
1444
1445    /// Replace a tree item
1446    pub fn replace(&mut self, new_item: &TreeItem) -> Option<TreeItem> {
1447        assert!(!self.was_deleted() && !new_item.was_deleted());
1448        unsafe { TreeItem::from_raw(Fl_Tree_Item_replace(self.inner, new_item.inner)) }
1449    }
1450
1451    /// Replace a child
1452    pub fn replace_child(&mut self, old_item: &TreeItem, new_item: &TreeItem) -> Option<TreeItem> {
1453        assert!(!self.was_deleted() && !old_item.was_deleted() && !new_item.was_deleted());
1454        unsafe {
1455            TreeItem::from_raw(Fl_Tree_Item_replace_child(
1456                self.inner,
1457                old_item.inner,
1458                new_item.inner,
1459            ))
1460        }
1461    }
1462
1463    /// Deparent a child by index
1464    pub fn deparent(&mut self, index: i32) -> Option<TreeItem> {
1465        if index < 0 || index >= self.children() {
1466            return None;
1467        }
1468        unsafe { TreeItem::from_raw(Fl_Tree_Item_deparent(self.inner, index)) }
1469    }
1470
1471    /// Reparent a child by index
1472    /// # Errors
1473    /// Errors on failure to move item   
1474    pub fn reparent(&mut self, new_child: &TreeItem, index: i32) -> Result<(), FltkError> {
1475        assert!(!self.was_deleted() && !new_child.was_deleted());
1476        if index < 0 || index >= self.children() {
1477            return Err(FltkError::Internal(FltkErrorKind::FailedOperation));
1478        }
1479        unsafe {
1480            match Fl_Tree_Item_reparent(self.inner, new_child.inner, index) {
1481                0 => Ok(()),
1482                _ => Err(FltkError::Internal(FltkErrorKind::FailedOperation)),
1483            }
1484        }
1485    }
1486
1487    /// Move the item 'from' to sibling position of 'to'.
1488    /// # Errors
1489    /// Errors on failure to move item   
1490    pub fn move_item(&mut self, to: i32, from: i32) -> Result<(), FltkError> {
1491        unsafe {
1492            match Fl_Tree_Item_move(self.inner, to, from) {
1493                0 => Ok(()),
1494                _ => Err(FltkError::Internal(FltkErrorKind::FailedOperation)),
1495            }
1496        }
1497    }
1498
1499    /// Move the current item above the specified `item`
1500    /// # Errors
1501    /// Errors on failure to move item   
1502    pub fn move_above(&mut self, item: &TreeItem) -> Result<(), FltkError> {
1503        assert!(!self.was_deleted() && !item.was_deleted());
1504        unsafe {
1505            match Fl_Tree_Item_move_above(self.inner, item.inner) {
1506                0 => Ok(()),
1507                _ => Err(FltkError::Internal(FltkErrorKind::FailedOperation)),
1508            }
1509        }
1510    }
1511
1512    /// Move the current item below the specified `item`
1513    /// # Errors
1514    /// Errors on failure to move item   
1515    pub fn move_below(&mut self, item: &TreeItem) -> Result<(), FltkError> {
1516        assert!(!self.was_deleted() && !item.was_deleted());
1517        unsafe {
1518            match Fl_Tree_Item_move_below(self.inner, item.inner) {
1519                0 => Ok(()),
1520                _ => Err(FltkError::Internal(FltkErrorKind::FailedOperation)),
1521            }
1522        }
1523    }
1524
1525    /// Parent the current item as a child of the specified `item`.
1526    /// # Errors
1527    /// Errors on failure to move item    
1528    pub fn move_into(&mut self, item: &TreeItem, pos: i32) -> Result<(), FltkError> {
1529        assert!(!self.was_deleted() && !item.was_deleted());
1530        unsafe {
1531            match Fl_Tree_Item_move_into(self.inner, item.inner, pos) {
1532                0 => Ok(()),
1533                _ => Err(FltkError::Internal(FltkErrorKind::FailedOperation)),
1534            }
1535        }
1536    }
1537
1538    /// Gets the depth of the item
1539    pub fn depth(&self) -> i32 {
1540        unsafe { Fl_Tree_Item_depth(self.inner) }
1541    }
1542
1543    /// Gets the previous item
1544    pub fn prev(&self) -> Option<TreeItem> {
1545        unsafe { TreeItem::from_raw(Fl_Tree_Item_prev(self.inner)) }
1546    }
1547
1548    /// Gets the next item
1549    pub fn next(&self) -> Option<TreeItem> {
1550        unsafe { TreeItem::from_raw(Fl_Tree_Item_next(self.inner)) }
1551    }
1552
1553    /// Gets the next sibling
1554    pub fn next_sibling(&self) -> Option<TreeItem> {
1555        unsafe { TreeItem::from_raw(Fl_Tree_Item_next_sibling(self.inner)) }
1556    }
1557
1558    /// Gets the previous sibling
1559    pub fn prev_sibling(&self) -> Option<TreeItem> {
1560        unsafe { TreeItem::from_raw(Fl_Tree_Item_prev_sibling(self.inner)) }
1561    }
1562
1563    /// Update surrounding siblings
1564    pub fn update_prev_next(&mut self, index: i32) {
1565        unsafe { Fl_Tree_Item_update_prev_next(self.inner, index) }
1566    }
1567
1568    /// Return the parent of the item
1569    pub fn parent(&self) -> Option<TreeItem> {
1570        unsafe { TreeItem::from_raw(Fl_Tree_Item_parent(self.inner) as *mut Fl_Tree_Item) }
1571    }
1572
1573    /// Set the parent of the item
1574    pub fn set_parent(&mut self, val: &TreeItem) {
1575        unsafe { Fl_Tree_Item_set_parent(self.inner, val.inner) }
1576    }
1577
1578    /// Return the tree of the item
1579    pub fn tree(&self) -> Option<Tree> {
1580        unsafe { Tree::from_raw(Fl_Tree_Item_tree(self.inner) as *mut Fl_Tree) }
1581    }
1582
1583    /// Open the item exposing all children
1584    pub fn open(&mut self) {
1585        unsafe { Fl_Tree_Item_open(self.inner) }
1586    }
1587
1588    /// Close the item hiding all children
1589    pub fn close(&mut self) {
1590        unsafe { Fl_Tree_Item_close(self.inner) }
1591    }
1592
1593    /// Returns whether an item is open
1594    pub fn is_open(&self) -> bool {
1595        unsafe { Fl_Tree_Item_is_open(self.inner) != 0 }
1596    }
1597
1598    /// Returns whether an item is closed
1599    pub fn is_close(&self) -> bool {
1600        unsafe { Fl_Tree_Item_is_close(self.inner) != 0 }
1601    }
1602
1603    /// Toggle the open state of the item
1604    pub fn open_toggle(&mut self) {
1605        unsafe { Fl_Tree_Item_open_toggle(self.inner) }
1606    }
1607
1608    /// Select an item at index
1609    pub fn select(&mut self, index: i32) {
1610        unsafe { Fl_Tree_Item_select(self.inner, index) }
1611    }
1612
1613    /// Toggle the select state of an item
1614    pub fn select_toggle(&mut self) {
1615        unsafe { Fl_Tree_Item_select_toggle(self.inner) }
1616    }
1617
1618    /// Select all subitems, returns number of selected items
1619    pub fn select_all(&mut self) -> i32 {
1620        unsafe { Fl_Tree_Item_select_all(self.inner) }
1621    }
1622
1623    /// Deselect an item
1624    pub fn deselect(&mut self) {
1625        unsafe { Fl_Tree_Item_deselect(self.inner) }
1626    }
1627
1628    /// Deselect all subitems
1629    pub fn deselect_all(&mut self) -> i32 {
1630        unsafe { Fl_Tree_Item_deselect_all(self.inner) }
1631    }
1632
1633    /// Returns whether an item is root
1634    pub fn is_root(&self) -> bool {
1635        unsafe { Fl_Tree_Item_is_root(self.inner) != 0 }
1636    }
1637
1638    /// Returns whether an item is visible
1639    pub fn is_visible(&self) -> bool {
1640        unsafe { Fl_Tree_Item_is_visible(self.inner) != 0 }
1641    }
1642
1643    /// Returns whether an item is active
1644    pub fn is_active(&self) -> bool {
1645        unsafe { Fl_Tree_Item_is_active(self.inner) != 0 }
1646    }
1647
1648    /// Returns whether an item is activated
1649    pub fn is_activated(&self) -> bool {
1650        unsafe { Fl_Tree_Item_is_activated(self.inner) != 0 }
1651    }
1652
1653    /// Deactivate an item
1654    pub fn deactivate(&mut self) {
1655        unsafe { Fl_Tree_Item_deactivate(self.inner) }
1656    }
1657
1658    /// Activate an item
1659    pub fn activate(&mut self, val: bool) {
1660        unsafe { Fl_Tree_Item_activate(self.inner, i32::from(val)) }
1661    }
1662
1663    /// Returns whether an item is selected
1664    pub fn is_selected(&self) -> bool {
1665        unsafe { Fl_Tree_Item_is_selected(self.inner) != 0 }
1666    }
1667
1668    /// Check if the tree item was deleted
1669    pub fn was_deleted(&self) -> bool {
1670        unsafe {
1671            let parent = self.parent;
1672            let is_root = self.is_root;
1673            if self.tree.was_deleted() {
1674                return true;
1675            }
1676            if is_root {
1677                self.tree.root().is_none() || self.inner.is_null()
1678            } else {
1679                Fl_Tree_Item_children(parent) == 0 || self.inner.is_null()
1680            }
1681        }
1682    }
1683
1684    /// Gets the user icon
1685    pub fn user_icon(&self) -> Option<Box<dyn ImageExt>> {
1686        unsafe {
1687            let image_ptr = Fl_Tree_Item_usericon(self.inner);
1688            if image_ptr.is_null() {
1689                None
1690            } else {
1691                Some(Box::new(Image::from_image_ptr(
1692                    image_ptr as *mut fltk_sys::image::Fl_Image,
1693                )))
1694            }
1695        }
1696    }
1697
1698    /// Sets the user icon
1699    pub fn set_user_icon<Img: ImageExt>(&mut self, image: Option<Img>) {
1700        if let Some(image) = image {
1701            assert!(!image.was_deleted());
1702            unsafe { Fl_Tree_Item_set_usericon(self.inner, image.as_image_ptr() as *mut _) }
1703        } else {
1704            unsafe { Fl_Tree_Item_set_usericon(self.inner, std::ptr::null_mut::<raw::c_void>()) }
1705        }
1706    }
1707
1708    /// Return the internal pointer of the tree item
1709    pub fn as_ptr(&self) -> *mut Fl_Tree_Item {
1710        self.inner
1711    }
1712}
1713
1714impl Iterator for TreeItem {
1715    type Item = TreeItem;
1716    /// Gets the next item
1717    fn next(&mut self) -> Option<Self::Item> {
1718        unsafe { TreeItem::from_raw(Fl_Tree_Item_next(self.inner)) }
1719    }
1720}
1721
1722impl TreeItemArray {
1723    /// Returns the `len()` of the array
1724    fn total(&self) -> i32 {
1725        unsafe { Fl_Tree_Item_Array_total(self.inner) }
1726    }
1727
1728    /// Swaps children
1729    #[allow(dead_code)]
1730    fn swap(&mut self, ax: i32, bx: i32) {
1731        unsafe { Fl_Tree_Item_Array_swap(self.inner, ax, bx) }
1732    }
1733
1734    /// Move items
1735    #[allow(dead_code)]
1736    fn move_item(&mut self, to: i32, from: i32) -> i32 {
1737        unsafe { Fl_Tree_Item_Array_move(self.inner, to, from) }
1738    }
1739
1740    /// Deparent item
1741    #[allow(dead_code)]
1742    fn deparent(&mut self, pos: i32) -> i32 {
1743        unsafe { Fl_Tree_Item_Array_deparent(self.inner, pos) }
1744    }
1745
1746    /// Reparent item
1747    #[allow(dead_code)]
1748    fn reparent(&mut self, item: &TreeItem, newparent: &TreeItem, pos: i32) -> i32 {
1749        unsafe { Fl_Tree_Item_Array_reparent(self.inner, item.inner, newparent.inner, pos) }
1750    }
1751
1752    /// Clears the array
1753    #[allow(dead_code)]
1754    fn clear(&mut self) {
1755        unsafe { Fl_Tree_Item_Array_clear(self.inner) }
1756    }
1757
1758    /// Adds an item to the array
1759    #[allow(dead_code)]
1760    fn add(&mut self, val: &TreeItem) {
1761        unsafe { Fl_Tree_Item_Array_add(self.inner, val.inner) }
1762    }
1763
1764    /// Insert an item to the array at pos
1765    #[allow(dead_code)]
1766    fn insert(&mut self, pos: i32, new_item: &TreeItem) {
1767        unsafe { Fl_Tree_Item_Array_insert(self.inner, pos, new_item.inner) }
1768    }
1769
1770    /// Replace an item at pos
1771    #[allow(dead_code)]
1772    fn replace(&mut self, pos: i32, new_item: &TreeItem) {
1773        unsafe { Fl_Tree_Item_Array_replace(self.inner, pos, new_item.inner) }
1774    }
1775
1776    /// Remove an item at pos
1777    #[allow(dead_code)]
1778    fn remove(&mut self, index: i32) {
1779        unsafe { Fl_Tree_Item_Array_remove(self.inner, index) }
1780    }
1781
1782    /// Remove an item
1783    #[allow(dead_code)]
1784    fn remove_item(&mut self, item: &TreeItem) -> i32 {
1785        unsafe { Fl_Tree_Item_Array_remove_item(self.inner, item.inner) }
1786    }
1787
1788    /// Gets the item at idx
1789    fn at(&self, idx: i32) -> Option<TreeItem> {
1790        unsafe { TreeItem::from_raw(Fl_Tree_Item_Array_at(self.inner, idx)) }
1791    }
1792
1793    /// Transforms the `TreeItemArray` into a vector
1794    fn into_vec(self) -> Option<Vec<TreeItem>> {
1795        let c = self.total();
1796        let mut v: Vec<TreeItem> = vec![];
1797        if c == 0 {
1798            None
1799        } else {
1800            for i in 0..c {
1801                let val = self.at(i);
1802                val.as_ref()?;
1803                v.push(val.unwrap());
1804            }
1805            Some(v)
1806        }
1807    }
1808}
1809
1810impl IntoIterator for TreeItemArray {
1811    type Item = TreeItem;
1812    type IntoIter = std::vec::IntoIter<Self::Item>;
1813
1814    fn into_iter(self) -> Self::IntoIter {
1815        self.into_vec().map_or_else(
1816            || Vec::with_capacity(0).into_iter(),
1817            std::iter::IntoIterator::into_iter,
1818        )
1819    }
1820}
1821
1822#[cfg(not(feature = "single-threaded"))]
1823unsafe impl Send for TreeItem {}
1824
1825#[cfg(not(feature = "single-threaded"))]
1826unsafe impl Sync for TreeItem {}
1827
1828impl PartialEq for TreeItem {
1829    fn eq(&self, other: &Self) -> bool {
1830        self.inner == other.inner
1831    }
1832}
1833
1834impl Eq for TreeItem {}
1835
1836impl Drop for TreeItemArray {
1837    fn drop(&mut self) {
1838        unsafe { Fl_Tree_Item_Array_delete(self.inner) }
1839    }
1840}