zng_wgt_input/
touch_props.rs

1use zng_ext_input::touch::{TOUCH_TRANSFORM_EVENT, TouchTransformMode};
2use zng_view_api::touch::TouchPhase;
3use zng_wgt::prelude::*;
4
5/// Applies transforms from touch gestures on the widget.
6#[property(LAYOUT, default(false))]
7pub fn touch_transform(child: impl UiNode, mode: impl IntoVar<TouchTransformMode>) -> impl UiNode {
8    let mode = mode.into_var();
9    let mut handle = EventHandle::dummy();
10    let mut transform_committed = PxTransform::identity();
11    let mut transform = PxTransform::identity();
12    match_node(child, move |c, op| match op {
13        UiNodeOp::Init => {
14            WIDGET.sub_var(&mode);
15            if !mode.get().is_empty() {
16                handle = TOUCH_TRANSFORM_EVENT.subscribe(WIDGET.id());
17            }
18        }
19        UiNodeOp::Deinit => {
20            handle = EventHandle::dummy();
21        }
22        UiNodeOp::Event { update } => {
23            if let Some(args) = TOUCH_TRANSFORM_EVENT.on(update) {
24                if args.propagation().is_stopped() {
25                    return;
26                }
27
28                let t = transform_committed.then(&args.local_transform(mode.get()));
29                if transform != t {
30                    transform = t;
31                    WIDGET.render_update();
32                }
33
34                match args.phase {
35                    TouchPhase::Start | TouchPhase::Move => {}
36                    TouchPhase::End => {
37                        transform_committed = transform;
38                    }
39                    TouchPhase::Cancel => {
40                        transform = transform_committed;
41                        WIDGET.render_update();
42                    }
43                }
44            }
45        }
46        UiNodeOp::Update { .. } => {
47            if let Some(mode) = mode.get_new() {
48                if handle.is_dummy() {
49                    if !mode.is_empty() {
50                        handle = TOUCH_TRANSFORM_EVENT.subscribe(WIDGET.id());
51                    }
52                } else if mode.is_empty() {
53                    handle = EventHandle::dummy();
54                }
55            }
56        }
57        UiNodeOp::Render { frame } => {
58            frame.push_inner_transform(&transform, |f| c.render(f));
59        }
60        UiNodeOp::RenderUpdate { update } => {
61            update.with_inner_transform(&transform, |u| c.render_update(u));
62        }
63        _ => {}
64    })
65}