1use gdk::Rectangle;
6use glib;
7pub use glib::signal::Inhibit;
8use glib::signal::SignalHandlerId;
9use glib::SourceId;
10
11use {Continue, ScrollType, Widget};
12
13pub fn idle_add<F>(func: F) -> SourceId
20where
21 F: FnMut() -> Continue + 'static,
22{
23 assert_initialized_main_thread!();
24 glib::idle_add_local(func)
25}
26
27pub fn timeout_add<F>(interval: u32, func: F) -> SourceId
38where
39 F: FnMut() -> Continue + 'static,
40{
41 assert_initialized_main_thread!();
42 glib::timeout_add_local(interval, func)
43}
44
45pub fn timeout_add_seconds<F>(interval: u32, func: F) -> SourceId
55where
56 F: FnMut() -> Continue + 'static,
57{
58 assert_initialized_main_thread!();
59 glib::timeout_add_seconds_local(interval, func)
60}
61
62pub trait EditableSignals: 'static {
63 fn connect_changed<F>(&self, changed_func: F) -> SignalHandlerId
64 where
65 F: Fn(&Self) + 'static;
66 fn connect_delete_text<F>(&self, delete_text_func: F) -> SignalHandlerId
67 where
68 F: Fn(&Self, i32, i32) + 'static;
69 fn connect_insert_text<F>(&self, insert_text_func: F) -> SignalHandlerId
70 where
71 F: Fn(&Self, &str, &mut i32) + 'static;
72}
73
74mod editable {
75 use glib::object::Cast;
76 use glib::signal::{connect_raw, SignalHandlerId};
77 use glib::translate::*;
78 use gtk_sys::GtkEditable;
79 use libc::{c_char, c_int, c_uchar};
80 use std::ffi::CStr;
81 use std::mem::transmute;
82 use std::slice;
83 use std::str;
84 use Editable;
85 use IsA;
86
87 impl<T: IsA<Editable>> super::EditableSignals for T {
88 fn connect_changed<F>(&self, changed_func: F) -> SignalHandlerId
89 where
90 F: Fn(&Self) + 'static,
91 {
92 unsafe {
93 let f: Box<F> = Box::new(changed_func);
94 connect_raw(
95 self.to_glib_none().0 as *mut _,
96 b"changed\0".as_ptr() as *mut _,
97 Some(transmute(trampoline::<Self, F> as usize)),
98 Box::into_raw(f),
99 )
100 }
101 }
102
103 fn connect_delete_text<F>(&self, delete_text_func: F) -> SignalHandlerId
104 where
105 F: Fn(&Self, i32, i32) + 'static,
106 {
107 unsafe {
108 let f: Box<F> = Box::new(delete_text_func);
109 connect_raw(
110 self.to_glib_none().0 as *mut _,
111 b"delete-text\0".as_ptr() as *mut _,
112 Some(transmute(delete_trampoline::<Self, F> as usize)),
113 Box::into_raw(f),
114 )
115 }
116 }
117
118 fn connect_insert_text<F>(&self, insert_text_func: F) -> SignalHandlerId
119 where
120 F: Fn(&Self, &str, &mut i32) + 'static,
121 {
122 unsafe {
123 let f: Box<F> = Box::new(insert_text_func);
124 connect_raw(
125 self.to_glib_none().0 as *mut _,
126 b"insert-text\0".as_ptr() as *mut _,
127 Some(transmute(insert_trampoline::<Self, F> as usize)),
128 Box::into_raw(f),
129 )
130 }
131 }
132 }
133
134 unsafe extern "C" fn trampoline<T, F: Fn(&T) + 'static>(this: *mut GtkEditable, f: &F)
135 where
136 T: IsA<Editable>,
137 {
138 f(&Editable::from_glib_borrow(this).unsafe_cast());
139 }
140
141 unsafe extern "C" fn delete_trampoline<T, F: Fn(&T, i32, i32) + 'static>(
142 this: *mut GtkEditable,
143 start_pos: c_int,
144 end_pos: c_int,
145 f: &F,
146 ) where
147 T: IsA<Editable>,
148 {
149 f(
150 &Editable::from_glib_borrow(this).unsafe_cast(),
151 start_pos,
152 end_pos,
153 );
154 }
155
156 unsafe extern "C" fn insert_trampoline<T, F: Fn(&T, &str, &mut i32) + 'static>(
157 this: *mut GtkEditable,
158 new_text: *mut c_char,
159 new_text_length: c_int,
160 position: *mut c_int,
161 f: &F,
162 ) where
163 T: IsA<Editable>,
164 {
165 let buf = if new_text_length != -1 {
166 slice::from_raw_parts(new_text as *mut c_uchar, new_text_length as usize)
167 } else {
168 CStr::from_ptr(new_text).to_bytes()
169 };
170 let string = str::from_utf8(buf).unwrap();
171 f(
172 &Editable::from_glib_borrow(this).unsafe_cast(),
173 string,
174 transmute(position),
175 );
176 }
177}
178
179pub trait SpinButtonSignals: 'static {
180 fn connect_change_value<F>(&self, change_value_func: F) -> SignalHandlerId
181 where
182 F: Fn(&Self, ScrollType) + 'static;
183 fn connect_input<F>(&self, input_func: F) -> SignalHandlerId
184 where
185 F: Fn(&Self) -> Option<Result<f64, ()>> + 'static;
186 fn connect_output<F>(&self, output_func: F) -> SignalHandlerId
187 where
188 F: Fn(&Self) -> Inhibit + 'static;
189 fn connect_value_changed<F>(&self, value_changed_func: F) -> SignalHandlerId
190 where
191 F: Fn(&Self) + 'static;
192 fn connect_wrapped<F>(&self, wrapped_func: F) -> SignalHandlerId
193 where
194 F: Fn(&Self) + 'static;
195}
196
197mod spin_button {
198 use glib::object::Cast;
199 use glib::signal::{connect_raw, SignalHandlerId};
200 use glib::translate::*;
201 use glib::IsA;
202 use glib_sys::gboolean;
203 use glib_sys::{GFALSE, GTRUE};
204 use gtk_sys::{GtkSpinButton, GTK_INPUT_ERROR};
205 use libc::{c_double, c_int};
206 use std::boxed::Box as Box_;
207 use std::mem::transmute;
208 use Inhibit;
209 use ScrollType;
210 use SpinButton;
211
212 impl<T: IsA<SpinButton>> ::SpinButtonSignals for T {
213 fn connect_change_value<F>(&self, change_value_func: F) -> SignalHandlerId
214 where
215 F: Fn(&Self, ScrollType) + 'static,
216 {
217 unsafe {
218 let f: Box<F> = Box::new(change_value_func);
219 connect_raw(
220 self.to_glib_none().0 as *mut _,
221 b"change_value\0".as_ptr() as *mut _,
222 Some(transmute(change_trampoline::<Self, F> as usize)),
223 Box::into_raw(f),
224 )
225 }
226 }
227
228 fn connect_input<F>(&self, f: F) -> SignalHandlerId
229 where
230 F: Fn(&Self) -> Option<Result<f64, ()>> + 'static,
231 {
232 unsafe {
233 let f: Box_<F> = Box_::new(f);
234 connect_raw(
235 self.to_glib_none().0 as *mut _,
236 b"input\0".as_ptr() as *mut _,
237 Some(transmute(input_trampoline::<Self, F> as usize)),
238 Box_::into_raw(f),
239 )
240 }
241 }
242
243 fn connect_output<F>(&self, output_func: F) -> SignalHandlerId
244 where
245 F: Fn(&Self) -> Inhibit + 'static,
246 {
247 unsafe {
248 let f: Box<F> = Box::new(output_func);
249 connect_raw(
250 self.to_glib_none().0 as *mut _,
251 b"output\0".as_ptr() as *mut _,
252 Some(transmute(output_trampoline::<Self, F> as usize)),
253 Box::into_raw(f),
254 )
255 }
256 }
257
258 fn connect_value_changed<F>(&self, value_changed_func: F) -> SignalHandlerId
259 where
260 F: Fn(&Self) + 'static,
261 {
262 unsafe {
263 let f: Box<F> = Box::new(value_changed_func);
264 connect_raw(
265 self.to_glib_none().0 as *mut _,
266 b"value-changed\0".as_ptr() as *mut _,
267 Some(transmute(trampoline::<Self, F> as usize)),
268 Box::into_raw(f),
269 )
270 }
271 }
272
273 fn connect_wrapped<F>(&self, wrapped_func: F) -> SignalHandlerId
274 where
275 F: Fn(&Self) + 'static,
276 {
277 unsafe {
278 let f: Box<F> = Box::new(wrapped_func);
279 connect_raw(
280 self.to_glib_none().0 as *mut _,
281 b"wrapped\0".as_ptr() as *mut _,
282 Some(transmute(trampoline::<Self, F> as usize)),
283 Box::into_raw(f),
284 )
285 }
286 }
287 }
288
289 unsafe extern "C" fn change_trampoline<T, F: Fn(&T, ScrollType) + 'static>(
290 this: *mut GtkSpinButton,
291 scroll: ScrollType,
292 f: &F,
293 ) where
294 T: IsA<SpinButton>,
295 {
296 f(&SpinButton::from_glib_borrow(this).unsafe_cast(), scroll)
297 }
298
299 unsafe extern "C" fn input_trampoline<T, F: Fn(&T) -> Option<Result<f64, ()>> + 'static>(
300 this: *mut GtkSpinButton,
301 new_value: *mut c_double,
302 f: &F,
303 ) -> c_int
304 where
305 T: IsA<SpinButton>,
306 {
307 match f(&SpinButton::from_glib_borrow(this).unsafe_cast()) {
308 Some(Ok(v)) => {
309 *new_value = v;
310 GTRUE
311 }
312 Some(Err(_)) => GTK_INPUT_ERROR,
313 None => GFALSE,
314 }
315 }
316
317 unsafe extern "C" fn output_trampoline<T, F: Fn(&T) -> Inhibit + 'static>(
318 this: *mut GtkSpinButton,
319 f: &F,
320 ) -> gboolean
321 where
322 T: IsA<SpinButton>,
323 {
324 f(&SpinButton::from_glib_borrow(this).unsafe_cast()).to_glib()
325 }
326
327 unsafe extern "C" fn trampoline<T, F: Fn(&T) + 'static>(this: *mut GtkSpinButton, f: &F)
328 where
329 T: IsA<SpinButton>,
330 {
331 f(&SpinButton::from_glib_borrow(this).unsafe_cast())
332 }
333}
334
335pub trait OverlaySignals: 'static {
336 fn connect_get_child_position<F>(&self, f: F) -> SignalHandlerId
337 where
338 F: Fn(&Self, &Widget) -> Option<Rectangle> + 'static;
339}
340
341mod overlay {
342 use gdk::Rectangle;
343 use gdk_sys::GdkRectangle;
344 use glib::object::Cast;
345 use glib::signal::{connect_raw, SignalHandlerId};
346 use glib::translate::*;
347 use glib_sys::{gboolean, gpointer};
348 use gtk_sys::{GtkOverlay, GtkWidget};
349 use std::mem::transmute;
350 use std::ptr;
351 use IsA;
352 use Overlay;
353 use Widget;
354
355 impl<O: IsA<Overlay>> ::OverlaySignals for O {
356 fn connect_get_child_position<F>(&self, f: F) -> SignalHandlerId
357 where
358 F: Fn(&Self, &Widget) -> Option<Rectangle> + 'static,
359 {
360 unsafe {
361 let f: Box<F> = Box::new(f);
362 connect_raw(
363 self.to_glib_none().0 as *mut _,
364 b"get-child-position\0".as_ptr() as *mut _,
365 Some(transmute(get_child_position_trampoline::<Self, F> as usize)),
366 Box::into_raw(f),
367 )
368 }
369 }
370 }
371
372 unsafe extern "C" fn get_child_position_trampoline<
373 T,
374 F: Fn(&T, &Widget) -> Option<Rectangle> + 'static,
375 >(
376 this: *mut GtkOverlay,
377 widget: *mut GtkWidget,
378 allocation: *mut GdkRectangle,
379 f: gpointer,
380 ) -> gboolean
381 where
382 T: IsA<Overlay>,
383 {
384 let f: &F = &*(f as *const F);
385 match f(
386 &Overlay::from_glib_borrow(this).unsafe_cast(),
387 &from_glib_borrow(widget),
388 ) {
389 Some(rect) => {
390 ptr::write(allocation, ptr::read(rect.to_glib_none().0));
391 true
392 }
393 None => false,
394 }
395 .to_glib()
396 }
397}