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 IntoUiNode, mode: impl IntoVar<TouchTransformMode>) -> UiNode {
8    let mode = mode.into_var();
9    let mut handle = VarHandle::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(UpdateOp::Update, WIDGET.id());
17            }
18        }
19        UiNodeOp::Deinit => {
20            handle = VarHandle::dummy();
21        }
22        UiNodeOp::Update { .. } => {
23            TOUCH_TRANSFORM_EVENT.each_update(false, |args| {
24                let t = transform_committed.then(&args.local_transform(mode.get(), (WINDOW.id(), WIDGET.id())));
25                if transform != t {
26                    transform = t;
27                    WIDGET.render_update();
28                }
29
30                match args.phase {
31                    TouchPhase::Start | TouchPhase::Move => {}
32                    TouchPhase::End => {
33                        transform_committed = transform;
34                    }
35                    TouchPhase::Cancel => {
36                        transform = transform_committed;
37                        WIDGET.render_update();
38                    }
39                }
40            });
41
42            if let Some(mode) = mode.get_new() {
43                if handle.is_dummy() {
44                    if !mode.is_empty() {
45                        handle = TOUCH_TRANSFORM_EVENT.subscribe(UpdateOp::Update, WIDGET.id());
46                    }
47                } else if mode.is_empty() {
48                    handle = VarHandle::dummy();
49                }
50            }
51        }
52        UiNodeOp::Render { frame } => {
53            frame.push_inner_transform(&transform, |f| c.render(f));
54        }
55        UiNodeOp::RenderUpdate { update } => {
56            update.with_inner_transform(&transform, |u| c.render_update(u));
57        }
58        _ => {}
59    })
60}