tui_lipan/widgets/drag_drop/
drag_source.rs1use std::hash::Hash;
2use std::sync::Arc;
3
4use crate::core::element::{Element, ElementKind};
5use crate::layout::drag_source_layout_hint::drag_source_snapshot_collapse_key;
6use crate::layout::hash::LayoutHash;
7use crate::style::{LayoutConstraints, Length, Style, StyleSlot};
8
9use super::drag_source_layout::measure_drag_source;
10use super::payload::{
11 DragCancelEvent, DragPayload, DragPreview, DragSlot, DragSlotAxis, DragStartEvent,
12 DragStartedEvent,
13};
14
15pub type DragStartHandler = Arc<dyn Fn(DragStartEvent) -> Option<Box<dyn DragPayload>>>;
18
19#[derive(Clone)]
21pub struct DragSource {
22 pub(crate) child: Option<Box<Element>>,
23 pub(crate) on_drag_start: Option<DragStartHandler>,
24 pub(crate) on_drag_cancel: Option<crate::callback::Callback<DragCancelEvent>>,
25 pub(crate) on_drag_started: Option<crate::callback::Callback<DragStartedEvent>>,
26 pub(crate) drag_group: Option<Arc<str>>,
27 pub(crate) preview: DragPreview,
28 pub(crate) dragging_style: StyleSlot,
29 pub(crate) drag_slot: DragSlot,
30 pub(crate) drag_slot_axis: DragSlotAxis,
31 pub(crate) preview_max_width: Option<u16>,
32 pub(crate) preview_max_height: Option<u16>,
33 pub(crate) threshold: u16,
34 pub(crate) enabled: bool,
35}
36
37impl Default for DragSource {
38 fn default() -> Self {
39 Self {
40 child: None,
41 on_drag_start: None,
42 on_drag_cancel: None,
43 on_drag_started: None,
44 drag_group: None,
45 preview: DragPreview::None,
46 dragging_style: StyleSlot::Inherit,
47 drag_slot: DragSlot::Collapse,
48 drag_slot_axis: DragSlotAxis::default(),
49 preview_max_width: None,
50 preview_max_height: None,
51 threshold: 3,
52 enabled: true,
53 }
54 }
55}
56
57impl DragSource {
58 pub fn new() -> Self {
60 Self::default()
61 }
62
63 pub fn child(mut self, child: impl Into<Element>) -> Self {
65 self.child = Some(Box::new(child.into()));
66 self
67 }
68
69 pub fn on_drag_start(
71 mut self,
72 cb: impl Fn(DragStartEvent) -> Option<Box<dyn DragPayload>> + 'static,
73 ) -> Self {
74 self.on_drag_start = Some(Arc::new(cb));
75 self
76 }
77
78 pub fn on_drag_cancel(mut self, cb: crate::callback::Callback<DragCancelEvent>) -> Self {
80 self.on_drag_cancel = Some(cb);
81 self
82 }
83
84 pub fn on_drag_started(mut self, cb: crate::callback::Callback<DragStartedEvent>) -> Self {
86 self.on_drag_started = Some(cb);
87 self
88 }
89
90 pub fn drag_group(mut self, group: impl Into<Arc<str>>) -> Self {
92 self.drag_group = Some(group.into());
93 self
94 }
95
96 pub fn clear_drag_group(mut self) -> Self {
98 self.drag_group = None;
99 self
100 }
101
102 pub fn preview(mut self, preview: DragPreview) -> Self {
104 self.preview = preview;
105 self
106 }
107
108 pub fn preview_label(mut self, label: impl Into<Arc<str>>) -> Self {
110 self.preview = DragPreview::Label(label.into());
111 self
112 }
113
114 pub fn preview_snapshot(mut self) -> Self {
116 self.preview = DragPreview::SourceSnapshot;
117 self
118 }
119
120 pub fn no_preview(mut self) -> Self {
122 self.preview = DragPreview::None;
123 self
124 }
125
126 pub fn dragging_style(mut self, style: Style) -> Self {
128 self.dragging_style = StyleSlot::Replace(style);
129 self
130 }
131
132 pub fn extend_dragging_style(mut self, style: Style) -> Self {
134 self.dragging_style = StyleSlot::Extend(style);
135 self
136 }
137
138 pub fn inherit_dragging_style(mut self) -> Self {
140 self.dragging_style = StyleSlot::Inherit;
141 self
142 }
143
144 pub fn dragging_style_slot(mut self, slot: StyleSlot) -> Self {
146 self.dragging_style = slot;
147 self
148 }
149
150 pub fn drag_slot(mut self, slot: DragSlot) -> Self {
152 self.drag_slot = slot;
153 self
154 }
155
156 pub fn drag_slot_collapse(mut self) -> Self {
158 self.drag_slot = DragSlot::Collapse;
159 self
160 }
161
162 pub fn drag_slot_length(mut self, len: Length) -> Self {
164 self.drag_slot = DragSlot::Specified(len);
165 self
166 }
167
168 pub fn drag_slot_axis(mut self, axis: DragSlotAxis) -> Self {
170 self.drag_slot_axis = axis;
171 self
172 }
173
174 pub fn preview_max_width(mut self, max_width: Option<u16>) -> Self {
176 self.preview_max_width = max_width;
177 self
178 }
179
180 pub fn preview_max_height(mut self, max_height: Option<u16>) -> Self {
182 self.preview_max_height = max_height;
183 self
184 }
185
186 pub fn preview_max_size(mut self, max_width: Option<u16>, max_height: Option<u16>) -> Self {
188 self.preview_max_width = max_width;
189 self.preview_max_height = max_height;
190 self
191 }
192
193 pub fn threshold(mut self, threshold: u16) -> Self {
195 self.threshold = threshold;
196 self
197 }
198
199 pub fn enabled(mut self, enabled: bool) -> Self {
201 self.enabled = enabled;
202 self
203 }
204}
205
206impl From<DragSource> for Element {
207 fn from(value: DragSource) -> Self {
208 let (min_w, min_h) = measure_drag_source(&value, None, None, None);
209 let min_h = if matches!(value.preview, DragPreview::SourceSnapshot) {
212 0
213 } else {
214 min_h
215 };
216 Element::new(ElementKind::DragSource(value)).with_layout(
217 LayoutConstraints::default()
218 .min_width(Length::Px(min_w))
219 .min_height(Length::Px(min_h)),
220 )
221 }
222}
223
224impl LayoutHash for DragSource {
225 fn layout_hash(
226 &self,
227 hasher: &mut impl std::hash::Hasher,
228 recurse: &dyn Fn(&Element) -> Option<u64>,
229 ) -> Option<()> {
230 self.enabled.hash(hasher);
231 self.on_drag_start.is_some().hash(hasher);
232 self.on_drag_cancel.is_some().hash(hasher);
233 self.on_drag_started.is_some().hash(hasher);
234 self.drag_group.hash(hasher);
235 self.preview.hash(hasher);
236 self.dragging_style.hash(hasher);
237 self.drag_slot.hash(hasher);
238 self.drag_slot_axis.hash(hasher);
239 self.preview_max_width.hash(hasher);
240 self.preview_max_height.hash(hasher);
241 self.threshold.hash(hasher);
242 if matches!(self.preview, DragPreview::SourceSnapshot) {
245 drag_source_snapshot_collapse_key().hash(hasher);
246 }
247 if let Some(child) = self.child.as_ref() {
248 recurse(child.as_ref())?.hash(hasher);
249 }
250 Some(())
251 }
252}