1use crate::{prelude::*, Settings};
2use glib::translate::*;
3use std::ffi::c_void;
4
5impl Settings {
6 #[doc(alias = "panel_settings_bind")]
7 #[doc(alias = "panel_settings_bind_with_mapping")]
8 pub fn bind<'a, P: IsA<glib::Object>>(
9 &'a self,
10 key: &'a str,
11 object: &'a P,
12 property: &'a str,
13 ) -> BindingBuilder<'a> {
14 BindingBuilder {
15 settings: self.upcast_ref(),
16 key,
17 object: object.upcast_ref(),
18 property,
19 flags: gio::SettingsBindFlags::DEFAULT,
20 get_mapping: None,
21 set_mapping: None,
22 }
23 }
24
25 #[doc(alias = "panel_settings_get_schema_id")]
26 #[doc(alias = "get_schema_id")]
27 pub fn schema_id(&self) -> &glib::GStr {
28 unsafe { from_glib_none(ffi::panel_settings_get_schema_id(self.to_glib_none().0)) }
29 }
30}
31
32#[must_use = "The builder must be built to be used"]
33pub struct BindingBuilder<'a> {
34 settings: &'a Settings,
35 key: &'a str,
36 object: &'a glib::Object,
37 property: &'a str,
38 flags: gio::SettingsBindFlags,
39 #[allow(clippy::type_complexity)]
40 get_mapping: Option<Box<dyn Fn(&glib::Variant, glib::Type) -> Option<glib::Value>>>,
41 #[allow(clippy::type_complexity)]
42 set_mapping: Option<Box<dyn Fn(&glib::Value, glib::VariantType) -> Option<glib::Variant>>>,
43}
44
45impl<'a> BindingBuilder<'a> {
46 pub fn flags(mut self, flags: gio::SettingsBindFlags) -> Self {
47 self.flags = flags;
48 self
49 }
50
51 pub fn get(mut self) -> Self {
54 self.flags |= gio::SettingsBindFlags::GET;
55 self
56 }
57
58 pub fn set(mut self) -> Self {
61 self.flags |= gio::SettingsBindFlags::SET;
62 self
63 }
64
65 pub fn set_only(mut self) -> Self {
68 self.flags = (self.flags - gio::SettingsBindFlags::GET) | gio::SettingsBindFlags::SET;
69 self
70 }
71
72 pub fn get_only(mut self) -> Self {
75 self.flags = (self.flags - gio::SettingsBindFlags::SET) | gio::SettingsBindFlags::GET;
76 self
77 }
78
79 pub fn no_sensitivity(mut self) -> Self {
82 self.flags |= gio::SettingsBindFlags::NO_SENSITIVITY;
83 self
84 }
85
86 pub fn get_no_changes(mut self) -> Self {
89 self.flags |= gio::SettingsBindFlags::GET_NO_CHANGES;
90 self
91 }
92
93 pub fn invert_boolean(mut self) -> Self {
96 self.flags |= gio::SettingsBindFlags::INVERT_BOOLEAN;
97 self
98 }
99
100 #[doc(alias = "get_mapping")]
101 pub fn mapping<F: Fn(&glib::Variant, glib::Type) -> Option<glib::Value> + 'static>(
102 mut self,
103 f: F,
104 ) -> Self {
105 self.get_mapping = Some(Box::new(f));
106 self
107 }
108
109 pub fn set_mapping<
110 F: Fn(&glib::Value, glib::VariantType) -> Option<glib::Variant> + 'static,
111 >(
112 mut self,
113 f: F,
114 ) -> Self {
115 self.set_mapping = Some(Box::new(f));
116 self
117 }
118
119 pub fn build(self) {
120 type Mappings = (
121 Option<Box<dyn Fn(&glib::Variant, glib::Type) -> Option<glib::Value>>>,
122 Option<Box<dyn Fn(&glib::Value, glib::VariantType) -> Option<glib::Variant>>>,
123 );
124 unsafe extern "C" fn bind_with_mapping_get_trampoline(
125 value: *mut glib::gobject_ffi::GValue,
126 variant: *mut glib::ffi::GVariant,
127 user_data: glib::ffi::gpointer,
128 ) -> glib::ffi::gboolean {
129 let user_data = &*(user_data as *const Mappings);
130 let f = user_data.0.as_ref().unwrap();
131 let value = &mut *(value as *mut glib::Value);
132 if let Some(v) = f(&from_glib_borrow(variant), value.type_()) {
133 *value = v;
134 true
135 } else {
136 false
137 }
138 .into_glib()
139 }
140 unsafe extern "C" fn bind_with_mapping_set_trampoline(
141 value: *const glib::gobject_ffi::GValue,
142 variant_type: *const glib::ffi::GVariantType,
143 user_data: glib::ffi::gpointer,
144 ) -> *mut glib::ffi::GVariant {
145 let user_data = &*(user_data as *const Mappings);
146 let f = user_data.1.as_ref().unwrap();
147 let value = &*(value as *const glib::Value);
148 f(value, from_glib_none(variant_type)).into_glib_ptr()
149 }
150 unsafe extern "C" fn destroy_closure(ptr: *mut c_void) {
151 let _ = Box::<Mappings>::from_raw(ptr as *mut _);
152 }
153
154 if self.get_mapping.is_none() && self.set_mapping.is_none() {
155 unsafe {
156 ffi::panel_settings_bind(
157 self.settings.to_glib_none().0,
158 self.key.to_glib_none().0,
159 ToGlibPtr::<*mut glib::gobject_ffi::GObject>::to_glib_none(&self.object).0
160 as *mut _,
161 self.property.to_glib_none().0,
162 self.flags.into_glib(),
163 );
164 }
165 } else {
166 let get_trampoline: Option<unsafe extern "C" fn(_, _, _) -> _> =
167 if self.get_mapping.is_none() {
168 None
169 } else {
170 Some(bind_with_mapping_get_trampoline)
171 };
172 let set_trampoline: Option<unsafe extern "C" fn(_, _, _) -> _> =
173 if self.set_mapping.is_none() {
174 None
175 } else {
176 Some(bind_with_mapping_set_trampoline)
177 };
178 let mappings: Mappings = (self.get_mapping, self.set_mapping);
179 unsafe {
180 ffi::panel_settings_bind_with_mapping(
181 self.settings.to_glib_none().0,
182 self.key.to_glib_none().0,
183 ToGlibPtr::<*mut glib::gobject_ffi::GObject>::to_glib_none(&self.object).0
184 as *mut _,
185 self.property.to_glib_none().0,
186 self.flags.into_glib(),
187 get_trampoline,
188 set_trampoline,
189 Box::into_raw(Box::new(mappings)) as *mut c_void,
190 Some(destroy_closure),
191 )
192 }
193 }
194 }
195}