1use glib;
6use glib::object::Cast;
7use glib::object::IsA;
8use glib::signal::connect_raw;
9use glib::signal::SignalHandlerId;
10use glib::translate::*;
11use glib::GString;
12use glib_sys;
13use gtk_sys;
14use std::boxed::Box as Box_;
15use std::fmt;
16use std::mem::transmute;
17use std::ptr;
18use Application;
19use Error;
20use Widget;
21
22glib_wrapper! {
23 pub struct Builder(Object<gtk_sys::GtkBuilder, gtk_sys::GtkBuilderClass, BuilderClass>);
24
25 match fn {
26 get_type => || gtk_sys::gtk_builder_get_type(),
27 }
28}
29
30impl Builder {
31 pub fn new() -> Builder {
32 assert_initialized_main_thread!();
33 unsafe { from_glib_full(gtk_sys::gtk_builder_new()) }
34 }
35
36 pub fn new_from_resource(resource_path: &str) -> Builder {
37 assert_initialized_main_thread!();
38 unsafe {
39 from_glib_full(gtk_sys::gtk_builder_new_from_resource(
40 resource_path.to_glib_none().0,
41 ))
42 }
43 }
44
45 pub fn new_from_string(string: &str) -> Builder {
46 assert_initialized_main_thread!();
47 let length = string.len() as isize;
48 unsafe {
49 from_glib_full(gtk_sys::gtk_builder_new_from_string(
50 string.to_glib_none().0,
51 length,
52 ))
53 }
54 }
55}
56
57impl Default for Builder {
58 fn default() -> Self {
59 Self::new()
60 }
61}
62
63pub const NONE_BUILDER: Option<&Builder> = None;
64
65pub trait BuilderExt: 'static {
66 fn add_from_resource(&self, resource_path: &str) -> Result<(), Error>;
71
72 fn add_from_string(&self, buffer: &str) -> Result<(), Error>;
73
74 fn add_objects_from_resource(
75 &self,
76 resource_path: &str,
77 object_ids: &[&str],
78 ) -> Result<(), Error>;
79
80 fn add_objects_from_string(&self, buffer: &str, object_ids: &[&str]) -> Result<(), Error>;
81
82 fn expose_object<P: IsA<glib::Object>>(&self, name: &str, object: &P);
87
88 fn extend_with_template<P: IsA<Widget>>(
89 &self,
90 widget: &P,
91 template_type: glib::types::Type,
92 buffer: &str,
93 ) -> Result<(), Error>;
94
95 fn get_application(&self) -> Option<Application>;
96
97 fn get_objects(&self) -> Vec<glib::Object>;
98
99 fn get_translation_domain(&self) -> Option<GString>;
100
101 fn get_type_from_name(&self, type_name: &str) -> glib::types::Type;
102
103 fn set_application<P: IsA<Application>>(&self, application: &P);
106
107 fn set_translation_domain(&self, domain: Option<&str>);
108
109 fn value_from_string_type(
112 &self,
113 type_: glib::types::Type,
114 string: &str,
115 ) -> Result<glib::Value, Error>;
116
117 fn connect_property_translation_domain_notify<F: Fn(&Self) + 'static>(
118 &self,
119 f: F,
120 ) -> SignalHandlerId;
121}
122
123impl<O: IsA<Builder>> BuilderExt for O {
124 fn add_from_resource(&self, resource_path: &str) -> Result<(), Error> {
133 unsafe {
134 let mut error = ptr::null_mut();
135 let _ = gtk_sys::gtk_builder_add_from_resource(
136 self.as_ref().to_glib_none().0,
137 resource_path.to_glib_none().0,
138 &mut error,
139 );
140 if error.is_null() {
141 Ok(())
142 } else {
143 Err(from_glib_full(error))
144 }
145 }
146 }
147
148 fn add_from_string(&self, buffer: &str) -> Result<(), Error> {
149 let length = buffer.len() as usize;
150 unsafe {
151 let mut error = ptr::null_mut();
152 let _ = gtk_sys::gtk_builder_add_from_string(
153 self.as_ref().to_glib_none().0,
154 buffer.to_glib_none().0,
155 length,
156 &mut error,
157 );
158 if error.is_null() {
159 Ok(())
160 } else {
161 Err(from_glib_full(error))
162 }
163 }
164 }
165
166 fn add_objects_from_resource(
167 &self,
168 resource_path: &str,
169 object_ids: &[&str],
170 ) -> Result<(), Error> {
171 unsafe {
172 let mut error = ptr::null_mut();
173 let _ = gtk_sys::gtk_builder_add_objects_from_resource(
174 self.as_ref().to_glib_none().0,
175 resource_path.to_glib_none().0,
176 object_ids.to_glib_none().0,
177 &mut error,
178 );
179 if error.is_null() {
180 Ok(())
181 } else {
182 Err(from_glib_full(error))
183 }
184 }
185 }
186
187 fn add_objects_from_string(&self, buffer: &str, object_ids: &[&str]) -> Result<(), Error> {
188 let length = buffer.len() as usize;
189 unsafe {
190 let mut error = ptr::null_mut();
191 let _ = gtk_sys::gtk_builder_add_objects_from_string(
192 self.as_ref().to_glib_none().0,
193 buffer.to_glib_none().0,
194 length,
195 object_ids.to_glib_none().0,
196 &mut error,
197 );
198 if error.is_null() {
199 Ok(())
200 } else {
201 Err(from_glib_full(error))
202 }
203 }
204 }
205
206 fn expose_object<P: IsA<glib::Object>>(&self, name: &str, object: &P) {
215 unsafe {
216 gtk_sys::gtk_builder_expose_object(
217 self.as_ref().to_glib_none().0,
218 name.to_glib_none().0,
219 object.as_ref().to_glib_none().0,
220 );
221 }
222 }
223
224 fn extend_with_template<P: IsA<Widget>>(
225 &self,
226 widget: &P,
227 template_type: glib::types::Type,
228 buffer: &str,
229 ) -> Result<(), Error> {
230 let length = buffer.len() as usize;
231 unsafe {
232 let mut error = ptr::null_mut();
233 let _ = gtk_sys::gtk_builder_extend_with_template(
234 self.as_ref().to_glib_none().0,
235 widget.as_ref().to_glib_none().0,
236 template_type.to_glib(),
237 buffer.to_glib_none().0,
238 length,
239 &mut error,
240 );
241 if error.is_null() {
242 Ok(())
243 } else {
244 Err(from_glib_full(error))
245 }
246 }
247 }
248
249 fn get_application(&self) -> Option<Application> {
250 unsafe {
251 from_glib_none(gtk_sys::gtk_builder_get_application(
252 self.as_ref().to_glib_none().0,
253 ))
254 }
255 }
256
257 fn get_objects(&self) -> Vec<glib::Object> {
258 unsafe {
259 FromGlibPtrContainer::from_glib_container(gtk_sys::gtk_builder_get_objects(
260 self.as_ref().to_glib_none().0,
261 ))
262 }
263 }
264
265 fn get_translation_domain(&self) -> Option<GString> {
266 unsafe {
267 from_glib_none(gtk_sys::gtk_builder_get_translation_domain(
268 self.as_ref().to_glib_none().0,
269 ))
270 }
271 }
272
273 fn get_type_from_name(&self, type_name: &str) -> glib::types::Type {
274 unsafe {
275 from_glib(gtk_sys::gtk_builder_get_type_from_name(
276 self.as_ref().to_glib_none().0,
277 type_name.to_glib_none().0,
278 ))
279 }
280 }
281
282 fn set_application<P: IsA<Application>>(&self, application: &P) {
287 unsafe {
288 gtk_sys::gtk_builder_set_application(
289 self.as_ref().to_glib_none().0,
290 application.as_ref().to_glib_none().0,
291 );
292 }
293 }
294
295 fn set_translation_domain(&self, domain: Option<&str>) {
296 unsafe {
297 gtk_sys::gtk_builder_set_translation_domain(
298 self.as_ref().to_glib_none().0,
299 domain.to_glib_none().0,
300 );
301 }
302 }
303
304 fn value_from_string_type(
309 &self,
310 type_: glib::types::Type,
311 string: &str,
312 ) -> Result<glib::Value, Error> {
313 unsafe {
314 let mut value = glib::Value::uninitialized();
315 let mut error = ptr::null_mut();
316 let _ = gtk_sys::gtk_builder_value_from_string_type(
317 self.as_ref().to_glib_none().0,
318 type_.to_glib(),
319 string.to_glib_none().0,
320 value.to_glib_none_mut().0,
321 &mut error,
322 );
323 if error.is_null() {
324 Ok(value)
325 } else {
326 Err(from_glib_full(error))
327 }
328 }
329 }
330
331 fn connect_property_translation_domain_notify<F: Fn(&Self) + 'static>(
332 &self,
333 f: F,
334 ) -> SignalHandlerId {
335 unsafe extern "C" fn notify_translation_domain_trampoline<P, F: Fn(&P) + 'static>(
336 this: *mut gtk_sys::GtkBuilder,
337 _param_spec: glib_sys::gpointer,
338 f: glib_sys::gpointer,
339 ) where
340 P: IsA<Builder>,
341 {
342 let f: &F = &*(f as *const F);
343 f(&Builder::from_glib_borrow(this).unsafe_cast())
344 }
345 unsafe {
346 let f: Box_<F> = Box_::new(f);
347 connect_raw(
348 self.as_ptr() as *mut _,
349 b"notify::translation-domain\0".as_ptr() as *const _,
350 Some(transmute(
351 notify_translation_domain_trampoline::<Self, F> as usize,
352 )),
353 Box_::into_raw(f),
354 )
355 }
356 }
357}
358
359impl fmt::Display for Builder {
360 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
361 write!(f, "Builder")
362 }
363}