native_windows_gui/controls/
treeview_iterator.rs1use winapi::shared::windef::HWND;
2use winapi::um::commctrl::{HTREEITEM, TVGN_ROOT, TVGN_CHILD, TVGN_NEXT, TVGN_PARENT};
3use crate::{TreeView, TreeItem};
4use crate::win32::window_helper as wh;
5
6
7#[derive(Copy, Clone)]
8#[repr(usize)]
9enum NextAction {
10 Root = TVGN_ROOT,
11 Child = TVGN_CHILD,
12 Sibling = TVGN_NEXT,
13 Parent = TVGN_PARENT,
14}
15
16#[allow(unused)]
30pub struct TreeViewIterator<'a> {
31 tree_view: &'a TreeView,
32 tree_view_handle: HWND,
33 base_item: HTREEITEM,
34 current_item: HTREEITEM,
35 action: NextAction,
36}
37
38impl<'a> TreeViewIterator<'a> {
39
40 pub(crate) fn new(tree_view: &'a TreeView, current_item: HTREEITEM) -> TreeViewIterator {
42 let tree_view_handle = tree_view.handle.hwnd().unwrap();
43
44 let action = match current_item.is_null() {
45 true => NextAction::Root,
46 false => NextAction::Child
47 };
48
49 TreeViewIterator {
50 tree_view,
51 tree_view_handle,
52 base_item: current_item,
53 current_item,
54 action,
55 }
56 }
57
58}
59
60impl<'a> Iterator for TreeViewIterator<'a> {
61 type Item = TreeItem;
62
63 fn next(&mut self) -> Option<TreeItem> {
64 use NextAction::*;
65
66 let mut item: Option<TreeItem>;
67
68 loop {
69 item = next_item(self.tree_view_handle, self.action, self.current_item);
70 self.action = match (self.action, item.is_some()) {
71 (Root, _) => Child,
72 (Child, true) => Child,
73 (Child, false) => Sibling,
74 (Sibling, true) => Child,
75 (Sibling, false) => Parent,
76 (Parent, true) => {
77 self.current_item = item.as_ref().map(|i| i.handle).unwrap();
79
80 if self.base_item == self.current_item {
82 return None;
83 }
84
85 item = None;
87
88 Sibling
89 }
90 (Parent, false) => { return None; }
91 };
92
93 if item.is_some() {
94 self.current_item = item.as_ref().map(|i| i.handle).unwrap();
95 break;
96 }
97 }
98
99 item
100 }
101}
102
103
104fn next_item(tree: HWND, action: NextAction, handle: HTREEITEM) -> Option<TreeItem> {
105 use winapi::shared::minwindef::{WPARAM, LPARAM};
106 use winapi::um::commctrl::TVM_GETNEXTITEM;
107
108 let handle = wh::send_message(tree, TVM_GETNEXTITEM, action as WPARAM, handle as LPARAM) as HTREEITEM;
109 if handle.is_null() {
110 None
111 } else {
112 Some(TreeItem { handle })
113 }
114}