zng_view_api/
drag_drop.rs

1//! Drag&drop types.
2
3use std::{fmt, path::PathBuf};
4
5use zng_txt::Txt;
6
7use crate::ipc::IpcBytes;
8
9use bitflags::bitflags;
10
11/// Drag&drop data payload.
12#[derive(Clone, PartialEq, serde::Serialize, serde::Deserialize)]
13#[non_exhaustive]
14pub enum DragDropData {
15    /// Text encoded data.
16    ///
17    /// This can be HTML or JSON for example.
18    Text {
19        /// MIME type of the data.
20        ///
21        /// Plain text is `"text/plain"`.
22        format: Txt,
23        /// Data.
24        data: Txt,
25    },
26    /// File or directory path.
27    Path(PathBuf),
28    /// Binary encoded data.
29    ///
30    /// This can be an image for example.
31    Binary {
32        /// MIME type of the data.
33        format: Txt,
34        /// Data.
35        data: IpcBytes,
36    },
37}
38impl fmt::Debug for DragDropData {
39    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40        match self {
41            Self::Text { format, data } => write!(f, "Text {{ format: {:?}, data: {} bytes }}", format, data.len()),
42            Self::Path(data) => write!(f, "Path({})", data.display()),
43            Self::Binary { format, data } => write!(f, "Binary {{ format: {:?}, data: {} bytes }}", format, data.len()),
44        }
45    }
46}
47
48#[cfg(feature = "var")]
49zng_var::impl_from_and_into_var! {
50    fn from(plain: Txt) -> DragDropData {
51        DragDropData::Text {
52            format: "text/plain".into(),
53            data: plain,
54        }
55    }
56
57    fn from(plain: String) -> DragDropData {
58        Txt::from(plain).into()
59    }
60
61    fn from(plain: &'static str) -> DragDropData {
62        Txt::from(plain).into()
63    }
64
65    fn from(path: PathBuf) -> DragDropData {
66        DragDropData::Path(path)
67    }
68}
69
70bitflags! {
71    /// Drag&drop drop effect on the data source.
72    #[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
73    pub struct DragDropEffect: u8 {
74        /// Indicates that the dragged data will be copied from its present location to the drop location.
75        const COPY = 0b001;
76        /// Indicates that the dragged data will be moved from its present location to the drop location.
77        const MOVE = 0b010;
78        /// Indicates that some form of relationship or connection will be created between the source and drop locations.
79        const LINK = 0b100;
80    }
81}
82impl DragDropEffect {
83    /// Count effects flagged.
84    pub fn len(&self) -> u8 {
85        [DragDropEffect::COPY, DragDropEffect::MOVE, DragDropEffect::LINK]
86            .into_iter()
87            .filter(|&f| self.contains(f))
88            .count() as u8
89    }
90}
91
92/// Error for drag start or cancel error.
93#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
94#[non_exhaustive]
95pub enum DragDropError {
96    /// View-process implementer does not support any of the provided data types.
97    NotSupported,
98    /// Cannot start dragging.
99    CannotStart(Txt),
100}
101impl fmt::Display for DragDropError {
102    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103        match self {
104            DragDropError::NotSupported => write!(f, "not supported"),
105            DragDropError::CannotStart(txt) => write!(f, "cannot start, {txt}"),
106        }
107    }
108}
109impl std::error::Error for DragDropError {
110    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
111        None
112    }
113}