1use glib::object::{Cast, IsA};
6use glib::translate::*;
7use glib::{ToValue, Type, Value};
8use gtk_sys;
9use libc::c_int;
10use TreeIter;
11use TreeModel;
12use TreeStore;
13
14impl TreeStore {
15 pub fn new(column_types: &[Type]) -> TreeStore {
16 assert_initialized_main_thread!();
17 unsafe {
18 let mut column_types = column_types.iter().map(|t| t.to_glib()).collect::<Vec<_>>();
19 from_glib_full(gtk_sys::gtk_tree_store_newv(
20 column_types.len() as c_int,
21 column_types.as_mut_ptr(),
22 ))
23 }
24 }
25}
26
27pub trait TreeStoreExtManual: 'static {
28 fn insert_with_values(
29 &self,
30 parent: Option<&TreeIter>,
31 position: Option<u32>,
32 columns: &[u32],
33 values: &[&dyn ToValue],
34 ) -> TreeIter;
35
36 fn reorder(&self, parent: &TreeIter, new_order: &[u32]);
37
38 fn set(&self, iter: &TreeIter, columns: &[u32], values: &[&dyn ToValue]);
39
40 fn set_value(&self, iter: &TreeIter, column: u32, value: &Value);
41}
42
43impl<O: IsA<TreeStore>> TreeStoreExtManual for O {
44 fn insert_with_values(
45 &self,
46 parent: Option<&TreeIter>,
47 position: Option<u32>,
48 columns: &[u32],
49 values: &[&dyn ToValue],
50 ) -> TreeIter {
51 unsafe {
52 assert!(position.unwrap_or(0) <= i32::max_value() as u32);
53 assert_eq!(columns.len(), values.len());
54 let n_columns = gtk_sys::gtk_tree_model_get_n_columns(
55 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
56 ) as u32;
57 assert!(columns.len() <= n_columns as usize);
58 for (&column, value) in columns.iter().zip(values.iter()) {
59 let type_ = from_glib(gtk_sys::gtk_tree_model_get_column_type(
60 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
61 column as c_int,
62 ));
63 assert!(Value::type_transformable(value.to_value_type(), type_));
64 }
65 let mut iter = TreeIter::uninitialized();
66 gtk_sys::gtk_tree_store_insert_with_valuesv(
67 self.as_ref().to_glib_none().0,
68 iter.to_glib_none_mut().0,
69 mut_override(parent.to_glib_none().0),
70 position.map_or(-1, |n| n as c_int),
71 mut_override(columns.as_ptr() as *const c_int),
72 values.to_glib_none().0,
73 columns.len() as c_int,
74 );
75 iter
76 }
77 }
78
79 fn reorder(&self, parent: &TreeIter, new_order: &[u32]) {
80 unsafe {
81 let count = gtk_sys::gtk_tree_model_iter_n_children(
82 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
83 mut_override(parent.to_glib_none().0),
84 );
85 let safe_count = count as usize == new_order.len();
86 debug_assert!(
87 safe_count,
88 "Incorrect `new_order` slice length. Expected `{}`, found `{}`.",
89 count,
90 new_order.len()
91 );
92 let safe_values = new_order.iter().max().map_or(true, |&max| {
93 let max = max as i32;
94 max >= 0 && max < count
95 });
96 debug_assert!(
97 safe_values,
98 "Some `new_order` slice values are out of range. Maximum safe value: \
99 `{}`. The slice contents: `{:?}`",
100 count - 1,
101 new_order
102 );
103 if safe_count && safe_values {
104 gtk_sys::gtk_tree_store_reorder(
105 self.as_ref().to_glib_none().0,
106 mut_override(parent.to_glib_none().0),
107 mut_override(new_order.as_ptr() as *const c_int),
108 );
109 }
110 }
111 }
112
113 fn set(&self, iter: &TreeIter, columns: &[u32], values: &[&dyn ToValue]) {
114 unsafe {
115 assert_eq!(columns.len(), values.len());
116 let n_columns = gtk_sys::gtk_tree_model_get_n_columns(
117 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
118 ) as u32;
119 assert!(columns.len() <= n_columns as usize);
120 for (&column, value) in columns.iter().zip(values.iter()) {
121 assert!(column < n_columns);
122 let type_ = from_glib(gtk_sys::gtk_tree_model_get_column_type(
123 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
124 column as c_int,
125 ));
126 assert!(Value::type_transformable(value.to_value_type(), type_));
127 }
128 gtk_sys::gtk_tree_store_set_valuesv(
129 self.as_ref().to_glib_none().0,
130 mut_override(iter.to_glib_none().0),
131 mut_override(columns.as_ptr() as *const c_int),
132 values.to_glib_none().0,
133 columns.len() as c_int,
134 );
135 }
136 }
137
138 fn set_value(&self, iter: &TreeIter, column: u32, value: &Value) {
139 unsafe {
140 let columns = gtk_sys::gtk_tree_model_get_n_columns(
141 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
142 );
143 assert!(column < columns as u32);
144 let type_ = from_glib(gtk_sys::gtk_tree_model_get_column_type(
145 self.as_ref().upcast_ref::<TreeModel>().to_glib_none().0,
146 column as c_int,
147 ));
148 assert!(Value::type_transformable(value.type_(), type_));
149 gtk_sys::gtk_tree_store_set_value(
150 self.as_ref().to_glib_none().0,
151 mut_override(iter.to_glib_none().0),
152 column as c_int,
153 mut_override(value.to_glib_none().0),
154 );
155 }
156 }
157}