1 // Take a look at the license at the top of the repository in the LICENSE file.
2 
3 use crate::translate::*;
4 use crate::utils::is_canonical_pspec_name;
5 use crate::ParamFlags;
6 use crate::StaticType;
7 use crate::Type;
8 use crate::Value;
9 
10 use std::char::CharTryFromError;
11 use std::convert::TryFrom;
12 use std::ffi::CStr;
13 
14 // Can't use get_type here as this is not a boxed type but another fundamental type
15 wrapper! {
16     #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
17     #[doc(alias = "GParamSpec")]
18     pub struct ParamSpec(Shared<gobject_ffi::GParamSpec>);
19 
20     match fn {
21         ref => |ptr| gobject_ffi::g_param_spec_ref_sink(ptr),
22         unref => |ptr| gobject_ffi::g_param_spec_unref(ptr),
23     }
24 }
25 
26 impl StaticType for ParamSpec {
static_type() -> Type27     fn static_type() -> Type {
28         unsafe { from_glib(gobject_ffi::G_TYPE_PARAM) }
29     }
30 }
31 
32 #[doc(hidden)]
33 impl crate::value::ValueType for ParamSpec {
34     type Type = ParamSpec;
35 }
36 
37 #[doc(hidden)]
38 unsafe impl<'a> crate::value::FromValue<'a> for ParamSpec {
39     type Checker = crate::value::GenericValueTypeOrNoneChecker<Self>;
40 
from_value(value: &'a crate::Value) -> Self41     unsafe fn from_value(value: &'a crate::Value) -> Self {
42         let ptr = gobject_ffi::g_value_dup_param(value.to_glib_none().0);
43         assert!(!ptr.is_null());
44         from_glib_full(ptr as *mut gobject_ffi::GParamSpec)
45     }
46 }
47 
48 #[doc(hidden)]
49 impl crate::value::ToValue for ParamSpec {
to_value(&self) -> crate::Value50     fn to_value(&self) -> crate::Value {
51         unsafe {
52             let mut value = crate::Value::from_type(ParamSpec::static_type());
53             gobject_ffi::g_value_take_param(
54                 value.to_glib_none_mut().0,
55                 self.to_glib_full() as *mut _,
56             );
57             value
58         }
59     }
60 
value_type(&self) -> crate::Type61     fn value_type(&self) -> crate::Type {
62         ParamSpec::static_type()
63     }
64 }
65 
66 #[doc(hidden)]
67 impl crate::value::ToValueOptional for ParamSpec {
to_value_optional(s: Option<&Self>) -> crate::Value68     fn to_value_optional(s: Option<&Self>) -> crate::Value {
69         let mut value = crate::Value::for_value_type::<Self>();
70         unsafe {
71             gobject_ffi::g_value_take_param(value.to_glib_none_mut().0, s.to_glib_full() as *mut _);
72         }
73 
74         value
75     }
76 }
77 
78 unsafe impl Send for ParamSpec {}
79 unsafe impl Sync for ParamSpec {}
80 
81 impl ParamSpec {
downcast<T: ParamSpecType>(self) -> Result<T, ParamSpec>82     pub fn downcast<T: ParamSpecType>(self) -> Result<T, ParamSpec> {
83         unsafe {
84             if self.type_() == T::static_type() {
85                 Ok(from_glib_full(self.to_glib_full()))
86             } else {
87                 Err(self)
88             }
89         }
90     }
91 
downcast_ref<T: ParamSpecType>(&self) -> Option<&T>92     pub fn downcast_ref<T: ParamSpecType>(&self) -> Option<&T> {
93         unsafe {
94             if self.type_() == T::static_type() {
95                 Some(&*(self as *const ParamSpec as *const T))
96             } else {
97                 None
98             }
99         }
100     }
101 
102     #[doc(alias = "get_type")]
type_(&self) -> Type103     pub fn type_(&self) -> Type {
104         unsafe {
105             let ptr = self.to_glib_none().0;
106 
107             from_glib((*(*ptr).g_type_instance.g_class).g_type)
108         }
109     }
110 
111     #[doc(alias = "get_value_type")]
value_type(&self) -> crate::Type112     pub fn value_type(&self) -> crate::Type {
113         unsafe { from_glib((*self.to_glib_none().0).value_type) }
114     }
115 
116     #[doc(alias = "get_owner_type")]
owner_type(&self) -> crate::Type117     pub fn owner_type(&self) -> crate::Type {
118         unsafe { from_glib((*self.to_glib_none().0).owner_type) }
119     }
120 
121     #[doc(alias = "get_flags")]
flags(&self) -> ParamFlags122     pub fn flags(&self) -> ParamFlags {
123         unsafe { from_glib((*self.to_glib_none().0).flags) }
124     }
125 
126     #[doc(alias = "g_param_spec_get_blurb")]
127     #[doc(alias = "get_blurb")]
blurb(&self) -> &str128     pub fn blurb(&self) -> &str {
129         unsafe {
130             CStr::from_ptr(gobject_ffi::g_param_spec_get_blurb(self.to_glib_none().0))
131                 .to_str()
132                 .unwrap()
133         }
134     }
135 
136     #[doc(alias = "g_param_spec_get_default_value")]
137     #[doc(alias = "get_default_value")]
default_value(&self) -> &Value138     pub fn default_value(&self) -> &Value {
139         unsafe {
140             &*(gobject_ffi::g_param_spec_get_default_value(self.to_glib_none().0)
141                 as *const crate::Value)
142         }
143     }
144 
145     #[doc(alias = "g_param_spec_get_name")]
146     #[doc(alias = "get_name")]
name<'a>(&self) -> &'a str147     pub fn name<'a>(&self) -> &'a str {
148         unsafe {
149             CStr::from_ptr(gobject_ffi::g_param_spec_get_name(self.to_glib_none().0))
150                 .to_str()
151                 .unwrap()
152         }
153     }
154 
155     #[doc(alias = "g_param_spec_get_name_quark")]
156     #[doc(alias = "get_name_quark")]
name_quark(&self) -> crate::Quark157     pub fn name_quark(&self) -> crate::Quark {
158         unsafe {
159             from_glib(gobject_ffi::g_param_spec_get_name_quark(
160                 self.to_glib_none().0,
161             ))
162         }
163     }
164 
165     #[doc(alias = "g_param_spec_get_nick")]
166     #[doc(alias = "get_nick")]
nick(&self) -> &str167     pub fn nick(&self) -> &str {
168         unsafe {
169             CStr::from_ptr(gobject_ffi::g_param_spec_get_nick(self.to_glib_none().0))
170                 .to_str()
171                 .unwrap()
172         }
173     }
174 
175     //pub fn get_qdata(&self, quark: /*Ignored*/glib::Quark) -> /*Unimplemented*/Option<Fundamental: Pointer> {
176     //    unsafe { TODO: call gobject_ffi::g_param_spec_get_qdata() }
177     //}
178 
179     #[doc(alias = "g_param_spec_get_redirect_target")]
180     #[doc(alias = "get_redirect_target")]
redirect_target(&self) -> Option<ParamSpec>181     pub fn redirect_target(&self) -> Option<ParamSpec> {
182         unsafe {
183             from_glib_none(gobject_ffi::g_param_spec_get_redirect_target(
184                 self.to_glib_none().0,
185             ))
186         }
187     }
188 
189     //pub fn set_qdata(&self, quark: /*Ignored*/glib::Quark, data: Option</*Unimplemented*/Fundamental: Pointer>) {
190     //    unsafe { TODO: call gobject_ffi::g_param_spec_set_qdata() }
191     //}
192 
193     //pub fn set_qdata_full(&self, quark: /*Ignored*/glib::Quark, data: Option</*Unimplemented*/Fundamental: Pointer>, destroy: /*Unknown conversion*//*Unimplemented*/DestroyNotify) {
194     //    unsafe { TODO: call gobject_ffi::g_param_spec_set_qdata_full() }
195     //}
196 
197     //pub fn steal_qdata(&self, quark: /*Ignored*/glib::Quark) -> /*Unimplemented*/Option<Fundamental: Pointer> {
198     //    unsafe { TODO: call gobject_ffi::g_param_spec_steal_qdata() }
199     //}
200 
201     #[doc(alias = "g_param_spec_boolean")]
new_boolean( name: &str, nick: &str, blurb: &str, default_value: bool, flags: ParamFlags, ) -> ParamSpec202     pub fn new_boolean(
203         name: &str,
204         nick: &str,
205         blurb: &str,
206         default_value: bool,
207         flags: ParamFlags,
208     ) -> ParamSpec {
209         assert!(
210             is_canonical_pspec_name(name),
211             "{} is not a valid canonical parameter name",
212             name
213         );
214         unsafe {
215             from_glib_none(gobject_ffi::g_param_spec_boolean(
216                 name.to_glib_none().0,
217                 nick.to_glib_none().0,
218                 blurb.to_glib_none().0,
219                 default_value.into_glib(),
220                 flags.into_glib(),
221             ))
222         }
223     }
224 
225     #[doc(alias = "g_param_spec_boxed")]
new_boxed( name: &str, nick: &str, blurb: &str, boxed_type: crate::Type, flags: ParamFlags, ) -> ParamSpec226     pub fn new_boxed(
227         name: &str,
228         nick: &str,
229         blurb: &str,
230         boxed_type: crate::Type,
231         flags: ParamFlags,
232     ) -> ParamSpec {
233         assert!(
234             is_canonical_pspec_name(name),
235             "{} is not a valid canonical parameter name",
236             name
237         );
238         unsafe {
239             from_glib_none(gobject_ffi::g_param_spec_boxed(
240                 name.to_glib_none().0,
241                 nick.to_glib_none().0,
242                 blurb.to_glib_none().0,
243                 boxed_type.into_glib(),
244                 flags.into_glib(),
245             ))
246         }
247     }
248 
249     #[doc(alias = "g_param_spec_char")]
new_char( name: &str, nick: &str, blurb: &str, minimum: i8, maximum: i8, default_value: i8, flags: ParamFlags, ) -> ParamSpec250     pub fn new_char(
251         name: &str,
252         nick: &str,
253         blurb: &str,
254         minimum: i8,
255         maximum: i8,
256         default_value: i8,
257         flags: ParamFlags,
258     ) -> ParamSpec {
259         assert!(
260             is_canonical_pspec_name(name),
261             "{} is not a valid canonical parameter name",
262             name
263         );
264         unsafe {
265             from_glib_none(gobject_ffi::g_param_spec_char(
266                 name.to_glib_none().0,
267                 nick.to_glib_none().0,
268                 blurb.to_glib_none().0,
269                 minimum,
270                 maximum,
271                 default_value,
272                 flags.into_glib(),
273             ))
274         }
275     }
276 
277     #[doc(alias = "g_param_spec_double")]
new_double( name: &str, nick: &str, blurb: &str, minimum: f64, maximum: f64, default_value: f64, flags: ParamFlags, ) -> ParamSpec278     pub fn new_double(
279         name: &str,
280         nick: &str,
281         blurb: &str,
282         minimum: f64,
283         maximum: f64,
284         default_value: f64,
285         flags: ParamFlags,
286     ) -> ParamSpec {
287         assert!(
288             is_canonical_pspec_name(name),
289             "{} is not a valid canonical parameter name",
290             name
291         );
292         unsafe {
293             from_glib_none(gobject_ffi::g_param_spec_double(
294                 name.to_glib_none().0,
295                 nick.to_glib_none().0,
296                 blurb.to_glib_none().0,
297                 minimum,
298                 maximum,
299                 default_value,
300                 flags.into_glib(),
301             ))
302         }
303     }
304 
305     #[doc(alias = "g_param_spec_enum")]
new_enum( name: &str, nick: &str, blurb: &str, enum_type: crate::Type, default_value: i32, flags: ParamFlags, ) -> ParamSpec306     pub fn new_enum(
307         name: &str,
308         nick: &str,
309         blurb: &str,
310         enum_type: crate::Type,
311         default_value: i32,
312         flags: ParamFlags,
313     ) -> ParamSpec {
314         assert!(
315             is_canonical_pspec_name(name),
316             "{} is not a valid canonical parameter name",
317             name
318         );
319         unsafe {
320             from_glib_none(gobject_ffi::g_param_spec_enum(
321                 name.to_glib_none().0,
322                 nick.to_glib_none().0,
323                 blurb.to_glib_none().0,
324                 enum_type.into_glib(),
325                 default_value,
326                 flags.into_glib(),
327             ))
328         }
329     }
330 
331     #[doc(alias = "g_param_spec_flags")]
new_flags( name: &str, nick: &str, blurb: &str, flags_type: crate::Type, default_value: u32, flags: ParamFlags, ) -> ParamSpec332     pub fn new_flags(
333         name: &str,
334         nick: &str,
335         blurb: &str,
336         flags_type: crate::Type,
337         default_value: u32,
338         flags: ParamFlags,
339     ) -> ParamSpec {
340         assert!(
341             is_canonical_pspec_name(name),
342             "{} is not a valid canonical parameter name",
343             name
344         );
345         unsafe {
346             from_glib_none(gobject_ffi::g_param_spec_flags(
347                 name.to_glib_none().0,
348                 nick.to_glib_none().0,
349                 blurb.to_glib_none().0,
350                 flags_type.into_glib(),
351                 default_value,
352                 flags.into_glib(),
353             ))
354         }
355     }
356 
357     #[doc(alias = "g_param_spec_float")]
new_float( name: &str, nick: &str, blurb: &str, minimum: f32, maximum: f32, default_value: f32, flags: ParamFlags, ) -> ParamSpec358     pub fn new_float(
359         name: &str,
360         nick: &str,
361         blurb: &str,
362         minimum: f32,
363         maximum: f32,
364         default_value: f32,
365         flags: ParamFlags,
366     ) -> ParamSpec {
367         assert!(
368             is_canonical_pspec_name(name),
369             "{} is not a valid canonical parameter name",
370             name
371         );
372         unsafe {
373             from_glib_none(gobject_ffi::g_param_spec_float(
374                 name.to_glib_none().0,
375                 nick.to_glib_none().0,
376                 blurb.to_glib_none().0,
377                 minimum,
378                 maximum,
379                 default_value,
380                 flags.into_glib(),
381             ))
382         }
383     }
384 
385     #[doc(alias = "g_param_spec_gtype")]
new_type( name: &str, nick: &str, blurb: &str, is_a_type: crate::Type, flags: ParamFlags, ) -> ParamSpec386     pub fn new_type(
387         name: &str,
388         nick: &str,
389         blurb: &str,
390         is_a_type: crate::Type,
391         flags: ParamFlags,
392     ) -> ParamSpec {
393         assert!(
394             is_canonical_pspec_name(name),
395             "{} is not a valid canonical parameter name",
396             name
397         );
398         unsafe {
399             from_glib_none(gobject_ffi::g_param_spec_gtype(
400                 name.to_glib_none().0,
401                 nick.to_glib_none().0,
402                 blurb.to_glib_none().0,
403                 is_a_type.into_glib(),
404                 flags.into_glib(),
405             ))
406         }
407     }
408 
409     #[doc(alias = "g_param_spec_int")]
new_int( name: &str, nick: &str, blurb: &str, minimum: i32, maximum: i32, default_value: i32, flags: ParamFlags, ) -> ParamSpec410     pub fn new_int(
411         name: &str,
412         nick: &str,
413         blurb: &str,
414         minimum: i32,
415         maximum: i32,
416         default_value: i32,
417         flags: ParamFlags,
418     ) -> ParamSpec {
419         assert!(
420             is_canonical_pspec_name(name),
421             "{} is not a valid canonical parameter name",
422             name
423         );
424         unsafe {
425             from_glib_none(gobject_ffi::g_param_spec_int(
426                 name.to_glib_none().0,
427                 nick.to_glib_none().0,
428                 blurb.to_glib_none().0,
429                 minimum,
430                 maximum,
431                 default_value,
432                 flags.into_glib(),
433             ))
434         }
435     }
436 
437     #[doc(alias = "g_param_spec_int64")]
new_int64( name: &str, nick: &str, blurb: &str, minimum: i64, maximum: i64, default_value: i64, flags: ParamFlags, ) -> ParamSpec438     pub fn new_int64(
439         name: &str,
440         nick: &str,
441         blurb: &str,
442         minimum: i64,
443         maximum: i64,
444         default_value: i64,
445         flags: ParamFlags,
446     ) -> ParamSpec {
447         assert!(
448             is_canonical_pspec_name(name),
449             "{} is not a valid canonical parameter name",
450             name
451         );
452         unsafe {
453             from_glib_none(gobject_ffi::g_param_spec_int64(
454                 name.to_glib_none().0,
455                 nick.to_glib_none().0,
456                 blurb.to_glib_none().0,
457                 minimum,
458                 maximum,
459                 default_value,
460                 flags.into_glib(),
461             ))
462         }
463     }
464 
465     #[doc(alias = "g_param_spec_long")]
new_long( name: &str, nick: &str, blurb: &str, minimum: libc::c_long, maximum: libc::c_long, default_value: libc::c_long, flags: ParamFlags, ) -> ParamSpec466     pub fn new_long(
467         name: &str,
468         nick: &str,
469         blurb: &str,
470         minimum: libc::c_long,
471         maximum: libc::c_long,
472         default_value: libc::c_long,
473         flags: ParamFlags,
474     ) -> ParamSpec {
475         assert!(
476             is_canonical_pspec_name(name),
477             "{} is not a valid canonical parameter name",
478             name
479         );
480         unsafe {
481             from_glib_none(gobject_ffi::g_param_spec_long(
482                 name.to_glib_none().0,
483                 nick.to_glib_none().0,
484                 blurb.to_glib_none().0,
485                 minimum,
486                 maximum,
487                 default_value,
488                 flags.into_glib(),
489             ))
490         }
491     }
492 
493     #[doc(alias = "g_param_spec_object")]
new_object( name: &str, nick: &str, blurb: &str, object_type: crate::Type, flags: ParamFlags, ) -> ParamSpec494     pub fn new_object(
495         name: &str,
496         nick: &str,
497         blurb: &str,
498         object_type: crate::Type,
499         flags: ParamFlags,
500     ) -> ParamSpec {
501         assert!(
502             is_canonical_pspec_name(name),
503             "{} is not a valid canonical parameter name",
504             name
505         );
506         unsafe {
507             from_glib_none(gobject_ffi::g_param_spec_object(
508                 name.to_glib_none().0,
509                 nick.to_glib_none().0,
510                 blurb.to_glib_none().0,
511                 object_type.into_glib(),
512                 flags.into_glib(),
513             ))
514         }
515     }
516 
517     #[doc(alias = "g_param_spec_override")]
new_override(name: &str, overridden: &ParamSpec) -> ParamSpec518     pub fn new_override(name: &str, overridden: &ParamSpec) -> ParamSpec {
519         assert!(
520             is_canonical_pspec_name(name),
521             "{} is not a valid canonical parameter name",
522             name
523         );
524         unsafe {
525             from_glib_none(gobject_ffi::g_param_spec_override(
526                 name.to_glib_none().0,
527                 overridden.to_glib_none().0,
528             ))
529         }
530     }
531 
532     #[doc(alias = "g_param_spec_param")]
new_param( name: &str, nick: &str, blurb: &str, param_type: crate::Type, flags: ParamFlags, ) -> ParamSpec533     pub fn new_param(
534         name: &str,
535         nick: &str,
536         blurb: &str,
537         param_type: crate::Type,
538         flags: ParamFlags,
539     ) -> ParamSpec {
540         assert!(
541             is_canonical_pspec_name(name),
542             "{} is not a valid canonical parameter name",
543             name
544         );
545         unsafe {
546             from_glib_none(gobject_ffi::g_param_spec_param(
547                 name.to_glib_none().0,
548                 nick.to_glib_none().0,
549                 blurb.to_glib_none().0,
550                 param_type.into_glib(),
551                 flags.into_glib(),
552             ))
553         }
554     }
555 
556     #[doc(alias = "g_param_spec_pointer")]
new_pointer(name: &str, nick: &str, blurb: &str, flags: ParamFlags) -> ParamSpec557     pub fn new_pointer(name: &str, nick: &str, blurb: &str, flags: ParamFlags) -> ParamSpec {
558         assert!(
559             is_canonical_pspec_name(name),
560             "{} is not a valid canonical parameter name",
561             name
562         );
563         unsafe {
564             from_glib_none(gobject_ffi::g_param_spec_pointer(
565                 name.to_glib_none().0,
566                 nick.to_glib_none().0,
567                 blurb.to_glib_none().0,
568                 flags.into_glib(),
569             ))
570         }
571     }
572 
573     #[doc(alias = "g_param_spec_string")]
new_string( name: &str, nick: &str, blurb: &str, default_value: Option<&str>, flags: ParamFlags, ) -> ParamSpec574     pub fn new_string(
575         name: &str,
576         nick: &str,
577         blurb: &str,
578         default_value: Option<&str>,
579         flags: ParamFlags,
580     ) -> ParamSpec {
581         assert!(
582             is_canonical_pspec_name(name),
583             "{} is not a valid canonical parameter name",
584             name
585         );
586         let default_value = default_value.to_glib_none();
587         unsafe {
588             from_glib_none(gobject_ffi::g_param_spec_string(
589                 name.to_glib_none().0,
590                 nick.to_glib_none().0,
591                 blurb.to_glib_none().0,
592                 default_value.0,
593                 flags.into_glib(),
594             ))
595         }
596     }
597 
598     #[doc(alias = "g_param_spec_uchar")]
new_uchar( name: &str, nick: &str, blurb: &str, minimum: u8, maximum: u8, default_value: u8, flags: ParamFlags, ) -> ParamSpec599     pub fn new_uchar(
600         name: &str,
601         nick: &str,
602         blurb: &str,
603         minimum: u8,
604         maximum: u8,
605         default_value: u8,
606         flags: ParamFlags,
607     ) -> ParamSpec {
608         assert!(
609             is_canonical_pspec_name(name),
610             "{} is not a valid canonical parameter name",
611             name
612         );
613         unsafe {
614             from_glib_none(gobject_ffi::g_param_spec_uchar(
615                 name.to_glib_none().0,
616                 nick.to_glib_none().0,
617                 blurb.to_glib_none().0,
618                 minimum,
619                 maximum,
620                 default_value,
621                 flags.into_glib(),
622             ))
623         }
624     }
625 
626     #[doc(alias = "g_param_spec_uint")]
new_uint( name: &str, nick: &str, blurb: &str, minimum: u32, maximum: u32, default_value: u32, flags: ParamFlags, ) -> ParamSpec627     pub fn new_uint(
628         name: &str,
629         nick: &str,
630         blurb: &str,
631         minimum: u32,
632         maximum: u32,
633         default_value: u32,
634         flags: ParamFlags,
635     ) -> ParamSpec {
636         assert!(
637             is_canonical_pspec_name(name),
638             "{} is not a valid canonical parameter name",
639             name
640         );
641         unsafe {
642             from_glib_none(gobject_ffi::g_param_spec_uint(
643                 name.to_glib_none().0,
644                 nick.to_glib_none().0,
645                 blurb.to_glib_none().0,
646                 minimum,
647                 maximum,
648                 default_value,
649                 flags.into_glib(),
650             ))
651         }
652     }
653 
654     #[doc(alias = "g_param_spec_uint64")]
new_uint64( name: &str, nick: &str, blurb: &str, minimum: u64, maximum: u64, default_value: u64, flags: ParamFlags, ) -> ParamSpec655     pub fn new_uint64(
656         name: &str,
657         nick: &str,
658         blurb: &str,
659         minimum: u64,
660         maximum: u64,
661         default_value: u64,
662         flags: ParamFlags,
663     ) -> ParamSpec {
664         assert!(
665             is_canonical_pspec_name(name),
666             "{} is not a valid canonical parameter name",
667             name
668         );
669         unsafe {
670             from_glib_none(gobject_ffi::g_param_spec_uint64(
671                 name.to_glib_none().0,
672                 nick.to_glib_none().0,
673                 blurb.to_glib_none().0,
674                 minimum,
675                 maximum,
676                 default_value,
677                 flags.into_glib(),
678             ))
679         }
680     }
681 
682     #[doc(alias = "g_param_spec_ulong")]
new_ulong( name: &str, nick: &str, blurb: &str, minimum: libc::c_ulong, maximum: libc::c_ulong, default_value: libc::c_ulong, flags: ParamFlags, ) -> ParamSpec683     pub fn new_ulong(
684         name: &str,
685         nick: &str,
686         blurb: &str,
687         minimum: libc::c_ulong,
688         maximum: libc::c_ulong,
689         default_value: libc::c_ulong,
690         flags: ParamFlags,
691     ) -> ParamSpec {
692         assert!(
693             is_canonical_pspec_name(name),
694             "{} is not a valid canonical parameter name",
695             name
696         );
697         unsafe {
698             from_glib_none(gobject_ffi::g_param_spec_ulong(
699                 name.to_glib_none().0,
700                 nick.to_glib_none().0,
701                 blurb.to_glib_none().0,
702                 minimum,
703                 maximum,
704                 default_value,
705                 flags.into_glib(),
706             ))
707         }
708     }
709 
710     #[doc(alias = "g_param_spec_unichar")]
new_unichar( name: &str, nick: &str, blurb: &str, default_value: char, flags: ParamFlags, ) -> ParamSpec711     pub fn new_unichar(
712         name: &str,
713         nick: &str,
714         blurb: &str,
715         default_value: char,
716         flags: ParamFlags,
717     ) -> ParamSpec {
718         assert!(
719             is_canonical_pspec_name(name),
720             "{} is not a valid canonical parameter name",
721             name
722         );
723         unsafe {
724             from_glib_none(gobject_ffi::g_param_spec_unichar(
725                 name.to_glib_none().0,
726                 nick.to_glib_none().0,
727                 blurb.to_glib_none().0,
728                 default_value.into_glib(),
729                 flags.into_glib(),
730             ))
731         }
732     }
733 
734     #[doc(alias = "g_param_spec_value_array")]
new_value_array( name: &str, nick: &str, blurb: &str, element_spec: &ParamSpec, flags: ParamFlags, ) -> ParamSpec735     pub fn new_value_array(
736         name: &str,
737         nick: &str,
738         blurb: &str,
739         element_spec: &ParamSpec,
740         flags: ParamFlags,
741     ) -> ParamSpec {
742         assert!(
743             is_canonical_pspec_name(name),
744             "{} is not a valid canonical parameter name",
745             name
746         );
747         unsafe {
748             from_glib_none(gobject_ffi::g_param_spec_value_array(
749                 name.to_glib_none().0,
750                 nick.to_glib_none().0,
751                 blurb.to_glib_none().0,
752                 element_spec.to_glib_none().0,
753                 flags.into_glib(),
754             ))
755         }
756     }
757 
758     #[doc(alias = "g_param_spec_variant")]
new_variant( name: &str, nick: &str, blurb: &str, type_: &crate::VariantTy, default_value: Option<&crate::Variant>, flags: ParamFlags, ) -> ParamSpec759     pub fn new_variant(
760         name: &str,
761         nick: &str,
762         blurb: &str,
763         type_: &crate::VariantTy,
764         default_value: Option<&crate::Variant>,
765         flags: ParamFlags,
766     ) -> ParamSpec {
767         assert!(
768             is_canonical_pspec_name(name),
769             "{} is not a valid canonical parameter name",
770             name
771         );
772         unsafe {
773             from_glib_none(gobject_ffi::g_param_spec_variant(
774                 name.to_glib_none().0,
775                 nick.to_glib_none().0,
776                 blurb.to_glib_none().0,
777                 type_.to_glib_none().0,
778                 default_value.to_glib_none().0,
779                 flags.into_glib(),
780             ))
781         }
782     }
783 }
784 
785 pub unsafe trait ParamSpecType:
786     StaticType + FromGlibPtrFull<*mut gobject_ffi::GParamSpec> + 'static
787 {
788 }
789 
790 #[link(name = "gobject-2.0")]
791 extern "C" {
792     pub static g_param_spec_types: *const ffi::GType;
793 }
794 
795 macro_rules! define_param_spec {
796     ($rust_type:ident, $ffi_type:path, $mod_name:ident, $rust_type_offset:expr) => {
797         // Can't use get_type here as this is not a boxed type but another fundamental type
798         wrapper! {
799             #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
800             pub struct $rust_type(Shared<$ffi_type>);
801 
802             match fn {
803                 ref => |ptr| gobject_ffi::g_param_spec_ref_sink(ptr as *mut gobject_ffi::GParamSpec) as *mut $ffi_type,
804                 unref => |ptr| gobject_ffi::g_param_spec_unref(ptr as *mut gobject_ffi::GParamSpec),
805             }
806         }
807 
808         impl StaticType for $rust_type {
809             fn static_type() -> Type {
810                 unsafe {
811                     from_glib(*g_param_spec_types.add($rust_type_offset))
812                 }
813             }
814         }
815 
816         #[doc(hidden)]
817         impl crate::value::ValueType for $rust_type {
818             type Type = $rust_type;
819         }
820 
821         #[doc(hidden)]
822         unsafe impl<'a> crate::value::FromValue<'a> for $rust_type {
823             type Checker = $crate::value::GenericValueTypeOrNoneChecker<Self>;
824 
825             unsafe fn from_value(value: &'a crate::Value) -> Self {
826                 let ptr = gobject_ffi::g_value_dup_param(value.to_glib_none().0);
827                 assert!(!ptr.is_null());
828                 from_glib_full(ptr as *mut $ffi_type)
829             }
830         }
831 
832         #[doc(hidden)]
833         impl crate::value::ToValue for $rust_type {
834             fn to_value(&self) -> crate::Value {
835                 unsafe {
836                     let mut value = crate::Value::from_type($rust_type::static_type());
837                     gobject_ffi::g_value_take_param(value.to_glib_none_mut().0, self.to_glib_full() as *mut _);
838                     value
839                 }
840             }
841 
842             fn value_type(&self) -> crate::Type {
843                 $rust_type::static_type()
844             }
845         }
846 
847         #[doc(hidden)]
848         impl crate::value::ToValueOptional for $rust_type {
849             fn to_value_optional(s: Option<&Self>) -> crate::Value {
850                 let mut value = crate::Value::for_value_type::<Self>();
851                 unsafe {
852                     gobject_ffi::g_value_take_param(value.to_glib_none_mut().0, s.to_glib_full() as *mut _);
853                 }
854 
855                 value
856             }
857         }
858 
859         unsafe impl Send for $rust_type {}
860         unsafe impl Sync for $rust_type {}
861 
862         impl std::ops::Deref for $rust_type {
863             type Target = ParamSpec;
864 
865             fn deref(&self) -> &Self::Target {
866                 unsafe {
867                     &*(self as *const $rust_type as *const ParamSpec)
868                 }
869             }
870         }
871 
872         unsafe impl ParamSpecType for $rust_type {}
873 
874         #[doc(hidden)]
875         impl FromGlibPtrFull<*mut gobject_ffi::GParamSpec> for $rust_type {
876             unsafe fn from_glib_full(ptr: *mut gobject_ffi::GParamSpec) -> Self {
877                 from_glib_full(ptr as *mut $ffi_type)
878             }
879         }
880 
881         impl $rust_type {
882             pub fn upcast(self) -> ParamSpec {
883                 unsafe {
884                     from_glib_full(self.to_glib_full() as *mut gobject_ffi::GParamSpec)
885                 }
886             }
887 
888             pub fn upcast_ref(&self) -> &ParamSpec {
889                 &*self
890             }
891         }
892     };
893 }
894 
895 macro_rules! define_param_spec_default {
896     ($rust_type:ident, $value_type:ty, $from_glib:expr) => {
897         impl $rust_type {
898             pub fn default_value(&self) -> $value_type {
899                 unsafe {
900                     let ptr = self.to_glib_none().0;
901                     $from_glib((*ptr).default_value)
902                 }
903             }
904         }
905     };
906 }
907 
908 macro_rules! define_param_spec_min_max {
909     ($rust_type:ident, $value_type:ty, $from_glib:expr) => {
910         impl $rust_type {
911             pub fn minimum(&self) -> $value_type {
912                 unsafe {
913                     let ptr = self.to_glib_none().0;
914                     $from_glib((*ptr).minimum)
915                 }
916             }
917 
918             pub fn maximum(&self) -> $value_type {
919                 unsafe {
920                     let ptr = self.to_glib_none().0;
921                     $from_glib((*ptr).maximum)
922                 }
923             }
924         }
925     };
926 }
927 
928 macro_rules! define_param_spec_numeric {
929     ($rust_type:ident, $ffi_type:path, $value_type:ty, $mod_name:ident, $rust_type_offset:expr, $from_glib:expr) => {
930         define_param_spec!($rust_type, $ffi_type, $mod_name, $rust_type_offset);
931         define_param_spec_default!($rust_type, $value_type, $from_glib);
932         define_param_spec_min_max!($rust_type, $value_type, $from_glib);
933     };
934 }
935 
936 define_param_spec_numeric!(
937     ParamSpecChar,
938     gobject_ffi::GParamSpecChar,
939     i8,
940     param_spec_char,
941     0,
942     |x| x
943 );
944 
945 define_param_spec_numeric!(
946     ParamSpecUChar,
947     gobject_ffi::GParamSpecUChar,
948     u8,
949     param_spec_uchar,
950     1,
951     |x| x
952 );
953 
954 define_param_spec!(
955     ParamSpecBoolean,
956     gobject_ffi::GParamSpecBoolean,
957     param_spec_bool,
958     2
959 );
960 
961 define_param_spec_default!(ParamSpecBoolean, bool, |x| from_glib(x));
962 
963 define_param_spec_numeric!(
964     ParamSpecInt,
965     gobject_ffi::GParamSpecInt,
966     i32,
967     param_spec_int,
968     3,
969     |x| x
970 );
971 
972 define_param_spec_numeric!(
973     ParamSpecUInt,
974     gobject_ffi::GParamSpecUInt,
975     u32,
976     param_spec_uint,
977     4,
978     |x| x
979 );
980 
981 define_param_spec_numeric!(
982     ParamSpecLong,
983     gobject_ffi::GParamSpecLong,
984     libc::c_long,
985     param_spec_long,
986     5,
987     |x| x
988 );
989 
990 define_param_spec_numeric!(
991     ParamSpecULong,
992     gobject_ffi::GParamSpecULong,
993     libc::c_ulong,
994     param_spec_ulong,
995     6,
996     |x| x
997 );
998 
999 define_param_spec_numeric!(
1000     ParamSpecInt64,
1001     gobject_ffi::GParamSpecInt64,
1002     i64,
1003     param_spec_int64,
1004     7,
1005     |x| x
1006 );
1007 
1008 define_param_spec_numeric!(
1009     ParamSpecUInt64,
1010     gobject_ffi::GParamSpecUInt64,
1011     u64,
1012     param_spec_uint64,
1013     8,
1014     |x| x
1015 );
1016 
1017 define_param_spec!(
1018     ParamSpecUnichar,
1019     gobject_ffi::GParamSpecUnichar,
1020     param_spec_unichar,
1021     9
1022 );
1023 
1024 define_param_spec_default!(ParamSpecUnichar, Result<char, CharTryFromError>, TryFrom::try_from);
1025 
1026 define_param_spec!(
1027     ParamSpecEnum,
1028     gobject_ffi::GParamSpecEnum,
1029     param_spec_enum,
1030     10
1031 );
1032 
1033 define_param_spec_default!(ParamSpecEnum, i32, |x| x);
1034 
1035 impl ParamSpecEnum {
1036     #[doc(alias = "get_enum_class")]
enum_class(&self) -> crate::EnumClass1037     pub fn enum_class(&self) -> crate::EnumClass {
1038         unsafe {
1039             let ptr = self.to_glib_none().0;
1040 
1041             assert!(!(*ptr).enum_class.is_null());
1042 
1043             crate::EnumClass::new(from_glib((*(*ptr).enum_class).g_type_class.g_type))
1044                 .expect("Invalid enum class")
1045         }
1046     }
1047 }
1048 
1049 define_param_spec!(
1050     ParamSpecFlags,
1051     gobject_ffi::GParamSpecFlags,
1052     param_spec_flags,
1053     11
1054 );
1055 
1056 define_param_spec_default!(ParamSpecFlags, u32, |x| x);
1057 
1058 impl ParamSpecFlags {
1059     #[doc(alias = "get_flags_class")]
flags_class(&self) -> crate::FlagsClass1060     pub fn flags_class(&self) -> crate::FlagsClass {
1061         unsafe {
1062             let ptr = self.to_glib_none().0;
1063 
1064             assert!(!(*ptr).flags_class.is_null());
1065 
1066             crate::FlagsClass::new(from_glib((*(*ptr).flags_class).g_type_class.g_type))
1067                 .expect("Invalid flags class")
1068         }
1069     }
1070 }
1071 
1072 define_param_spec_numeric!(
1073     ParamSpecFloat,
1074     gobject_ffi::GParamSpecFloat,
1075     f32,
1076     param_spec_float,
1077     12,
1078     |x| x
1079 );
1080 
1081 define_param_spec_numeric!(
1082     ParamSpecDouble,
1083     gobject_ffi::GParamSpecDouble,
1084     f64,
1085     param_spec_double,
1086     13,
1087     |x| x
1088 );
1089 
1090 define_param_spec!(
1091     ParamSpecString,
1092     gobject_ffi::GParamSpecString,
1093     param_spec_string,
1094     14
1095 );
1096 
1097 define_param_spec_default!(ParamSpecString, Option<&str>, |x: *mut libc::c_char| {
1098     use std::ffi::CStr;
1099 
1100     if x.is_null() {
1101         None
1102     } else {
1103         Some(CStr::from_ptr(x).to_str().unwrap())
1104     }
1105 });
1106 
1107 define_param_spec!(
1108     ParamSpecParam,
1109     gobject_ffi::GParamSpecParam,
1110     param_spec_param,
1111     15
1112 );
1113 
1114 define_param_spec!(
1115     ParamSpecBoxed,
1116     gobject_ffi::GParamSpecBoxed,
1117     param_spec_boxed,
1118     16
1119 );
1120 
1121 define_param_spec!(
1122     ParamSpecPointer,
1123     gobject_ffi::GParamSpecPointer,
1124     param_spec_pointer,
1125     17
1126 );
1127 
1128 define_param_spec!(
1129     ParamSpecValueArray,
1130     gobject_ffi::GParamSpecValueArray,
1131     param_spec_value_array,
1132     18
1133 );
1134 
1135 impl ParamSpecValueArray {
1136     #[doc(alias = "get_element_spec")]
element_spec(&self) -> Option<ParamSpec>1137     pub fn element_spec(&self) -> Option<ParamSpec> {
1138         unsafe {
1139             let ptr = self.to_glib_none().0;
1140 
1141             from_glib_none((*ptr).element_spec)
1142         }
1143     }
1144 
1145     #[doc(alias = "get_fixed_n_elements")]
fixed_n_elements(&self) -> u321146     pub fn fixed_n_elements(&self) -> u32 {
1147         unsafe {
1148             let ptr = self.to_glib_none().0;
1149 
1150             (*ptr).fixed_n_elements
1151         }
1152     }
1153 }
1154 
1155 define_param_spec!(
1156     ParamSpecObject,
1157     gobject_ffi::GParamSpecObject,
1158     param_spec_object,
1159     19
1160 );
1161 
1162 define_param_spec!(
1163     ParamSpecOverride,
1164     gobject_ffi::GParamSpecOverride,
1165     param_spec_override,
1166     20
1167 );
1168 
1169 impl ParamSpecOverride {
1170     #[doc(alias = "get_overridden")]
overridden(&self) -> ParamSpec1171     pub fn overridden(&self) -> ParamSpec {
1172         unsafe {
1173             let ptr = self.to_glib_none().0;
1174 
1175             from_glib_none((*ptr).overridden)
1176         }
1177     }
1178 }
1179 
1180 define_param_spec!(
1181     ParamSpecGType,
1182     gobject_ffi::GParamSpecGType,
1183     param_spec_gtype,
1184     21
1185 );
1186 
1187 define_param_spec!(
1188     ParamSpecVariant,
1189     gobject_ffi::GParamSpecVariant,
1190     param_spec_variant,
1191     22
1192 );
1193 
1194 define_param_spec_default!(
1195     ParamSpecVariant,
1196     Option<crate::Variant>,
1197     |x: *mut ffi::GVariant| from_glib_none(x)
1198 );
1199 
1200 impl ParamSpecVariant {
1201     #[doc(alias = "get_type")]
type_(&self) -> Option<&crate::VariantTy>1202     pub fn type_(&self) -> Option<&crate::VariantTy> {
1203         unsafe {
1204             let ptr = self.to_glib_none().0;
1205 
1206             if (*ptr).type_.is_null() {
1207                 None
1208             } else {
1209                 Some(crate::VariantTy::from_ptr((*ptr).type_))
1210             }
1211         }
1212     }
1213 }
1214 
1215 #[cfg(test)]
1216 mod tests {
1217     use super::*;
1218 
1219     #[test]
test_param_spec_string()1220     fn test_param_spec_string() {
1221         let pspec = ParamSpec::new_string(
1222             "name",
1223             "nick",
1224             "blurb",
1225             Some("default"),
1226             ParamFlags::READWRITE,
1227         );
1228 
1229         assert_eq!(pspec.name(), "name");
1230         assert_eq!(pspec.nick(), "nick");
1231         assert_eq!(pspec.blurb(), "blurb");
1232         let default_value = pspec.default_value();
1233         assert_eq!(default_value.get::<&str>().unwrap(), "default");
1234         assert_eq!(pspec.flags(), ParamFlags::READWRITE);
1235         assert_eq!(pspec.value_type(), Type::STRING);
1236         assert_eq!(pspec.type_(), ParamSpecString::static_type());
1237 
1238         let pspec_ref = pspec
1239             .downcast_ref::<ParamSpecString>()
1240             .expect("Not a string param spec");
1241         assert_eq!(pspec_ref.default_value(), Some("default"));
1242 
1243         let pspec = pspec
1244             .downcast::<ParamSpecString>()
1245             .expect("Not a string param spec");
1246         assert_eq!(pspec.default_value(), Some("default"));
1247     }
1248 }
1249