1use glib::{Object, Type, Value, translate::*, value::FromValue};
4
5use crate::{Expression, ffi, prelude::*};
6
7#[doc(hidden)]
8impl AsRef<Expression> for Expression {
9 #[inline]
10 fn as_ref(&self) -> &Expression {
11 self
12 }
13}
14
15pub unsafe trait IsExpression:
23 StaticType + FromGlibPtrFull<*mut ffi::GtkExpression> + 'static
24{
25}
26
27impl Expression {
28 #[inline]
29 pub fn upcast(self) -> Self {
30 self
31 }
32
33 #[inline]
34 pub fn upcast_ref(&self) -> &Self {
35 self
36 }
37
38 #[inline]
39 pub fn is<E: IsExpression>(&self) -> bool {
40 self.type_().is_a(E::static_type())
41 }
42
43 #[inline]
44 pub fn downcast<E: IsExpression>(self) -> Result<E, Expression> {
45 unsafe {
46 if self.is::<E>() {
47 Ok(from_glib_full(self.into_glib_ptr()))
48 } else {
49 Err(self)
50 }
51 }
52 }
53
54 #[inline]
55 pub fn downcast_ref<E: IsExpression>(&self) -> Option<&E> {
56 unsafe {
57 if self.is::<E>() {
58 Some(&*(self as *const Expression as *const E))
59 } else {
60 None
61 }
62 }
63 }
64
65 #[inline]
66 pub fn type_(&self) -> Type {
67 unsafe {
68 let ptr = self.as_ptr();
69 from_glib((*(*(ptr as *mut glib::gobject_ffi::GTypeInstance)).g_class).g_type)
70 }
71 }
72
73 #[doc(alias = "gtk_expression_evaluate")]
74 pub fn evaluate(&self, this: Option<&impl IsA<Object>>) -> Option<Value> {
75 assert_initialized_main_thread!();
76 unsafe {
77 let mut value = Value::uninitialized();
78 let ret = ffi::gtk_expression_evaluate(
79 self.to_glib_none().0,
80 this.map(|t| t.as_ref()).to_glib_none().0,
81 value.to_glib_none_mut().0,
82 );
83 if from_glib(ret) { Some(value) } else { None }
84 }
85 }
86
87 #[doc(alias = "gtk_expression_evaluate")]
91 pub fn evaluate_as<V: for<'b> FromValue<'b> + 'static, T: IsA<Object>>(
92 &self,
93 this: Option<&T>,
94 ) -> Option<V> {
95 self.evaluate(this).map(|v| {
96 v.get_owned::<V>()
97 .expect("Failed to evaluate to this value type")
98 })
99 }
100
101 pub fn chain_property<T: IsA<glib::Object>>(
106 &self,
107 property_name: &str,
108 ) -> crate::PropertyExpression {
109 crate::PropertyExpression::new(T::static_type(), Some(self), property_name)
110 }
111
112 pub fn chain_closure<R>(&self, closure: glib::RustClosure) -> crate::ClosureExpression
141 where
142 R: glib::value::ValueType,
143 {
144 crate::ClosureExpression::new::<R>([self], closure)
145 }
146
147 pub fn chain_closure_with_callback<F, R>(&self, f: F) -> crate::ClosureExpression
152 where
153 F: Fn(&[glib::Value]) -> R + 'static,
154 R: glib::value::ValueType,
155 {
156 crate::ClosureExpression::with_callback([self], f)
157 }
158
159 #[cfg(feature = "v4_22")]
160 #[cfg_attr(docsrs, doc(cfg(feature = "v4_22")))]
161 pub fn chain_try(&self, fallback: impl AsRef<Expression>) -> crate::TryExpression {
166 crate::TryExpression::new([self, fallback.as_ref()])
167 }
168}
169
170impl std::fmt::Debug for Expression {
171 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
172 f.debug_struct("Expression")
173 .field("value_type", &self.value_type())
174 .field("is_static", &self.is_static())
175 .finish()
176 }
177}
178
179impl glib::value::ValueType for Expression {
180 type Type = Self;
181}
182
183unsafe impl<'a> glib::value::FromValue<'a> for Expression {
184 type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
185
186 #[inline]
187 unsafe fn from_value(value: &'a glib::Value) -> Self {
188 unsafe {
189 skip_assert_initialized!();
190 from_glib_full(crate::ffi::gtk_value_dup_expression(value.to_glib_none().0))
191 }
192 }
193}
194
195impl glib::value::ToValue for Expression {
196 #[inline]
197 fn to_value(&self) -> glib::Value {
198 let mut value = glib::Value::for_value_type::<Self>();
199 unsafe {
200 crate::ffi::gtk_value_set_expression(value.to_glib_none_mut().0, self.to_glib_none().0)
201 }
202 value
203 }
204
205 #[inline]
206 fn value_type(&self) -> glib::Type {
207 Self::static_type()
208 }
209}
210
211impl glib::value::ToValueOptional for Expression {
212 fn to_value_optional(s: Option<&Self>) -> glib::Value {
213 skip_assert_initialized!();
214 let mut value = glib::Value::for_value_type::<Self>();
215 unsafe {
216 crate::ffi::gtk_value_set_expression(value.to_glib_none_mut().0, s.to_glib_none().0)
217 }
218 value
219 }
220}
221
222impl From<Expression> for glib::Value {
223 fn from(e: Expression) -> Self {
224 skip_assert_initialized!();
225 let mut value = glib::Value::for_value_type::<Expression>();
226 unsafe {
227 crate::ffi::gtk_value_take_expression(value.to_glib_none_mut().0, e.into_glib_ptr())
228 }
229 value
230 }
231}
232
233pub trait GObjectPropertyExpressionExt: IsA<glib::Object> {
253 fn property_expression(&self, property_name: &str) -> crate::PropertyExpression {
256 let obj_expr = crate::ConstantExpression::new(self);
257 crate::PropertyExpression::new(Self::static_type(), Some(&obj_expr), property_name)
258 }
259
260 fn property_expression_weak(&self, property_name: &str) -> crate::PropertyExpression {
264 let obj_expr = crate::ObjectExpression::new(self);
265 crate::PropertyExpression::new(Self::static_type(), Some(&obj_expr), property_name)
266 }
267
268 fn this_expression(property_name: &str) -> crate::PropertyExpression {
271 skip_assert_initialized!();
272 crate::PropertyExpression::new(Self::static_type(), Expression::NONE, property_name)
273 }
274}
275
276impl<O: IsA<glib::Object>> GObjectPropertyExpressionExt for O {}
277
278macro_rules! define_expression {
279 ($rust_type:ident, $ffi_type:path) => {
280 impl std::ops::Deref for $rust_type {
281 type Target = crate::Expression;
282
283 #[inline]
284 fn deref(&self) -> &Self::Target {
285 unsafe { &*(self as *const $rust_type as *const crate::Expression) }
286 }
287 }
288
289 impl AsRef<crate::Expression> for $rust_type {
290 #[inline]
291 fn as_ref(&self) -> &crate::Expression {
292 self.upcast_ref()
293 }
294 }
295
296 impl $rust_type {
297 #[inline]
298 pub fn upcast(self) -> crate::Expression {
299 unsafe { std::mem::transmute(self) }
300 }
301
302 #[inline]
303 pub fn upcast_ref(&self) -> &crate::Expression {
304 self
305 }
306 }
307
308 #[doc(hidden)]
309 impl<'a> ToGlibPtr<'a, *const crate::ffi::GtkExpression> for $rust_type {
310 type Storage =
311 ::std::marker::PhantomData<&'a $crate::glib::shared::Shared<$ffi_type, $rust_type>>;
312
313 #[inline]
314 fn to_glib_none(
315 &'a self,
316 ) -> $crate::glib::translate::Stash<'a, *const crate::ffi::GtkExpression, Self> {
317 let stash =
318 $crate::glib::translate::ToGlibPtr::<*const $ffi_type>::to_glib_none(self);
319 $crate::glib::translate::Stash(stash.0 as *const _, stash.1)
320 }
321
322 #[inline]
323 fn to_glib_full(&self) -> *const crate::ffi::GtkExpression {
324 $crate::glib::translate::ToGlibPtr::<*const $ffi_type>::to_glib_full(self)
325 as *const _
326 }
327 }
328
329 #[doc(hidden)]
330 impl<'a> ToGlibPtr<'a, *mut crate::ffi::GtkExpression> for $rust_type {
331 type Storage =
332 ::std::marker::PhantomData<&'a $crate::glib::shared::Shared<$ffi_type, $rust_type>>;
333
334 #[inline]
335 fn to_glib_none(
336 &'a self,
337 ) -> $crate::glib::translate::Stash<'a, *mut crate::ffi::GtkExpression, Self> {
338 let stash =
339 $crate::glib::translate::ToGlibPtr::<*mut $ffi_type>::to_glib_none(self);
340 $crate::glib::translate::Stash(stash.0 as *mut _, stash.1)
341 }
342
343 #[inline]
344 fn to_glib_full(&self) -> *mut crate::ffi::GtkExpression {
345 $crate::glib::translate::ToGlibPtr::<*mut $ffi_type>::to_glib_full(self) as *mut _
346 }
347 }
348
349 #[doc(hidden)]
350 impl IntoGlibPtr<*mut crate::ffi::GtkExpression> for $rust_type {
351 #[inline]
352 fn into_glib_ptr(self) -> *mut crate::ffi::GtkExpression {
353 let s = std::mem::ManuallyDrop::new(self);
354 s.to_glib_none().0
355 }
356 }
357
358 #[doc(hidden)]
359 impl IntoGlibPtr<*const crate::ffi::GtkExpression> for $rust_type {
360 #[inline]
361 fn into_glib_ptr(self) -> *const crate::ffi::GtkExpression {
362 let s = std::mem::ManuallyDrop::new(self);
363 s.to_glib_none().0
364 }
365 }
366
367 #[doc(hidden)]
368 impl FromGlibPtrFull<*mut crate::ffi::GtkExpression> for $rust_type {
369 #[inline]
370 unsafe fn from_glib_full(ptr: *mut crate::ffi::GtkExpression) -> Self {
371 unsafe { from_glib_full(ptr as *mut $ffi_type) }
372 }
373 }
374
375 unsafe impl crate::expression::IsExpression for $rust_type {}
376
377 impl glib::value::ValueType for $rust_type {
378 type Type = Self;
379 }
380
381 unsafe impl<'a> glib::value::FromValue<'a> for $rust_type {
382 type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
383
384 #[inline]
385 unsafe fn from_value(value: &'a glib::Value) -> Self {
386 unsafe {
387 skip_assert_initialized!();
388 from_glib_full(crate::ffi::gtk_value_dup_expression(value.to_glib_none().0))
389 }
390 }
391 }
392
393 impl glib::value::ToValue for $rust_type {
394 #[inline]
395 fn to_value(&self) -> glib::Value {
396 let mut value = glib::Value::for_value_type::<Self>();
397 unsafe {
398 crate::ffi::gtk_value_set_expression(
399 value.to_glib_none_mut().0,
400 self.as_ptr() as *mut _,
401 )
402 }
403 value
404 }
405
406 #[inline]
407 fn value_type(&self) -> glib::Type {
408 use glib::prelude::StaticType;
409 Self::static_type()
410 }
411 }
412
413 impl glib::value::ToValueOptional for $rust_type {
414 #[inline]
415 fn to_value_optional(s: Option<&Self>) -> glib::Value {
416 skip_assert_initialized!();
417 let mut value = glib::Value::for_value_type::<Self>();
418 unsafe {
419 crate::ffi::gtk_value_set_expression(
420 value.to_glib_none_mut().0,
421 s.map(|s| s.as_ptr()).unwrap_or(std::ptr::null_mut()) as *mut _,
422 )
423 }
424 value
425 }
426 }
427
428 impl From<$rust_type> for glib::Value {
429 fn from(e: $rust_type) -> Self {
430 skip_assert_initialized!();
431 let mut value = glib::Value::for_value_type::<$rust_type>();
432 unsafe {
433 crate::ffi::gtk_value_take_expression(
434 value.to_glib_none_mut().0,
435 e.into_glib_ptr(),
436 )
437 }
438 value
439 }
440 }
441
442 impl glib::HasParamSpec for $rust_type {
443 type ParamSpec = crate::ParamSpecExpression;
444
445 type SetValue = $rust_type;
446
447 type BuilderFn = for<'a> fn(&'a str) -> crate::builders::ParamSpecExpressionBuilder<'a>;
448
449 fn param_spec_builder() -> Self::BuilderFn {
450 Self::ParamSpec::builder
451 }
452 }
453 };
454}