1#![allow(dead_code)]
2
3use fltk::{
4 app,
5 button::Button,
6 enums::Event,
7 frame::Frame,
8 prelude::*,
9 tree::{Tree, TreeItem, TreeReason, TreeSelect},
10 window::Window,
11};
12use std::cell::RefCell;
13use std::env;
14use std::rc::Rc;
15
16#[derive(PartialEq)]
17enum State {
18 MovingUp,
19 MovingDown,
20 Undefined,
21}
22
23fn verify_open_till_root(opt: &Option<fltk::tree::TreeItem>) -> bool {
24 let mut par = opt.clone();
25 loop {
26 match par.as_ref().unwrap().parent() {
27 Some(p) => {
28 if p.is_close() {
29 return false;
30 } else {
31 par = Some(p.clone());
32 }
33 }
34 None => return true,
35 }
36 }
37}
38
39struct TreeMouseFocus {
40 t_widget: fltk::tree::Tree,
41 previous_focus: Rc<RefCell<Option<TreeItem>>>,
42}
43
44impl TreeMouseFocus {
45 fn new(x: i32, y: i32, width: i32, height: i32, title: &'static str) -> Self {
46 let mut t_widget = Tree::new(x, y, width, height, title);
47 let previous_focus = Rc::new(RefCell::new(None::<TreeItem>));
48 let pfr = Rc::clone(&previous_focus);
49 t_widget.set_callback_reason(TreeReason::Selected);
50 t_widget.set_callback(|_t| println!("clicked an item"));
51 t_widget.handle(move |t, e| match e {
52 Event::Move => {
53 let (_, mouse_y) = app::event_coords();
54 let mut state = State::Undefined;
55 let mut pf = pfr.borrow_mut();
56 loop {
57 match &*pf {
58 Some(item) => {
59 let item_y = item.y();
60 match state {
61 State::MovingUp => {
62 if verify_open_till_root(&pf) {
63 if mouse_y < item_y {
64 *pf = pf.as_ref().unwrap().prev();
65 continue;
66 };
67 break;
68 } else {
69 *pf = pf.as_ref().unwrap().prev();
70 continue;
71 }
72 }
73 State::MovingDown => {
74 if verify_open_till_root(&pf) {
75 if mouse_y > item_y + item.h() {
76 *pf = pf.as_ref().unwrap().next();
77 continue;
78 };
79 break;
80 } else {
81 *pf = pf.as_ref().unwrap().next();
82 continue;
83 }
84 }
85 State::Undefined => {
86 if mouse_y < item_y {
87 *pf = pf.as_ref().unwrap().prev();
88 state = State::MovingUp;
89 continue;
90 };
91 if mouse_y > item_y + item.h() {
92 *pf = pf.as_ref().unwrap().next();
93 state = State::MovingDown;
94 continue;
95 };
96 return true; }
98 }
99 }
100 None => match &state {
102 State::MovingUp | State::MovingDown => return true,
103 State::Undefined => {
104 *pf = t.first();
105 state = State::MovingDown;
106 if pf.is_none() {
107 return true;
108 }
109 continue;
110 }
111 },
112 };
113 }
114 if verify_open_till_root(&pf) {
115 t.take_focus().ok();
116 t.set_item_focus(pf.as_ref().unwrap());
117 println!("Set focus to item: {:?}", pf.as_ref().unwrap().label());
118 }
119 true
120 }
121 _ => false,
122 });
123 Self {
124 t_widget,
125 previous_focus,
126 }
127 }
128
129 fn add(&mut self, path: &str) -> Option<TreeItem> {
130 self.t_widget.add(path)
131 }
132
133 fn remove(&mut self, item: &TreeItem) -> Result<(), FltkError> {
137 *self.previous_focus.borrow_mut() = None;
138 self.t_widget.remove(item)
139 }
140
141 fn get_items(&self) -> Option<Vec<TreeItem>> {
142 self.t_widget.get_items()
143 }
144}
145
146fn main() {
147 let path = env::current_dir().unwrap();
148 let path: String = path
149 .to_str()
150 .unwrap()
151 .chars()
152 .map(|c| match c {
153 '\\' => '/', _ => c,
155 })
156 .collect();
157
158 let app = app::App::default().with_scheme(app::Scheme::Gtk);
159 let mut wind = Window::default().with_size(400, 300);
160 let mut but = Button::new(260, 255, 80, 40, "Get Items");
161 let _frame = Frame::new(20, 255, 160, 40, "Focus follow mouse");
162 let mut tree = TreeMouseFocus::new(5, 10, 190, 240, "");
163 tree.add(&path);
164
165 let mut items = tree.get_items().unwrap();
166 items.as_mut_slice()[0].set_label("/");
167
168 let mut tree2 = Tree::new(205, 10, 190, 240, "");
169 tree2.set_select_mode(TreeSelect::Multi);
170 tree2.add("First");
171 tree2.add("First/1st");
172 tree2.add("First/2nd/3rd");
173 tree2.add("Second");
174 tree2.add("Third");
175
176 tree2.set_when(fltk::enums::When::ReleaseAlways);
177
178 wind.make_resizable(true);
179 wind.show();
180
181 but.set_callback({
182 let tree2 = tree2.clone();
183 move |_| match tree2.get_selected_items() {
184 None => println!("No items selected"),
185 Some(vals) => print!(
186 "In total {} items selected:\n{}",
187 vals.len(),
188 vals.iter()
189 .map(|i| tree2.item_pathname(i).unwrap() + "\n")
190 .collect::<String>()
191 ),
192 }
193 });
194
195 app.run().unwrap();
196}