1#![doc = include_str!("../README.md")]
2#![forbid(unsafe_code)]
3#![warn(missing_docs)]
4
5pub mod center;
7
8use egui::{Align, Label, Layout, Ui, UiBuilder, Vec2, WidgetText};
9
10pub use concat_idents::concat_idents;
11
12pub fn measure_text(ui: &mut Ui, text: impl Into<WidgetText>) -> Vec2 {
14 let res = Label::new(text).layout_in_ui(
16 &mut ui.new_child(
17 UiBuilder::new()
18 .max_rect(ui.available_rect_before_wrap())
19 .layout(Layout::left_to_right(Align::Center)),
20 ),
21 );
22
23 res.2.rect.size() + Vec2::new(0.1, 0.0)
26}
27
28pub fn current_scroll_delta(ui: &Ui) -> Vec2 {
30 -ui.min_rect().min.to_vec2()
31}
32
33#[cfg(all(feature = "tokio", not(target_arch = "wasm32")))]
35pub fn spawn(future: impl std::future::Future<Output = ()> + Send + 'static) {
36 tokio::task::spawn(future);
37}
38
39#[cfg(all(feature = "async", target_arch = "wasm32"))]
41pub fn spawn(future: impl std::future::Future<Output = ()> + 'static) {
42 wasm_bindgen_futures::spawn_local(future);
43}
44
45#[cfg(all(feature = "async", not(feature = "tokio"), not(target_arch = "wasm32")))]
46compile_error!("You need to enable the `tokio` feature to use this crate on native. If you need a different async runtime, please open an issue (should be easy to add).");
47
48#[macro_export]
50macro_rules! call_self_fn {
51 ($path:path, &mut $self:expr, ($($arg:expr,)*)) => {
52 $path($self, $($arg,)*)
53 };
54 ($path:path, mut $self:expr, ($($arg:expr,)*)) => {
55 $path($self, $($arg,)*)
56 };
57 ($path:path, &$self:expr, ($($arg:expr,)*)) => {
58 $path($self, $($arg,)*)
59 };
60 ($path:path, $self:expr, ($($arg:expr,)*)) => {
61 $path($self, $($arg,)*)
62 };
63 ($path:path, ($($arg:expr,)*)) => {
64 $path($($arg,)*)
65 };
66}
67
68#[macro_export]
70macro_rules! async_fn_def {
71 (
72 $(#[$docs:meta])*
73 $body:block,
75 $name:ident,
77 $callback_fn_path:path,
79 ($($(;$mutt:ident)? $arg:ident: $_type:ty,)*)
81 ($($call_args:ident,)*)
83 ($($gen:tt)*),
85 ($($return_type:tt)*),
87 ($($callback_body_self:tt)*),
89 ) => {
90 $crate::concat_idents!(fn_name = $name, _async {
92 $(#[$docs])*
93 #[doc = concat!("This is the async version of `", stringify!($name), "`")]
94 #[allow(unused_mut)]
95 pub fn fn_name$($gen)*(
96 $($callback_body_self)*
97 $($($mutt)? $arg: $_type,)*
98 ) -> $($return_type)* {
99 let callback = $body;
100
101 $crate::call_self_fn!{
103 $callback_fn_path,
104 $($callback_body_self)*
105 ($($call_args,)*
106 callback,)
107 }
108 }
109 });
110 };
111}
112
113#[macro_export]
115macro_rules! fn_def {
116 (
117 $(#[$docs:meta])*
118 $body:block,
120 $name:ident,
122 $($arg:ident: $_type:ty,)*
124 ($($gen:tt)*),
126 ($($return_type:tt)*),
128 ($($callback_body_self:tt)*),
130 ) => {
131 $(#[$docs])*
132 pub fn $name $($gen)*(
133 $($callback_body_self)*
134 $($arg: $_type,)*
135 ) -> $($return_type)* {
136 $body
137 }
138 };
139}
140
141#[macro_export]
143macro_rules! fnify {
144 (
145 $(#[$docs:meta])*
146 $name:ident,
147 body: $body:block,
148 parameters: ($($arg:ident: $_type:ty,)*),
149 async_body: $async_body:block,
150 async_parameters: ($(;$async_mutt:ident)? $($async_arg:ident: $async_type:ty,)*),
151 call_args: ($($call_args:ident,)*),
152 generics: ($($gen:tt)*),
153 async_generics: ($($async_gen:tt)*),
154 return_type: ($($return_type:tt)*),
155 call_prefix: ($($call_prefix:tt)*),
156 callback_body_self: ($($callback_body_self:tt)*),
157 ) => {
158 $crate::fn_def!(
159 $(#[$docs])*
160 $body,
161 $name,
162 $($arg: $_type,)*
163 ($($gen)*),
164 ($($return_type)*),
165 ($($callback_body_self)*),
166 );
167
168 #[cfg(feature = "async")]
169 $crate::async_fn_def!(
170 $(#[$docs])*
171 $async_body,
172 $name,
173 $($call_prefix)*$name,
174 ($(;$async_mutt)? $($async_arg: $async_type,)*)
175 ($($call_args,)*)
176 ($($async_gen)*),
177 ($($return_type)*),
178 ($($callback_body_self)*),
179 );
180 };
181}
182
183#[macro_export]
185macro_rules! asyncify {
186 (
187 $(#[$docs:meta])*
188 $name:ident,
189 $callback_name:ident: (impl FnMut($callback_type:ty, $($closure_arg_name:ident: $closure_arg:ty,)*) $($bounds:tt)*),
190 call_prefix: ($($call_prefix:tt)*),
191 generics: ($($gen:tt)*),
192 async_generics: ($($async_gen:tt)*),
193 parameters: ($($arg:ident: $_type:ty,)*),
194 future: $future:ty,
195 return_type: ($($return_type:tt)*),
196 body: |($($callback_body_self:tt)*)| $body:block,
197 ) => {
198 $crate::fnify!{
199 $(#[$docs])*
200 $name,
201 body: $body,
202 parameters: ($($arg: $_type,)* $callback_name: impl FnMut($($closure_arg,)* $callback_type) $($bounds)*,),
203 async_body: {
204 Box::new(move |$($closure_arg_name: $closure_arg,)* callback: $callback_type| {
205 let fut = future_fn($($closure_arg_name,)*);
206 $crate::spawn(async move {
207 let res = fut.await;
208 callback(res);
209 })
210 })
211 },
212 async_parameters: ($($arg: $_type,)* ;mut future_fn: $future,),
213 call_args: ($($arg,)*),
214 generics: ($($gen)*),
215 async_generics: ($($async_gen)*),
216 return_type: ($($return_type)*),
217 call_prefix: ($($call_prefix)*),
218 callback_body_self: ($($callback_body_self)*),
219 }
220 };
221 (
222 $(#[$docs:meta])*
223 $name:ident,
224 $callback_name:ident: (impl FnOnce($callback_type:ty) $($bounds:tt)*),
225 call_prefix: ($($call_prefix:tt)*),
226 generics: ($($gen:tt)*),
227 async_generics: ($($async_gen:tt)*),
228 parameters: ($($arg:ident: $_type:ty,)*),
229 future: $future:ty,
230 return_type: ($($return_type:tt)*),
231 body: |($($callback_body_self:tt)*)| $body:block,
232 ) => {
233 $crate::fnify!{
234 $(#[$docs])*
235 $name,
236 body: $body,
237 parameters: ($($arg: $_type,)* $callback_name: impl FnOnce($callback_type) $($bounds)*,),
238 async_body: {
239 Box::new(move |callback: $callback_type| {
240 let fut = future;
241 $crate::spawn(async move {
242 let res = fut.await;
243 callback(res);
244 })
245 })
246 },
247 async_parameters: ($($arg: $_type,)* ;mut future: $future,),
248 call_args: ($($arg,)*),
249 generics: ($($gen)*),
250 async_generics: ($($async_gen)*),
251 return_type: ($($return_type)*),
252 call_prefix: ($($call_prefix)*),
253 callback_body_self: ($($callback_body_self)*),
254 }
255 };
256}
257
258#[cfg(target_arch = "wasm32")]
260pub type CallbackType<T> = Box<dyn FnOnce(T)>;
261#[cfg(not(target_arch = "wasm32"))]
263pub type CallbackType<T> = Box<dyn FnOnce(T) + Send + Sync>;
264
265#[cfg(not(target_arch = "wasm32"))]
266mod sync {
267 pub use Send as MaybeSend;
269 pub use Sync as MaybeSync;
271}
272#[cfg(target_arch = "wasm32")]
273mod unsync {
274 pub trait MaybeSend {}
276
277 impl<T> MaybeSend for T where T: ?Sized {}
278
279 pub trait MaybeSync {}
281
282 impl<T> MaybeSync for T where T: ?Sized {}
283}
284
285#[cfg(not(target_arch = "wasm32"))]
286pub use sync::*;
287
288#[cfg(target_arch = "wasm32")]
289pub use unsync::*;