1use glib::object::Cast;
6use glib::object::IsA;
7use glib::signal::connect_raw;
8use glib::signal::SignalHandlerId;
9use glib::translate::*;
10use glib_sys;
11use gtk_sys;
12use std::boxed::Box as Box_;
13use std::fmt;
14use std::mem::transmute;
15use std::ptr;
16use SelectionMode;
17use TreeIter;
18use TreeModel;
19use TreePath;
20use TreeView;
21
22glib_wrapper! {
23 pub struct TreeSelection(Object<gtk_sys::GtkTreeSelection, gtk_sys::GtkTreeSelectionClass, TreeSelectionClass>);
24
25 match fn {
26 get_type => || gtk_sys::gtk_tree_selection_get_type(),
27 }
28}
29
30pub const NONE_TREE_SELECTION: Option<&TreeSelection> = None;
31
32pub trait TreeSelectionExt: 'static {
33 fn count_selected_rows(&self) -> i32;
34
35 fn get_mode(&self) -> SelectionMode;
36
37 fn get_selected(&self) -> Option<(TreeModel, TreeIter)>;
40
41 fn get_selected_rows(&self) -> (Vec<TreePath>, TreeModel);
42
43 fn get_tree_view(&self) -> Option<TreeView>;
44
45 fn iter_is_selected(&self, iter: &TreeIter) -> bool;
48
49 fn path_is_selected(&self, path: &TreePath) -> bool;
50
51 fn select_all(&self);
52
53 fn select_iter(&self, iter: &TreeIter);
54
55 fn select_path(&self, path: &TreePath);
56
57 fn select_range(&self, start_path: &TreePath, end_path: &TreePath);
58
59 fn selected_foreach<P: FnMut(&TreeModel, &TreePath, &TreeIter)>(&self, func: P);
60
61 fn set_mode(&self, type_: SelectionMode);
62
63 fn set_select_function(
64 &self,
65 func: Option<Box<dyn Fn(&TreeSelection, &TreeModel, &TreePath, bool) -> bool + 'static>>,
66 );
67
68 fn unselect_all(&self);
69
70 fn unselect_iter(&self, iter: &TreeIter);
71
72 fn unselect_path(&self, path: &TreePath);
73
74 fn unselect_range(&self, start_path: &TreePath, end_path: &TreePath);
75
76 fn connect_changed<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId;
77
78 fn connect_property_mode_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId;
79}
80
81impl<O: IsA<TreeSelection>> TreeSelectionExt for O {
82 fn count_selected_rows(&self) -> i32 {
83 unsafe { gtk_sys::gtk_tree_selection_count_selected_rows(self.as_ref().to_glib_none().0) }
84 }
85
86 fn get_mode(&self) -> SelectionMode {
87 unsafe {
88 from_glib(gtk_sys::gtk_tree_selection_get_mode(
89 self.as_ref().to_glib_none().0,
90 ))
91 }
92 }
93
94 fn get_selected(&self) -> Option<(TreeModel, TreeIter)> {
99 unsafe {
100 let mut model = ptr::null_mut();
101 let mut iter = TreeIter::uninitialized();
102 let ret = from_glib(gtk_sys::gtk_tree_selection_get_selected(
103 self.as_ref().to_glib_none().0,
104 &mut model,
105 iter.to_glib_none_mut().0,
106 ));
107 if ret {
108 Some((from_glib_none(model), iter))
109 } else {
110 None
111 }
112 }
113 }
114
115 fn get_selected_rows(&self) -> (Vec<TreePath>, TreeModel) {
116 unsafe {
117 let mut model = ptr::null_mut();
118 let ret = FromGlibPtrContainer::from_glib_full(
119 gtk_sys::gtk_tree_selection_get_selected_rows(
120 self.as_ref().to_glib_none().0,
121 &mut model,
122 ),
123 );
124 (ret, from_glib_none(model))
125 }
126 }
127
128 fn get_tree_view(&self) -> Option<TreeView> {
129 unsafe {
130 from_glib_none(gtk_sys::gtk_tree_selection_get_tree_view(
131 self.as_ref().to_glib_none().0,
132 ))
133 }
134 }
135
136 fn iter_is_selected(&self, iter: &TreeIter) -> bool {
141 unsafe {
142 from_glib(gtk_sys::gtk_tree_selection_iter_is_selected(
143 self.as_ref().to_glib_none().0,
144 mut_override(iter.to_glib_none().0),
145 ))
146 }
147 }
148
149 fn path_is_selected(&self, path: &TreePath) -> bool {
150 unsafe {
151 from_glib(gtk_sys::gtk_tree_selection_path_is_selected(
152 self.as_ref().to_glib_none().0,
153 mut_override(path.to_glib_none().0),
154 ))
155 }
156 }
157
158 fn select_all(&self) {
159 unsafe {
160 gtk_sys::gtk_tree_selection_select_all(self.as_ref().to_glib_none().0);
161 }
162 }
163
164 fn select_iter(&self, iter: &TreeIter) {
165 unsafe {
166 gtk_sys::gtk_tree_selection_select_iter(
167 self.as_ref().to_glib_none().0,
168 mut_override(iter.to_glib_none().0),
169 );
170 }
171 }
172
173 fn select_path(&self, path: &TreePath) {
174 unsafe {
175 gtk_sys::gtk_tree_selection_select_path(
176 self.as_ref().to_glib_none().0,
177 mut_override(path.to_glib_none().0),
178 );
179 }
180 }
181
182 fn select_range(&self, start_path: &TreePath, end_path: &TreePath) {
183 unsafe {
184 gtk_sys::gtk_tree_selection_select_range(
185 self.as_ref().to_glib_none().0,
186 mut_override(start_path.to_glib_none().0),
187 mut_override(end_path.to_glib_none().0),
188 );
189 }
190 }
191
192 fn selected_foreach<P: FnMut(&TreeModel, &TreePath, &TreeIter)>(&self, func: P) {
193 let func_data: P = func;
194 unsafe extern "C" fn func_func<P: FnMut(&TreeModel, &TreePath, &TreeIter)>(
195 model: *mut gtk_sys::GtkTreeModel,
196 path: *mut gtk_sys::GtkTreePath,
197 iter: *mut gtk_sys::GtkTreeIter,
198 data: glib_sys::gpointer,
199 ) {
200 let model = from_glib_borrow(model);
201 let path = from_glib_borrow(path);
202 let iter = from_glib_borrow(iter);
203 let callback: *mut P = data as *const _ as usize as *mut P;
204 (*callback)(&model, &path, &iter);
205 }
206 let func = Some(func_func::<P> as _);
207 let super_callback0: &P = &func_data;
208 unsafe {
209 gtk_sys::gtk_tree_selection_selected_foreach(
210 self.as_ref().to_glib_none().0,
211 func,
212 super_callback0 as *const _ as usize as *mut _,
213 );
214 }
215 }
216
217 fn set_mode(&self, type_: SelectionMode) {
218 unsafe {
219 gtk_sys::gtk_tree_selection_set_mode(self.as_ref().to_glib_none().0, type_.to_glib());
220 }
221 }
222
223 fn set_select_function(
224 &self,
225 func: Option<Box<dyn Fn(&TreeSelection, &TreeModel, &TreePath, bool) -> bool + 'static>>,
226 ) {
227 let func_data: Box_<
228 Option<Box<dyn Fn(&TreeSelection, &TreeModel, &TreePath, bool) -> bool + 'static>>,
229 > = Box::new(func);
230 unsafe extern "C" fn func_func(
231 selection: *mut gtk_sys::GtkTreeSelection,
232 model: *mut gtk_sys::GtkTreeModel,
233 path: *mut gtk_sys::GtkTreePath,
234 path_currently_selected: glib_sys::gboolean,
235 data: glib_sys::gpointer,
236 ) -> glib_sys::gboolean {
237 let selection = from_glib_borrow(selection);
238 let model = from_glib_borrow(model);
239 let path = from_glib_borrow(path);
240 let path_currently_selected = from_glib(path_currently_selected);
241 let callback: &Option<
242 Box<dyn Fn(&TreeSelection, &TreeModel, &TreePath, bool) -> bool + 'static>,
243 > = &*(data as *mut _);
244 let res = if let Some(ref callback) = *callback {
245 callback(&selection, &model, &path, path_currently_selected)
246 } else {
247 panic!("cannot get closure...")
248 };
249 res.to_glib()
250 }
251 let func = if func_data.is_some() {
252 Some(func_func as _)
253 } else {
254 None
255 };
256 unsafe extern "C" fn destroy_func(data: glib_sys::gpointer) {
257 let _callback: Box_<
258 Option<Box<dyn Fn(&TreeSelection, &TreeModel, &TreePath, bool) -> bool + 'static>>,
259 > = Box_::from_raw(data as *mut _);
260 }
261 let destroy_call3 = Some(destroy_func as _);
262 let super_callback0: Box_<
263 Option<Box<dyn Fn(&TreeSelection, &TreeModel, &TreePath, bool) -> bool + 'static>>,
264 > = func_data;
265 unsafe {
266 gtk_sys::gtk_tree_selection_set_select_function(
267 self.as_ref().to_glib_none().0,
268 func,
269 Box::into_raw(super_callback0) as *mut _,
270 destroy_call3,
271 );
272 }
273 }
274
275 fn unselect_all(&self) {
276 unsafe {
277 gtk_sys::gtk_tree_selection_unselect_all(self.as_ref().to_glib_none().0);
278 }
279 }
280
281 fn unselect_iter(&self, iter: &TreeIter) {
282 unsafe {
283 gtk_sys::gtk_tree_selection_unselect_iter(
284 self.as_ref().to_glib_none().0,
285 mut_override(iter.to_glib_none().0),
286 );
287 }
288 }
289
290 fn unselect_path(&self, path: &TreePath) {
291 unsafe {
292 gtk_sys::gtk_tree_selection_unselect_path(
293 self.as_ref().to_glib_none().0,
294 mut_override(path.to_glib_none().0),
295 );
296 }
297 }
298
299 fn unselect_range(&self, start_path: &TreePath, end_path: &TreePath) {
300 unsafe {
301 gtk_sys::gtk_tree_selection_unselect_range(
302 self.as_ref().to_glib_none().0,
303 mut_override(start_path.to_glib_none().0),
304 mut_override(end_path.to_glib_none().0),
305 );
306 }
307 }
308
309 fn connect_changed<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
310 unsafe extern "C" fn changed_trampoline<P, F: Fn(&P) + 'static>(
311 this: *mut gtk_sys::GtkTreeSelection,
312 f: glib_sys::gpointer,
313 ) where
314 P: IsA<TreeSelection>,
315 {
316 let f: &F = &*(f as *const F);
317 f(&TreeSelection::from_glib_borrow(this).unsafe_cast())
318 }
319 unsafe {
320 let f: Box_<F> = Box_::new(f);
321 connect_raw(
322 self.as_ptr() as *mut _,
323 b"changed\0".as_ptr() as *const _,
324 Some(transmute(changed_trampoline::<Self, F> as usize)),
325 Box_::into_raw(f),
326 )
327 }
328 }
329
330 fn connect_property_mode_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
331 unsafe extern "C" fn notify_mode_trampoline<P, F: Fn(&P) + 'static>(
332 this: *mut gtk_sys::GtkTreeSelection,
333 _param_spec: glib_sys::gpointer,
334 f: glib_sys::gpointer,
335 ) where
336 P: IsA<TreeSelection>,
337 {
338 let f: &F = &*(f as *const F);
339 f(&TreeSelection::from_glib_borrow(this).unsafe_cast())
340 }
341 unsafe {
342 let f: Box_<F> = Box_::new(f);
343 connect_raw(
344 self.as_ptr() as *mut _,
345 b"notify::mode\0".as_ptr() as *const _,
346 Some(transmute(notify_mode_trampoline::<Self, F> as usize)),
347 Box_::into_raw(f),
348 )
349 }
350 }
351}
352
353impl fmt::Display for TreeSelection {
354 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
355 write!(f, "TreeSelection")
356 }
357}