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