1use 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 &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}