glib_signal/
macros.rs

1/// A helper that impls [Signal](crate::Signal) and its related traits.
2///
3/// ## Syntax
4///
5/// ```
6/// use glib_signal::{impl_signal, SignalFlags};
7/// # use glib::Object as AnObject;
8/// # #[derive(Copy, Clone, Debug)] struct SignalType;
9/// impl_signal! { impl Notifies<"signal-name" as SignalType> for AnObject {
10///     //impl {const SIGNAL_NAME}; // provide a convenient accessor for the default signal handler
11///     impl BuildSignal; // provide a default impl to facilitate GObject type construction
12///     FLAGS = SignalFlags::NO_RECURSE; // optionally specify flags for the signal when building
13///     fn(&self, String) // finally, specify the callback handler signature (with optional return type)
14/// } }
15/// ```
16///
17/// ## Implements
18///
19/// - [Notifies<`SignalType`>](crate::Notifies) for `AnObject`
20/// - [Signal](crate::Signal) for `SignalType`
21/// - [BuildSignal](crate::BuildSignal) for `SignalType`, for use with
22///   [glib::ObjectImpl](glib::subclass::object::ObjectImpl::signals) (opt-in)
23#[macro_export]
24macro_rules! impl_signal {
25	(impl Notifies<$signal_str:literal as $signal:path> for $obj:path {
26		$(impl $imp:tt;)*
27		$(FLAGS = $flags:expr;)*
28		fn $($handler:tt)*
29	}) => {
30		impl $crate::Signal for $signal {
31			type Object = $obj;
32			$crate::_impl_signal_private! { @line Handler fn $($handler)* }
33			$(
34				$crate::_impl_signal_private! { @line FLAGS $flags }
35			)*
36
37			const NAME: &'static str = $signal_str;
38		}
39
40		impl $crate::Notifies<$signal> for $obj { }
41		$(
42			$crate::_impl_signal_private! { @impl ($signal) ($obj) $imp }
43		)*
44	};
45}
46
47#[macro_export]
48#[doc(hidden)]
49macro_rules! _impl_signal_private {
50	(@ty $ty:ty) => { $ty };
51	(@args (&self $(,$args:ty)*)) => {
52		($($args,)*)
53	};
54	(@line Handler fn $args:tt -> $($res:tt)+) => {
55		type Arguments = $crate::_impl_signal_private! { @args $args };
56		type Return = $crate::_impl_signal_private! { @ty $($res)* };
57	};
58	(@line Handler fn $args:tt) => {
59		type Arguments = $crate::_impl_signal_private! { @args $args };
60		type Return = $crate::PrimitiveValue<()>;
61	};
62	(@line FLAGS $flags:expr) => {
63		const FLAGS: $crate::glib::SignalFlags = $flags;
64	};
65	(@impl ($signal:path) ($obj:path) BuildSignal) => {
66		impl $crate::BuildSignal for $signal { }
67	};
68	(@impl ($signal:path) ($obj:path) {const $signal_const:ident}) => {
69		impl $obj {
70			pub const $signal_const: $signal = $signal;
71		}
72	};
73}
74
75/// The same syntax as [impl_signal], but also defines the corresponding signal struct.
76#[macro_export]
77macro_rules! def_signal {
78	(
79		$(#[$meta:meta])*
80		impl Notifies<$signal_str:literal as $signal:tt> for $obj:path { $($inner:tt)* }
81	) => {
82		$(
83			#[$meta]
84		)*
85		#[derive(Copy, Clone, Debug)]
86		pub struct $signal;
87
88		$crate::impl_signal! {
89			impl Notifies<$signal_str as $signal> for $obj {
90				$($inner)*
91			}
92		}
93	};
94}