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