1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
// Take a look at the license at the top of the repository in the LICENSE file.
use std::{boxed::Box as Box_, mem::transmute};
use glib::{
signal::{connect_raw, SignalHandlerId},
translate::*,
value::FromValue,
Slice, Type,
};
use crate::{prelude::*, DropTarget};
impl DropTarget {
/// Sets the supported `GType`s for this drop target.
/// ## `types`
/// all supported `GType`s
/// that can be dropped on the target
#[doc(alias = "gtk_drop_target_set_gtypes")]
pub fn set_types(&self, types: &[Type]) {
let types: Vec<glib::ffi::GType> = types.iter().map(|t| t.into_glib()).collect();
unsafe {
ffi::gtk_drop_target_set_gtypes(
self.to_glib_none().0,
mut_override(types.as_ptr()),
types.len(),
)
}
}
#[doc(alias = "gtk_drop_target_get_value")]
#[doc(alias = "get_value")]
// rustdoc-stripper-ignore-next
/// Similar to [`Self::value`] but panics if the value is of a different
/// type.
pub fn value_as<V: for<'b> FromValue<'b> + 'static>(&self) -> Option<V> {
self.value().map(|v| {
v.get_owned::<V>()
.expect("Failed to get value as this type")
})
}
/// Gets the list of supported `GType`s that can be dropped on the target.
///
/// If no types have been set, `NULL` will be returned.
///
/// # Returns
///
///
/// the `G_TYPE_INVALID`-terminated array of types included in
/// formats
#[doc(alias = "gtk_drop_target_get_gtypes")]
#[doc(alias = "get_gtypes")]
pub fn types(&self) -> Slice<Type> {
unsafe {
let mut n_types = std::mem::MaybeUninit::uninit();
let types =
ffi::gtk_drop_target_get_gtypes(self.to_glib_none().0, n_types.as_mut_ptr());
Slice::from_glib_none_num(types, n_types.assume_init() as _)
}
}
// Returns true if the drop was accepted
/// Emitted on the drop site when the user drops the data onto the widget.
///
/// The signal handler must determine whether the pointer position is in
/// a drop zone or not. If it is not in a drop zone, it returns [`false`]
/// and no further processing is necessary.
///
/// Otherwise, the handler returns [`true`]. In this case, this handler will
/// accept the drop. The handler is responsible for using the given @value
/// and performing the drop operation.
/// ## `value`
/// the `GValue` being dropped
/// ## `x`
/// the x coordinate of the current pointer position
/// ## `y`
/// the y coordinate of the current pointer position
///
/// # Returns
///
/// whether the drop was accepted at the given pointer position
pub fn connect_drop<F: Fn(&DropTarget, &glib::Value, f64, f64) -> bool + 'static>(
&self,
f: F,
) -> SignalHandlerId {
unsafe extern "C" fn drop_trampoline<
F: Fn(&DropTarget, &glib::Value, f64, f64) -> bool + 'static,
>(
this: *mut ffi::GtkDropTarget,
value: *mut glib::gobject_ffi::GValue,
x: libc::c_double,
y: libc::c_double,
f: glib::ffi::gpointer,
) -> glib::ffi::gboolean {
let f: &F = &*(f as *const F);
f(
&from_glib_borrow(this),
&*(value as *const glib::Value),
x,
y,
)
.into_glib()
}
unsafe {
let f: Box_<F> = Box_::new(f);
connect_raw(
self.as_ptr() as *mut _,
b"drop\0".as_ptr() as *const _,
Some(transmute::<_, unsafe extern "C" fn()>(
drop_trampoline::<F> as *const (),
)),
Box_::into_raw(f),
)
}
}
}