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