[go: up one dir, main page]

gtk/
signal.rs

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