Skip to main content

libadwaita/
spin_row.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use crate::SpinRow;
4use glib::{
5    signal::{SignalHandlerId, connect_raw},
6    translate::*,
7};
8use gtk::{glib, prelude::*};
9use std::ffi::{c_double, c_int};
10use std::{boxed::Box as Box_, mem::transmute};
11
12impl SpinRow {
13    /// Emitted to convert the user's input into a double value.
14    ///
15    /// The signal handler is expected to use [`EditableExtManual::text()`][crate::gtk::prelude::EditableExtManual::text()] to
16    /// retrieve the text of the spinbutton and set new_value to the new value.
17    ///
18    /// The default conversion uses `strtod()`.
19    ///
20    /// See [`input`][struct@crate::Gtk::SpinButton#input].
21    ///
22    /// # Returns
23    ///
24    /// `TRUE` for a successful conversion, `FALSE` if the input was not
25    ///   handled, and `Gtk::INPUT_ERROR` if the conversion failed.
26    ///
27    /// ## `new_value`
28    /// return location for the new value
29    pub fn connect_input<F>(&self, f: F) -> SignalHandlerId
30    where
31        F: Fn(&Self) -> Option<Result<f64, ()>> + 'static,
32    {
33        unsafe {
34            let f: Box_<F> = Box_::new(f);
35            connect_raw(
36                self.as_ptr() as *mut _,
37                c"input".as_ptr() as *const _,
38                Some(transmute::<*const (), unsafe extern "C" fn()>(
39                    input_trampoline::<F> as *const (),
40                )),
41                Box_::into_raw(f),
42            )
43        }
44    }
45}
46
47unsafe extern "C" fn input_trampoline<F: Fn(&SpinRow) -> Option<Result<f64, ()>> + 'static>(
48    this: *mut ffi::AdwSpinRow,
49    new_value: *mut c_double,
50    f: &F,
51) -> c_int {
52    unsafe {
53        match f(SpinRow::from_glib_borrow(this).unsafe_cast_ref()) {
54            Some(Ok(v)) => {
55                *new_value = v;
56                glib::ffi::GTRUE
57            }
58            Some(Err(_)) => gtk::ffi::GTK_INPUT_ERROR,
59            None => glib::ffi::GFALSE,
60        }
61    }
62}