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