dioxus_dnd/core/
effects.rs1use std::ops::{BitOr, BitOrAssign};
4
5use super::{DragId, DragMode, DropEffect, PointerKind, ZoneId};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9pub struct DropEffects(u8);
10
11impl DropEffects {
12 pub const EMPTY: Self = Self(0);
13 pub const MOVE: Self = Self(1 << 0);
14 pub const COPY: Self = Self(1 << 1);
15 pub const LINK: Self = Self(1 << 2);
16 pub const STANDARD: Self = Self(Self::MOVE.0 | Self::COPY.0 | Self::LINK.0);
17 pub const ALL: Self = Self::STANDARD;
18
19 pub fn contains(self, effect: DropEffect) -> bool {
20 let flag = match effect {
21 DropEffect::Move => Self::MOVE,
22 DropEffect::Copy => Self::COPY,
23 DropEffect::Link => Self::LINK,
24 DropEffect::None => return false,
25 };
26 self.0 & flag.0 != 0
27 }
28
29 pub fn is_empty(self) -> bool {
30 self.0 == 0
31 }
32
33 pub fn negotiate(self, proposed: DropEffect) -> Option<DropEffect> {
36 if proposed == DropEffect::None {
37 return None;
38 }
39 if self.contains(proposed) {
40 return Some(proposed);
41 }
42 [DropEffect::Move, DropEffect::Copy, DropEffect::Link]
43 .into_iter()
44 .find(|effect| self.contains(*effect))
45 }
46}
47
48impl Default for DropEffects {
49 fn default() -> Self {
50 Self::ALL
51 }
52}
53
54impl BitOr for DropEffects {
55 type Output = Self;
56
57 fn bitor(self, rhs: Self) -> Self::Output {
58 Self(self.0 | rhs.0)
59 }
60}
61
62impl BitOrAssign for DropEffects {
63 fn bitor_assign(&mut self, rhs: Self) {
64 self.0 |= rhs.0;
65 }
66}
67
68#[derive(Debug, Clone, PartialEq)]
70#[non_exhaustive]
71pub struct DropQuery<T> {
72 pub payload: T,
73 pub source: Option<ZoneId>,
74 pub proposed_effect: DropEffect,
75 pub mode: DragMode,
76 pub pointer_kind: PointerKind,
77 pub drag_id: Option<DragId>,
78}
79
80impl<T> DropQuery<T> {
81 pub fn new(payload: T) -> Self {
82 Self {
83 payload,
84 source: None,
85 proposed_effect: DropEffect::default(),
86 mode: DragMode::default(),
87 pointer_kind: PointerKind::default(),
88 drag_id: None,
89 }
90 }
91}
92
93#[cfg(test)]
94mod tests {
95 use super::*;
96
97 #[test]
98 fn negotiation_keeps_supported_effect_and_falls_back_explicitly() {
99 let effects = DropEffects::MOVE | DropEffects::COPY;
100 assert_eq!(effects.negotiate(DropEffect::Copy), Some(DropEffect::Copy));
101 assert_eq!(effects.negotiate(DropEffect::Link), Some(DropEffect::Move));
102 assert_eq!(DropEffects::EMPTY.negotiate(DropEffect::Move), None);
103 assert_eq!(DropEffects::ALL.negotiate(DropEffect::None), None);
104 assert!(!DropEffects::ALL.contains(DropEffect::None));
105 }
106}