Skip to main content

azul_layout/managers/
drag_drop.rs

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