raui_core/widget/component/interactive/
float_view.rs1use crate::{
2 pre_hooks, unpack_named_slots,
3 widget::{
4 component::{
5 containers::float_box::{
6 FloatBoxChange, FloatBoxChangeMessage, FloatBoxNotifyProps, FloatBoxState,
7 },
8 interactive::{
9 button::{ButtonNotifyMessage, ButtonNotifyProps, ButtonProps, use_button},
10 navigation::{
11 NavSignal, NavTrackingNotifyMessage, NavTrackingNotifyProps, use_nav_item,
12 use_nav_tracking_self,
13 },
14 },
15 },
16 context::WidgetContext,
17 node::WidgetNode,
18 unit::area::AreaBoxNode,
19 utils::Vec2,
20 },
21};
22
23#[pre_hooks(use_button, use_nav_tracking_self)]
24pub fn use_float_view_control(context: &mut WidgetContext) {
25 context
26 .props
27 .write(ButtonNotifyProps(context.id.to_owned().into()));
28 context
29 .props
30 .write(NavTrackingNotifyProps(context.id.to_owned().into()));
31
32 context.life_cycle.unmount(|context| {
33 context.signals.write(NavSignal::Unlock);
34 });
35
36 context.life_cycle.change(|context| {
37 let Some(notify) = context
38 .props
39 .read_cloned_or_default::<FloatBoxNotifyProps>()
40 .0
41 .read()
42 else {
43 return;
44 };
45 let button = context.state.read_cloned_or_default::<ButtonProps>();
46 let zoom = context.props.read_cloned_or_default::<FloatBoxState>().zoom;
47 let scale = if zoom > 0.0 { 1.0 / zoom } else { 1.0 };
48
49 for msg in context.messenger.messages {
50 if let Some(msg) = msg.as_any().downcast_ref::<ButtonNotifyMessage>() {
51 if msg.trigger_start() {
52 context.signals.write(NavSignal::Lock);
53 }
54 if msg.trigger_stop() {
55 context.signals.write(NavSignal::Unlock);
56 }
57 } else if let Some(msg) = msg.as_any().downcast_ref::<NavTrackingNotifyMessage>() {
58 if button.selected && button.trigger {
59 let delta = msg.pointer_delta_ui_space();
60 context.messenger.write(
61 notify.clone(),
62 FloatBoxChangeMessage {
63 sender: context.id.to_owned(),
64 change: FloatBoxChange::RelativePosition(Vec2 {
65 x: delta.x * scale,
66 y: delta.y * scale,
67 }),
68 },
69 );
70 }
71 }
72 }
73 });
74}
75
76#[pre_hooks(use_nav_item, use_float_view_control)]
77pub fn float_view_control(mut context: WidgetContext) -> WidgetNode {
78 let WidgetContext {
79 id,
80 props,
81 state,
82 named_slots,
83 ..
84 } = context;
85 unpack_named_slots!(named_slots => content);
86
87 if let Some(p) = content.props_mut() {
88 p.merge_from(props.clone());
89 p.write(state.read_cloned_or_default::<ButtonProps>());
90 }
91
92 AreaBoxNode {
93 id: id.to_owned(),
94 slot: Box::new(content),
95 }
96 .into()
97}