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