Skip to main content

azul_layout/managers/
drag_drop.rs

1//! **Node** drag and drop state management
2//!
3//! This module maintains the old API types for backwards compatibility.
4//! Internally, it now uses the unified `DragContext` from `azul_core::drag`.
5
6use azul_core::dom::{DomId, DomNodeId, NodeId, OptionDomNodeId};
7use azul_core::drag::{ActiveDragType, DragContext};
8use azul_css::{impl_option, impl_option_inner, AzString, OptionString};
9
10// Re-export DragData for use in other modules
11pub use azul_core::drag::DragData;
12
13/// Type of drag operation
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15#[repr(C)]
16pub enum DragType {
17    /// Dragging a DOM node
18    Node,
19    /// Dragging a file from OS
20    File,
21}
22
23/// State of an active drag operation
24#[derive(Debug, Clone, PartialEq)]
25#[repr(C)]
26pub struct DragState {
27    /// Type of drag
28    pub drag_type: DragType,
29    /// Source node (for node dragging)
30    pub source_node: OptionDomNodeId,
31    /// Current drop target (if hovering over valid drop zone)
32    pub current_drop_target: OptionDomNodeId,
33    /// File path (for file dragging)
34    pub file_path: OptionString,
35}
36
37impl DragState {
38    /// Create DragState from a DragContext (for backwards compatibility)
39    pub fn from_context(ctx: &DragContext) -> Option<Self> {
40        match &ctx.drag_type {
41            ActiveDragType::Node(node_drag) => Some(DragState {
42                drag_type: DragType::Node,
43                source_node: OptionDomNodeId::Some(DomNodeId {
44                    dom: node_drag.dom_id,
45                    node: azul_core::styled_dom::NodeHierarchyItemId::from_crate_internal(Some(node_drag.node_id)),
46                }),
47                current_drop_target: node_drag.current_drop_target,
48                file_path: OptionString::None,
49            }),
50            ActiveDragType::FileDrop(file_drop) => Some(DragState {
51                drag_type: DragType::File,
52                source_node: OptionDomNodeId::None,
53                current_drop_target: file_drop.drop_target,
54                file_path: file_drop.files.as_ref().first().cloned().into(),
55            }),
56            _ => None, // Other drag types don't map to the old API
57        }
58    }
59}
60
61impl_option!(
62    DragState,
63    OptionDragState,
64    copy = false,
65    [Debug, Clone, PartialEq]
66);
67
68/// Manager for drag-and-drop operations
69///
70/// **DEPRECATED**: Use `GestureAndDragManager` with `DragContext` instead.
71/// This type is kept for backwards compatibility only.
72#[derive(Debug, Clone, PartialEq, Default)]
73pub struct DragDropManager {
74    /// Currently active drag operation (using new unified system)
75    pub active_drag: Option<DragContext>,
76}
77
78impl DragDropManager {
79    /// Create a new drag-drop manager
80    pub fn new() -> Self {
81        Self { active_drag: None }
82    }
83
84    /// Start a node drag operation
85    pub fn start_node_drag(&mut self, source_node: DomNodeId) {
86        self.active_drag = Some(DragContext::node_drag(
87            source_node.dom,
88            source_node.node.into_crate_internal().unwrap_or(NodeId::ZERO),
89            azul_core::geom::LogicalPosition::zero(),
90            DragData::default(),
91            0,
92        ));
93    }
94
95    /// Start a file drag operation
96    pub fn start_file_drag(&mut self, file_path: AzString) {
97        self.active_drag = Some(DragContext::file_drop(
98            vec![file_path],
99            azul_core::geom::LogicalPosition::zero(),
100            0,
101        ));
102    }
103
104    /// Update the current drop target
105    pub fn set_drop_target(&mut self, target: Option<DomNodeId>) {
106        if let Some(ref mut drag) = self.active_drag {
107            if let Some(node_drag) = drag.as_node_drag_mut() {
108                node_drag.current_drop_target = target.into();
109            }
110        }
111    }
112
113    /// End the drag operation and return the final context
114    pub fn end_drag(&mut self) -> Option<DragContext> {
115        self.active_drag.take()
116    }
117
118    /// Check if a drag operation is active
119    pub fn is_dragging(&self) -> bool {
120        self.active_drag.is_some()
121    }
122
123    /// Check if currently dragging a node
124    pub fn is_dragging_node(&self) -> bool {
125        self.active_drag.as_ref().is_some_and(|d| d.is_node_drag())
126    }
127
128    /// Check if currently dragging a file
129    pub fn is_dragging_file(&self) -> bool {
130        self.active_drag.as_ref().is_some_and(|d| d.is_file_drop())
131    }
132
133    /// Get the active drag context
134    pub fn get_drag_context(&self) -> Option<&DragContext> {
135        self.active_drag.as_ref()
136    }
137
138    /// Get the active drag state (old API for backwards compatibility)
139    pub fn get_drag_state(&self) -> Option<DragState> {
140        self.active_drag.as_ref().and_then(DragState::from_context)
141    }
142
143    /// Cancel the current drag operation
144    pub fn cancel_drag(&mut self) {
145        self.active_drag = None;
146    }
147}