1use raui_immediate::*;
2
3macro_rules! impl_imports {
4 () => {
5 #[allow(unused_imports)]
6 use raui_core::widget::component::{
7 containers::{
8 anchor_box::*, area_box::*, content_box::*, context_box::*, flex_box::*,
9 float_box::*, grid_box::*, hidden_box::*, horizontal_box::*, portal_box::*,
10 responsive_box::*, scroll_box::*, size_box::*, switch_box::*, tabs_box::*,
11 tooltip_box::*, variant_box::*, vertical_box::*, wrap_box::*,
12 },
13 interactive::{
14 button::*, float_view::*, input_field::*, navigation::*, options_view::*,
15 scroll_view::*, slider_view::*,
16 },
17 };
18 #[allow(unused_imports)]
19 use raui_core::widget::{
20 component::{image_box::*, space_box::*, text_box::*},
21 none_widget,
22 };
23 #[allow(unused_imports)]
24 use raui_material::component::{
25 containers::{
26 context_paper::*, flex_paper::*, grid_paper::*, horizontal_paper::*,
27 modal_paper::*, paper::*, scroll_paper::*, text_tooltip_paper::*, tooltip_paper::*,
28 vertical_paper::*, window_paper::*, wrap_paper::*,
29 },
30 interactive::{
31 button_paper::*, icon_button_paper::*, slider_paper::*, switch_button_paper::*,
32 text_button_paper::*, text_field_paper::*,
33 },
34 };
35 #[allow(unused_imports)]
36 use raui_material::component::{icon_paper::*, switch_paper::*, text_paper::*};
37 };
38}
39
40macro_rules! impl_slot_components {
41 ($($name:ident),+ $(,)?) => {
42 $(
43 pub fn $name<R>(
44 props: impl Into<raui_core::props::Props>,
45 f: impl FnMut() -> R,
46 ) -> R {
47 impl_imports!();
48 crate::slot_component(raui_core::make_widget!($name), props, f)
49 }
50 )+
51 };
52}
53
54macro_rules! impl_list_components {
55 ($($name:ident),+ $(,)?) => {
56 $(
57 pub fn $name<R>(
58 props: impl Into<raui_core::props::Props>,
59 f: impl FnMut() -> R,
60 ) -> R {
61 impl_imports!();
62 crate::list_component(raui_core::make_widget!($name), props, f)
63 }
64 )+
65 };
66}
67
68macro_rules! impl_content_components {
69 ($content:literal : $($name:ident),+ $(,)?) => {
70 $(
71 pub fn $name<R>(
72 props: impl Into<raui_core::props::Props>,
73 f: impl FnMut() -> R,
74 ) -> R {
75 impl_imports!();
76 crate::content_component(raui_core::make_widget!($name), $content, props, f)
77 }
78 )+
79 };
80}
81
82macro_rules! impl_components {
83 ($($name:ident),+ $(,)?) => {
84 $(
85 pub fn $name(
86 props: impl Into<raui_core::props::Props>,
87 ) {
88 impl_imports!();
89 crate::component(raui_core::make_widget!($name), props)
90 }
91 )+
92 };
93}
94
95pub mod core {
96 impl_components! {
97 image_box,
98 nav_scroll_box_side_scrollbars,
99 none_widget,
100 space_box,
101 text_box,
102 }
103
104 pub mod containers {
105 impl_content_components! {
106 "content":
107 anchor_box,
108 area_box,
109 hidden_box,
110 nav_scroll_box_content,
111 pivot_box,
112 portal_box,
113 size_box,
114 wrap_box,
115 }
116
117 impl_slot_components! {
118 context_box,
119 nav_scroll_box,
120 portals_context_box,
121 portals_tooltip_box,
122 responsive_props_box,
123 tooltip_box,
124 variant_box,
125 }
126
127 impl_list_components! {
128 content_box,
129 flex_box,
130 float_box,
131 grid_box,
132 horizontal_box,
133 nav_content_box,
134 nav_flex_box,
135 nav_float_box,
136 nav_grid_box,
137 nav_horizontal_box,
138 nav_switch_box,
139 nav_tabs_box,
140 nav_vertical_box,
141 responsive_box,
142 switch_box,
143 vertical_box,
144 }
145 }
146
147 pub mod interactive {
148 use raui_core::{
149 make_widget,
150 props::Props,
151 widget::{
152 component::interactive::{
153 button::ButtonProps,
154 input_field::{TextInputProps, TextInputState},
155 navigation::NavTrackingProps,
156 options_view::{OptionsViewProps, OptionsViewProxy},
157 slider_view::{SliderViewProps, SliderViewProxy},
158 },
159 utils::Vec2,
160 },
161 };
162 use raui_immediate::{begin, end, pop, push, use_state};
163 use std::str::FromStr;
164
165 #[derive(Debug, Default, Copy, Clone)]
166 pub struct ImmediateTracking {
167 pub state: NavTrackingProps,
168 pub prev: NavTrackingProps,
169 }
170
171 impl ImmediateTracking {
172 pub fn pointer_delta_factor(&self) -> Vec2 {
173 Vec2 {
174 x: self.state.factor.x - self.prev.factor.x,
175 y: self.state.factor.y - self.prev.factor.y,
176 }
177 }
178
179 pub fn pointer_delta_unscaled(&self) -> Vec2 {
180 Vec2 {
181 x: self.state.unscaled.x - self.prev.unscaled.x,
182 y: self.state.unscaled.y - self.prev.unscaled.y,
183 }
184 }
185
186 pub fn pointer_delta_ui_space(&self) -> Vec2 {
187 Vec2 {
188 x: self.state.ui_space.x - self.prev.ui_space.x,
189 y: self.state.ui_space.y - self.prev.ui_space.y,
190 }
191 }
192
193 pub fn pointer_moved(&self) -> bool {
194 (self.state.factor.x - self.prev.factor.x)
195 + (self.state.factor.y - self.prev.factor.y)
196 > 1.0e-6
197 }
198 }
199
200 #[derive(Debug, Default, Copy, Clone)]
201 pub struct ImmediateButton {
202 pub state: ButtonProps,
203 pub prev: ButtonProps,
204 }
205
206 impl ImmediateButton {
207 pub fn select_start(&self) -> bool {
208 !self.prev.selected && self.state.selected
209 }
210
211 pub fn select_stop(&self) -> bool {
212 self.prev.selected && !self.state.selected
213 }
214
215 pub fn select_changed(&self) -> bool {
216 self.prev.selected != self.state.selected
217 }
218
219 pub fn trigger_start(&self) -> bool {
220 !self.prev.trigger && self.state.trigger
221 }
222
223 pub fn trigger_stop(&self) -> bool {
224 self.prev.trigger && !self.state.trigger
225 }
226
227 pub fn trigger_changed(&self) -> bool {
228 self.prev.trigger != self.state.trigger
229 }
230
231 pub fn context_start(&self) -> bool {
232 !self.prev.context && self.state.context
233 }
234
235 pub fn context_stop(&self) -> bool {
236 self.prev.context && !self.state.context
237 }
238
239 pub fn context_changed(&self) -> bool {
240 self.prev.context != self.state.context
241 }
242 }
243
244 impl_content_components! {
245 "content":
246 float_view_control,
247 navigation_barrier,
248 }
249
250 pub fn tracking(
251 props: impl Into<Props>,
252 mut f: impl FnMut(ImmediateTracking),
253 ) -> ImmediateTracking {
254 use crate::internal::*;
255 let state = use_state(ImmediateTracking::default);
256 let result = state.read().unwrap().to_owned();
257 begin();
258 f(result);
259 let node = end().pop().unwrap_or_default();
260 push(
261 make_widget!(immediate_tracking)
262 .with_props(ImmediateTrackingProps { state: Some(state) })
263 .merge_props(props.into())
264 .named_slot("content", node),
265 );
266 result
267 }
268
269 pub fn self_tracking(
270 props: impl Into<Props>,
271 mut f: impl FnMut(ImmediateTracking),
272 ) -> ImmediateTracking {
273 use crate::internal::*;
274 let state = use_state(ImmediateTracking::default);
275 let result = state.read().unwrap().to_owned();
276 begin();
277 f(result);
278 let node = end().pop().unwrap_or_default();
279 push(
280 make_widget!(immediate_self_tracking)
281 .with_props(ImmediateTrackingProps { state: Some(state) })
282 .merge_props(props.into())
283 .named_slot("content", node),
284 );
285 result
286 }
287
288 pub fn button(
289 props: impl Into<Props>,
290 mut f: impl FnMut(ImmediateButton),
291 ) -> ImmediateButton {
292 use crate::internal::*;
293 let state = use_state(ImmediateButton::default);
294 let result = state.read().unwrap().to_owned();
295 begin();
296 f(result);
297 let node = end().pop().unwrap_or_default();
298 push(
299 make_widget!(immediate_button)
300 .with_props(ImmediateButtonProps { state: Some(state) })
301 .merge_props(props.into())
302 .named_slot("content", node),
303 );
304 result
305 }
306
307 pub fn tracked_button(
308 props: impl Into<Props>,
309 mut f: impl FnMut(ImmediateButton),
310 ) -> ImmediateButton {
311 use crate::internal::*;
312 let state = use_state(ImmediateButton::default);
313 let result = state.read().unwrap().to_owned();
314 begin();
315 f(result);
316 let node = end().pop().unwrap_or_default();
317 push(
318 make_widget!(immediate_tracked_button)
319 .with_props(ImmediateButtonProps { state: Some(state) })
320 .merge_props(props.into())
321 .named_slot("content", node),
322 );
323 result
324 }
325
326 pub fn self_tracked_button(
327 props: impl Into<Props>,
328 mut f: impl FnMut(ImmediateButton),
329 ) -> ImmediateButton {
330 use crate::internal::*;
331 let state = use_state(ImmediateButton::default);
332 let result = state.read().unwrap().to_owned();
333 begin();
334 f(result);
335 let node = end().pop().unwrap_or_default();
336 push(
337 make_widget!(immediate_self_tracked_button)
338 .with_props(ImmediateButtonProps { state: Some(state) })
339 .merge_props(props.into())
340 .named_slot("content", node),
341 );
342 result
343 }
344
345 pub fn text_input<T: ToString + FromStr + Send + Sync>(
346 value: &T,
347 props: impl Into<Props>,
348 mut f: impl FnMut(&str, TextInputState),
349 ) -> (Option<T>, TextInputState) {
350 use crate::internal::*;
351 let content = use_state(|| value.to_string());
352 let props = props.into();
353 let TextInputProps { allow_new_line, .. } = props.read_cloned_or_default();
354 let text_state = use_state(TextInputState::default);
355 let text_result = text_state.read().unwrap().to_owned();
356 if !text_result.focused {
357 *content.write().unwrap() = value.to_string();
358 }
359 let result = content.read().unwrap().to_string();
360 begin();
361 f(&result, text_result);
362 let node = end().pop().unwrap_or_default();
363 push(
364 make_widget!(immediate_text_input)
365 .with_props(ImmediateTextInputProps {
366 state: Some(text_state),
367 })
368 .merge_props(props)
369 .with_props(TextInputProps {
370 allow_new_line,
371 text: Some(content.into()),
372 })
373 .named_slot("content", node),
374 );
375 (result.parse().ok(), text_result)
376 }
377
378 pub fn input_field<T: ToString + FromStr + Send + Sync>(
379 value: &T,
380 props: impl Into<Props>,
381 mut f: impl FnMut(&str, TextInputState, ImmediateButton),
382 ) -> (Option<T>, TextInputState, ImmediateButton) {
383 use crate::internal::*;
384 let content = use_state(|| value.to_string());
385 let props = props.into();
386 let TextInputProps { allow_new_line, .. } = props.read_cloned_or_default();
387 let text_state = use_state(TextInputState::default);
388 let text_result = text_state.read().unwrap().to_owned();
389 let button_state = use_state(ImmediateButton::default);
390 let button_result = button_state.read().unwrap().to_owned();
391 if !text_result.focused {
392 *content.write().unwrap() = value.to_string();
393 }
394 let result = content.read().unwrap().to_string();
395 begin();
396 f(&result, text_result, button_result);
397 let node = end().pop().unwrap_or_default();
398 push(
399 make_widget!(immediate_input_field)
400 .with_props(ImmediateTextInputProps {
401 state: Some(text_state),
402 })
403 .with_props(ImmediateButtonProps {
404 state: Some(button_state),
405 })
406 .merge_props(props)
407 .with_props(TextInputProps {
408 allow_new_line,
409 text: Some(content.into()),
410 })
411 .named_slot("content", node),
412 );
413 (result.parse().ok(), text_result, button_result)
414 }
415
416 pub fn slider_view<T: SliderViewProxy + Clone + 'static>(
417 value: T,
418 props: impl Into<Props>,
419 mut f: impl FnMut(&T, ImmediateButton),
420 ) -> (T, ImmediateButton) {
421 use crate::internal::*;
422 let content = use_state(|| value.to_owned());
423 let props = props.into();
424 let SliderViewProps {
425 from,
426 to,
427 direction,
428 ..
429 } = props.read_cloned_or_default();
430 let button_state = use_state(ImmediateButton::default);
431 let button_result = button_state.read().unwrap().to_owned();
432 let result = content.read().unwrap().to_owned();
433 begin();
434 f(&result, button_result);
435 let node = end().pop().unwrap_or_default();
436 push(
437 make_widget!(immediate_slider_view)
438 .with_props(ImmediateButtonProps {
439 state: Some(button_state),
440 })
441 .merge_props(props)
442 .with_props(SliderViewProps {
443 input: Some(content.into()),
444 from,
445 to,
446 direction,
447 })
448 .named_slot("content", node),
449 );
450 (result, button_result)
451 }
452
453 pub fn options_view<T: OptionsViewProxy + Clone + 'static>(
454 value: T,
455 props: impl Into<Props>,
456 mut f_items: impl FnMut(&T),
457 mut f_content: impl FnMut(),
458 ) -> T {
459 let content = use_state(|| value.to_owned());
460 let props = props.into();
461 let result = content.read().unwrap().to_owned();
462 begin();
463 f_items(&result);
464 let nodes = end();
465 begin();
466 f_content();
467 let node = pop();
468 push(
469 make_widget!(raui_core::widget::component::interactive::options_view::options_view)
470 .merge_props(props)
471 .with_props(OptionsViewProps {
472 input: Some(content.into()),
473 })
474 .named_slot("content", node)
475 .listed_slots(nodes),
476 );
477 result
478 }
479 }
480}
481
482pub mod material {
483 impl_components! {
484 icon_paper,
485 scroll_paper_side_scrollbars,
486 switch_paper,
487 text_paper,
488 }
489
490 pub mod containers {
491 impl_slot_components! {
492 context_paper,
493 scroll_paper,
494 tooltip_paper,
495 window_paper,
496 window_title_controls_paper,
497 }
498
499 impl_content_components! {
500 "content":
501 modal_paper,
502 text_tooltip_paper,
503 wrap_paper,
504 }
505
506 impl_list_components! {
507 flex_paper,
508 grid_paper,
509 horizontal_paper,
510 nav_flex_paper,
511 nav_grid_paper,
512 nav_horizontal_paper,
513 nav_paper,
514 nav_vertical_paper,
515 paper,
516 vertical_paper,
517 }
518 }
519
520 pub mod interactive {
521 use crate::core::interactive::ImmediateButton;
522 use raui_core::{
523 make_widget,
524 props::Props,
525 widget::component::interactive::{
526 input_field::{TextInputProps, TextInputState},
527 slider_view::{SliderViewProps, SliderViewProxy},
528 },
529 };
530 use raui_immediate::{begin, end, push, use_state};
531 use std::str::FromStr;
532
533 pub fn button_paper(
534 props: impl Into<Props>,
535 mut f: impl FnMut(ImmediateButton),
536 ) -> ImmediateButton {
537 use crate::internal::*;
538 let state = use_state(ImmediateButton::default);
539 let result = state.read().unwrap().to_owned();
540 begin();
541 f(result);
542 let node = end().pop().unwrap_or_default();
543 push(
544 make_widget!(immediate_button_paper)
545 .with_props(ImmediateButtonProps { state: Some(state) })
546 .merge_props(props.into())
547 .named_slot("content", node),
548 );
549 result
550 }
551
552 pub fn icon_button_paper(props: impl Into<Props>) -> ImmediateButton {
553 use crate::internal::*;
554 let state = use_state(ImmediateButton::default);
555 let result = state.read().unwrap().to_owned();
556 push(
557 make_widget!(immediate_icon_button_paper)
558 .with_props(ImmediateButtonProps { state: Some(state) })
559 .merge_props(props.into()),
560 );
561 result
562 }
563
564 pub fn switch_button_paper(props: impl Into<Props>) -> ImmediateButton {
565 use crate::internal::*;
566 let state = use_state(ImmediateButton::default);
567 let result = state.read().unwrap().to_owned();
568 push(
569 make_widget!(immediate_switch_button_paper)
570 .with_props(ImmediateButtonProps { state: Some(state) })
571 .merge_props(props.into()),
572 );
573 result
574 }
575
576 pub fn text_button_paper(props: impl Into<Props>) -> ImmediateButton {
577 use crate::internal::*;
578 let state = use_state(ImmediateButton::default);
579 let result = state.read().unwrap().to_owned();
580 push(
581 make_widget!(immediate_text_button_paper)
582 .with_props(ImmediateButtonProps { state: Some(state) })
583 .merge_props(props.into()),
584 );
585 result
586 }
587
588 pub fn text_field_paper<T: ToString + FromStr + Send + Sync>(
589 value: &T,
590 props: impl Into<Props>,
591 ) -> (Option<T>, TextInputState, ImmediateButton) {
592 use crate::internal::*;
593 let content = use_state(|| value.to_string());
594 let props = props.into();
595 let TextInputProps { allow_new_line, .. } =
596 props.read_cloned_or_default::<TextInputProps>();
597 let text_state = use_state(TextInputState::default);
598 let text_result = text_state.read().unwrap().to_owned();
599 let button_state = use_state(ImmediateButton::default);
600 let button_result = button_state.read().unwrap().to_owned();
601 if !text_result.focused {
602 *content.write().unwrap() = value.to_string();
603 }
604 let result = content.read().unwrap().to_string();
605 push(
606 make_widget!(immediate_text_field_paper)
607 .with_props(ImmediateTextInputProps {
608 state: Some(text_state),
609 })
610 .with_props(ImmediateButtonProps {
611 state: Some(button_state),
612 })
613 .merge_props(props)
614 .with_props(TextInputProps {
615 allow_new_line,
616 text: Some(content.into()),
617 }),
618 );
619 (result.parse().ok(), text_result, button_result)
620 }
621
622 pub fn slider_paper<T: SliderViewProxy + Clone + 'static>(
623 value: T,
624 props: impl Into<Props>,
625 mut f: impl FnMut(&T, ImmediateButton),
626 ) -> (T, ImmediateButton) {
627 use crate::internal::*;
628 let content = use_state(|| value.to_owned());
629 let props = props.into();
630 let SliderViewProps {
631 from,
632 to,
633 direction,
634 ..
635 } = props.read_cloned_or_default();
636 let button_state = use_state(ImmediateButton::default);
637 let button_result = button_state.read().unwrap().to_owned();
638 let result = content.read().unwrap().to_owned();
639 begin();
640 f(&result, button_result);
641 let node = end().pop().unwrap_or_default();
642 push(
643 make_widget!(immediate_slider_paper)
644 .with_props(ImmediateButtonProps {
645 state: Some(button_state),
646 })
647 .merge_props(props)
648 .with_props(SliderViewProps {
649 input: Some(content.into()),
650 from,
651 to,
652 direction,
653 })
654 .named_slot("content", node),
655 );
656 (result, button_result)
657 }
658
659 pub fn numeric_slider_paper<T: SliderViewProxy + Clone + 'static>(
660 value: T,
661 props: impl Into<Props>,
662 ) -> (T, ImmediateButton) {
663 use crate::internal::*;
664 let content = use_state(|| value.to_owned());
665 let props = props.into();
666 let SliderViewProps {
667 from,
668 to,
669 direction,
670 ..
671 } = props.read_cloned_or_default();
672 let button_state = use_state(ImmediateButton::default);
673 let button_result = button_state.read().unwrap().to_owned();
674 let result = content.read().unwrap().to_owned();
675 push(
676 make_widget!(immediate_numeric_slider_paper)
677 .with_props(ImmediateButtonProps {
678 state: Some(button_state),
679 })
680 .merge_props(props)
681 .with_props(SliderViewProps {
682 input: Some(content.into()),
683 from,
684 to,
685 direction,
686 }),
687 );
688 (result, button_result)
689 }
690 }
691}
692
693mod internal {
694 use crate::core::interactive::{ImmediateButton, ImmediateTracking};
695 use raui_core::{
696 ManagedLazy, Prefab, PropsData, make_widget, pre_hooks,
697 widget::{
698 component::interactive::{
699 button::{
700 ButtonNotifyMessage, ButtonNotifyProps, button, self_tracked_button,
701 tracked_button,
702 },
703 input_field::{TextInputState, input_field, text_input},
704 navigation::{
705 NavTrackingNotifyMessage, NavTrackingNotifyProps, self_tracking, tracking,
706 use_nav_tracking_self,
707 },
708 slider_view::slider_view,
709 },
710 context::WidgetContext,
711 node::WidgetNode,
712 },
713 };
714 use raui_material::component::interactive::{
715 button_paper::button_paper_impl,
716 icon_button_paper::icon_button_paper_impl,
717 slider_paper::{numeric_slider_paper_impl, slider_paper_impl},
718 switch_button_paper::switch_button_paper_impl,
719 text_button_paper::text_button_paper_impl,
720 text_field_paper::text_field_paper_impl,
721 };
722 use serde::{Deserialize, Serialize};
723
724 #[derive(PropsData, Default, Clone, Serialize, Deserialize)]
725 #[props_data(raui_core::props::PropsData)]
726 #[prefab(raui_core::Prefab)]
727 pub struct ImmediateTrackingProps {
728 #[serde(default, skip)]
729 pub state: Option<ManagedLazy<ImmediateTracking>>,
730 }
731
732 impl std::fmt::Debug for ImmediateTrackingProps {
733 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
734 f.debug_struct("ImmediateTrackingProps")
735 .field(
736 "state",
737 &self
738 .state
739 .as_ref()
740 .and_then(|state| state.read())
741 .map(|state| *state),
742 )
743 .finish()
744 }
745 }
746
747 #[derive(PropsData, Default, Clone, Serialize, Deserialize)]
748 #[props_data(raui_core::props::PropsData)]
749 #[prefab(raui_core::Prefab)]
750 pub struct ImmediateButtonProps {
751 #[serde(default, skip)]
752 pub state: Option<ManagedLazy<ImmediateButton>>,
753 }
754
755 impl std::fmt::Debug for ImmediateButtonProps {
756 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
757 f.debug_struct("ImmediateButtonProps")
758 .field(
759 "state",
760 &self
761 .state
762 .as_ref()
763 .and_then(|state| state.read())
764 .map(|state| *state),
765 )
766 .finish()
767 }
768 }
769
770 #[derive(PropsData, Default, Clone, Serialize, Deserialize)]
771 #[props_data(raui_core::props::PropsData)]
772 pub struct ImmediateTextInputProps {
773 #[serde(default, skip)]
774 pub state: Option<ManagedLazy<TextInputState>>,
775 }
776
777 impl std::fmt::Debug for ImmediateTextInputProps {
778 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
779 f.debug_struct("ImmediateTextInputProps")
780 .finish_non_exhaustive()
781 }
782 }
783
784 fn use_immediate_tracking(ctx: &mut WidgetContext) {
785 ctx.props
786 .write(NavTrackingNotifyProps(ctx.id.to_owned().into()));
787
788 if let Ok(props) = ctx.props.read::<ImmediateTrackingProps>() {
789 let state = props.state.as_ref().unwrap();
790 let mut state = state.write().unwrap();
791 state.prev = state.state;
792 }
793
794 ctx.life_cycle.change(|ctx| {
795 if let Ok(props) = ctx.props.read::<ImmediateTrackingProps>()
796 && let Some(state) = props.state.as_ref()
797 && let Some(mut state) = state.write()
798 {
799 for msg in ctx.messenger.messages {
800 if let Some(msg) = msg.as_any().downcast_ref::<NavTrackingNotifyMessage>() {
801 state.state = msg.state;
802 }
803 }
804 }
805 });
806 }
807
808 fn use_immediate_button(ctx: &mut WidgetContext) {
809 ctx.props.write(ButtonNotifyProps(ctx.id.to_owned().into()));
810
811 if let Ok(props) = ctx.props.read::<ImmediateButtonProps>() {
812 let state = props.state.as_ref().unwrap();
813 let mut state = state.write().unwrap();
814 state.prev = state.state;
815 }
816
817 ctx.life_cycle.change(|ctx| {
818 if let Ok(props) = ctx.props.read::<ImmediateButtonProps>()
819 && let Some(state) = props.state.as_ref()
820 && let Some(mut state) = state.write()
821 {
822 for msg in ctx.messenger.messages {
823 if let Some(msg) = msg.as_any().downcast_ref::<ButtonNotifyMessage>() {
824 state.state = msg.state;
825 }
826 }
827 }
828 });
829 }
830
831 fn use_immediate_text_input(ctx: &mut WidgetContext) {
832 if let Ok(data) = ctx.state.read_cloned::<TextInputState>()
833 && let Ok(props) = ctx.props.read::<ImmediateTextInputProps>()
834 {
835 let state = props.state.as_ref().unwrap();
836 let mut state = state.write().unwrap();
837 *state = data;
838 }
839 }
840
841 #[pre_hooks(use_immediate_tracking)]
842 pub(crate) fn immediate_tracking(mut ctx: WidgetContext) -> WidgetNode {
843 tracking(ctx)
844 }
845
846 #[pre_hooks(use_immediate_tracking, use_nav_tracking_self)]
847 pub(crate) fn immediate_self_tracking(mut ctx: WidgetContext) -> WidgetNode {
848 self_tracking(ctx)
849 }
850
851 #[pre_hooks(use_immediate_button)]
852 pub(crate) fn immediate_button(mut ctx: WidgetContext) -> WidgetNode {
853 button(ctx)
854 }
855
856 #[pre_hooks(use_immediate_button)]
857 pub(crate) fn immediate_tracked_button(mut ctx: WidgetContext) -> WidgetNode {
858 tracked_button(ctx)
859 }
860
861 #[pre_hooks(use_immediate_button)]
862 pub(crate) fn immediate_self_tracked_button(mut ctx: WidgetContext) -> WidgetNode {
863 self_tracked_button(ctx)
864 }
865
866 #[pre_hooks(use_immediate_text_input)]
867 pub(crate) fn immediate_text_input(mut ctx: WidgetContext) -> WidgetNode {
868 text_input(ctx)
869 }
870
871 #[pre_hooks(use_immediate_text_input, use_immediate_button)]
872 pub(crate) fn immediate_input_field(mut ctx: WidgetContext) -> WidgetNode {
873 input_field(ctx)
874 }
875
876 #[pre_hooks(use_immediate_button)]
877 pub(crate) fn immediate_slider_view(mut ctx: WidgetContext) -> WidgetNode {
878 slider_view(ctx)
879 }
880
881 pub(crate) fn immediate_button_paper(ctx: WidgetContext) -> WidgetNode {
882 button_paper_impl(make_widget!(immediate_button), ctx)
883 }
884
885 pub(crate) fn immediate_icon_button_paper(ctx: WidgetContext) -> WidgetNode {
886 icon_button_paper_impl(make_widget!(immediate_button_paper), ctx)
887 }
888
889 pub(crate) fn immediate_switch_button_paper(ctx: WidgetContext) -> WidgetNode {
890 switch_button_paper_impl(make_widget!(immediate_button_paper), ctx)
891 }
892
893 pub(crate) fn immediate_text_button_paper(ctx: WidgetContext) -> WidgetNode {
894 text_button_paper_impl(make_widget!(immediate_button_paper), ctx)
895 }
896
897 pub(crate) fn immediate_text_field_paper(ctx: WidgetContext) -> WidgetNode {
898 text_field_paper_impl(make_widget!(immediate_input_field), ctx)
899 }
900
901 pub(crate) fn immediate_slider_paper(ctx: WidgetContext) -> WidgetNode {
902 slider_paper_impl(make_widget!(immediate_slider_view), ctx)
903 }
904
905 pub(crate) fn immediate_numeric_slider_paper(ctx: WidgetContext) -> WidgetNode {
906 numeric_slider_paper_impl(make_widget!(immediate_slider_paper), ctx)
907 }
908}