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