freya_components/
draggable_canvas.rs1use freya_core::prelude::*;
2use torin::prelude::{
3 Area,
4 CursorPoint,
5 Position,
6};
7
8#[derive(Clone)]
9struct DraggableCanvasLayout(State<Area>);
10
11#[derive(Clone)]
12struct DraggableCanvasRegistry(State<Vec<usize>>);
13
14#[derive(PartialEq)]
15pub struct DraggableCanvas {
16 children: Vec<Element>,
17 layout: LayoutData,
18 key: DiffKey,
19}
20
21impl KeyExt for DraggableCanvas {
22 fn write_key(&mut self) -> &mut DiffKey {
23 &mut self.key
24 }
25}
26
27impl Default for DraggableCanvas {
28 fn default() -> Self {
29 Self::new()
30 }
31}
32
33impl DraggableCanvas {
34 pub fn new() -> Self {
35 Self {
36 children: vec![],
37 layout: LayoutData::default(),
38 key: DiffKey::None,
39 }
40 }
41}
42
43impl LayoutExt for DraggableCanvas {
44 fn get_layout(&mut self) -> &mut LayoutData {
45 &mut self.layout
46 }
47}
48
49impl ContainerExt for DraggableCanvas {}
50
51impl ChildrenExt for DraggableCanvas {
52 fn get_children(&mut self) -> &mut Vec<Element> {
53 &mut self.children
54 }
55}
56
57impl Render for DraggableCanvas {
58 fn render(&self) -> impl IntoElement {
59 let mut layout = use_state(Area::default);
60 use_provide_context(move || DraggableCanvasLayout(layout));
61 use_provide_context(|| DraggableCanvasRegistry(State::create(Vec::new())));
62 rect()
63 .layout(self.layout.clone())
64 .on_sized(move |e: Event<SizedEventData>| layout.set(e.visible_area))
65 .children(self.children.clone())
66 }
67 fn render_key(&self) -> DiffKey {
68 self.key.clone().or(self.default_key())
69 }
70}
71
72#[derive(PartialEq)]
73pub struct Draggable {
74 initial_position: CursorPoint,
75 children: Vec<Element>,
76 key: DiffKey,
77}
78
79impl Default for Draggable {
80 fn default() -> Self {
81 Self::new()
82 }
83}
84
85impl Draggable {
86 pub fn new() -> Self {
87 Self {
88 initial_position: CursorPoint::zero(),
89 children: vec![],
90 key: DiffKey::None,
91 }
92 }
93
94 pub fn inital_position(mut self, initial_position: impl Into<CursorPoint>) -> Self {
95 self.initial_position = initial_position.into();
96 self
97 }
98}
99
100impl KeyExt for Draggable {
101 fn write_key(&mut self) -> &mut DiffKey {
102 &mut self.key
103 }
104}
105
106impl ChildrenExt for Draggable {
107 fn get_children(&mut self) -> &mut Vec<Element> {
108 &mut self.children
109 }
110}
111
112impl Render for Draggable {
113 fn render(&self) -> impl IntoElement {
114 let mut position = use_state(|| self.initial_position);
115 let mut dragging_position = use_state::<Option<CursorPoint>>(|| None);
116 let DraggableCanvasLayout(layout) = use_consume::<DraggableCanvasLayout>();
117 let DraggableCanvasRegistry(mut registry) = use_consume::<DraggableCanvasRegistry>();
118 let id = use_id::<DraggableCanvasLayout>();
119
120 use_hook(move || {
121 registry.write().push(id);
122 });
123
124 use_drop(move || {
125 registry.write().retain(|i| *i != id);
126 });
127
128 let on_global_mouse_move = move |e: Event<MouseEventData>| {
129 if let Some(dragging_position) = dragging_position() {
130 position.set(CursorPoint::new(
131 e.global_location.x - dragging_position.x,
132 e.global_location.y - dragging_position.y,
133 ));
134 e.stop_propagation();
135 }
136 };
137
138 let on_pointer_down = move |e: Event<PointerEventData>| {
139 dragging_position.set(Some(CursorPoint::new(
140 e.element_location().x + layout.read().min_x() as f64,
141 e.element_location().y + layout.read().min_y() as f64,
142 )));
143 e.stop_propagation();
144 let mut registry = registry.write();
145 registry.retain(|i| *i != id);
146 registry.insert(0, id);
147 };
148
149 let on_capture_global_mouse_up = move |e: Event<MouseEventData>| {
150 if dragging_position.read().is_some() {
151 e.stop_propagation();
152 e.prevent_default();
153 dragging_position.set(None);
154 }
155 };
156
157 let (left, top) = position().to_tuple();
158
159 let layer = registry
160 .read()
161 .iter()
162 .rev()
163 .position(|i| *i == id)
164 .map(|layer| layer * 1024)
165 .unwrap_or_default();
166
167 rect()
168 .on_global_mouse_move(on_global_mouse_move)
169 .on_pointer_down(on_pointer_down)
170 .on_capture_global_mouse_up(on_capture_global_mouse_up)
171 .position(Position::new_absolute().left(left as f32).top(top as f32))
172 .layer(layer as i16)
173 .children(self.children.clone())
174 }
175
176 fn render_key(&self) -> DiffKey {
177 self.key.clone().or(self.default_key())
178 }
179}