1 // Take a look at the license at the top of the repository in the LICENSE file. 2 3 use crate::Builder; 4 use glib::prelude::*; 5 use glib::translate::*; 6 use glib::GString; 7 use glib::Object; 8 use std::path::Path; 9 10 impl Builder { 11 #[doc(alias = "gtk_builder_new_from_file")] from_file<T: AsRef<Path>>(file_path: T) -> Builder12 pub fn from_file<T: AsRef<Path>>(file_path: T) -> Builder { 13 assert_initialized_main_thread!(); 14 unsafe { 15 from_glib_full(ffi::gtk_builder_new_from_file( 16 file_path.as_ref().to_glib_none().0, 17 )) 18 } 19 } 20 } 21 22 pub trait BuilderExtManual: 'static { 23 #[doc(alias = "gtk_builder_get_object")] 24 #[doc(alias = "get_object")] object<T: IsA<Object>>(&self, name: &str) -> Option<T>25 fn object<T: IsA<Object>>(&self, name: &str) -> Option<T>; 26 27 #[doc(alias = "gtk_builder_add_from_file")] add_from_file<T: AsRef<Path>>(&self, file_path: T) -> Result<(), glib::Error>28 fn add_from_file<T: AsRef<Path>>(&self, file_path: T) -> Result<(), glib::Error>; 29 #[doc(alias = "gtk_builder_connect_signals_full")] connect_signals< P: FnMut(&Builder, &str) -> Box<dyn Fn(&[glib::Value]) -> Option<glib::Value> + 'static>, >( &self, func: P, )30 fn connect_signals< 31 P: FnMut(&Builder, &str) -> Box<dyn Fn(&[glib::Value]) -> Option<glib::Value> + 'static>, 32 >( 33 &self, 34 func: P, 35 ); 36 } 37 38 impl<O: IsA<Builder>> BuilderExtManual for O { object<T: IsA<Object>>(&self, name: &str) -> Option<T>39 fn object<T: IsA<Object>>(&self, name: &str) -> Option<T> { 40 unsafe { 41 Option::<Object>::from_glib_none(ffi::gtk_builder_get_object( 42 self.upcast_ref().to_glib_none().0, 43 name.to_glib_none().0, 44 )) 45 .and_then(|obj| obj.dynamic_cast::<T>().ok()) 46 } 47 } 48 add_from_file<T: AsRef<Path>>(&self, file_path: T) -> Result<(), glib::Error>49 fn add_from_file<T: AsRef<Path>>(&self, file_path: T) -> Result<(), glib::Error> { 50 unsafe { 51 let mut error = ::std::ptr::null_mut(); 52 ffi::gtk_builder_add_from_file( 53 self.upcast_ref().to_glib_none().0, 54 file_path.as_ref().to_glib_none().0, 55 &mut error, 56 ); 57 if error.is_null() { 58 Ok(()) 59 } else { 60 Err(from_glib_full(error)) 61 } 62 } 63 } 64 connect_signals< P: FnMut(&Builder, &str) -> Box<dyn Fn(&[glib::Value]) -> Option<glib::Value> + 'static>, >( &self, func: P, )65 fn connect_signals< 66 P: FnMut(&Builder, &str) -> Box<dyn Fn(&[glib::Value]) -> Option<glib::Value> + 'static>, 67 >( 68 &self, 69 func: P, 70 ) { 71 let func_data: P = func; 72 unsafe extern "C" fn func_func< 73 P: FnMut(&Builder, &str) -> Box<dyn Fn(&[glib::Value]) -> Option<glib::Value> + 'static>, 74 >( 75 builder: *mut ffi::GtkBuilder, 76 object: *mut glib::gobject_ffi::GObject, 77 signal_name: *const libc::c_char, 78 handler_name: *const libc::c_char, 79 connect_object: *mut glib::gobject_ffi::GObject, 80 flags: glib::gobject_ffi::GConnectFlags, 81 user_data: glib::ffi::gpointer, 82 ) { 83 assert!(connect_object.is_null(), "Connect object is not supported"); 84 assert!( 85 flags & glib::gobject_ffi::G_CONNECT_SWAPPED == 0, 86 "Swapped signal handler is not supported" 87 ); 88 89 let builder = from_glib_borrow(builder); 90 let object: Borrowed<glib::Object> = from_glib_borrow(object); 91 let signal_name: Borrowed<GString> = from_glib_borrow(signal_name); 92 let handler_name: Borrowed<GString> = from_glib_borrow(handler_name); 93 let callback: *mut P = user_data as *const _ as usize as *mut P; 94 let func = (*callback)(&builder, handler_name.as_str()); 95 object 96 .connect_unsafe( 97 signal_name.as_str(), 98 flags & glib::gobject_ffi::G_CONNECT_AFTER != 0, 99 move |args| func(args), 100 ) 101 .expect("Failed to connect to builder signal"); 102 } 103 let func = Some(func_func::<P> as _); 104 let super_callback0: &P = &func_data; 105 unsafe { 106 ffi::gtk_builder_connect_signals_full( 107 self.as_ref().to_glib_none().0, 108 func, 109 super_callback0 as *const _ as usize as *mut _, 110 ); 111 } 112 } 113 } 114