zng_wgt_dialog/
backdrop.rs

1//! Modal backdrop widget.
2
3use zng_wgt::{prelude::*, *};
4use zng_wgt_container::Container;
5use zng_wgt_fill::background_color;
6use zng_wgt_input::gesture::on_click;
7use zng_wgt_layer::popup::POPUP_CLOSE_REQUESTED_EVENT;
8use zng_wgt_style::{Style, StyleMix, impl_style_fn};
9
10use crate::DIALOG;
11
12/// Modal dialog parent widget that fills the window.
13///
14/// This widget is instantiated by [`DIALOG`] automatically, you can only customize it by setting the [`style_fn`](fn@style_fn)
15/// contextual property. Note that the [`popup::close_delay`] and [`popup::is_close_delaying`] properties work with this widget.
16///
17/// [`popup::close_delay`]: fn@zng_wgt_layer::popup::close_delay
18/// [`popup::is_close_delaying`]: fn@zng_wgt_layer::popup::is_close_delaying
19#[widget($crate::backdrop::DialogBackdrop {
20    ($child:expr) => {
21        child = $child;
22    }
23})]
24pub struct DialogBackdrop(StyleMix<Container>);
25impl DialogBackdrop {
26    fn widget_intrinsic(&mut self) {
27        self.style_intrinsic(STYLE_FN_VAR, property_id!(self::style_fn));
28
29        self.widget_builder()
30            .push_build_action(|b| b.push_intrinsic(NestGroup::EVENT, "popup-pump", backdrop_node));
31
32        widget_set! {
33            self;
34            modal = true;
35
36            on_click = hn!(|args| {
37                args.propagation().stop();
38                DIALOG.respond_default();
39            });
40        }
41    }
42}
43impl_style_fn!(DialogBackdrop, DefaultStyle);
44
45/// Share popup events with the dialog child.
46fn backdrop_node(child: impl IntoUiNode) -> UiNode {
47    match_node(child, |c, op| match op {
48        UiNodeOp::Init => {
49            WIDGET.sub_event(&POPUP_CLOSE_REQUESTED_EVENT);
50        }
51        UiNodeOp::Event { update } => {
52            if let Some(args) = POPUP_CLOSE_REQUESTED_EVENT.on(update) {
53                for child in WIDGET.info().descendants() {
54                    if POPUP_CLOSE_REQUESTED_EVENT.is_subscriber(child.id()) {
55                        let mut delivery = UpdateDeliveryList::new_any();
56                        delivery.insert_wgt(&child);
57                        let update = POPUP_CLOSE_REQUESTED_EVENT.new_update_custom(args.clone(), delivery);
58                        c.event(&update);
59                    }
60                }
61            }
62        }
63        _ => {}
64    })
65}
66
67/// Dialog backdrop default style.
68#[widget($crate::backdrop::DefaultStyle)]
69pub struct DefaultStyle(Style);
70impl DefaultStyle {
71    fn widget_intrinsic(&mut self) {
72        widget_set! {
73            self;
74
75            #[easing(250.ms())]
76            background_color = colors::BLACK.transparent();
77            zng_wgt_layer::popup::close_delay = 250.ms();
78            when *#is_inited && !*#zng_wgt_layer::popup::is_close_delaying {
79                background_color = colors::BLACK.with_alpha(20.pct());
80            }
81        }
82    }
83}