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

            
11
use azul_core::dom::{DomNodeId, NodeId, OptionDomNodeId};
12
use azul_core::drag::{ActiveDragType, DragContext};
13
use azul_css::{impl_option, impl_option_inner, AzString, OptionString};
14

            
15
/// Re-exported for the C API (`api.json` / `drag-drop-test.c`).
16
pub use azul_core::drag::DragData;
17

            
18
/// Type of drag operation
19
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20
#[repr(C)]
21
pub 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)]
31
pub 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

            
42
impl 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

            
66
impl_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)]
78
pub struct DragDropManager {
79
    /// Currently active drag operation (using new unified system)
80
    pub active_drag: Option<DragContext>,
81
}
82

            
83
impl DragDropManager {
84
    /// Create a new drag-drop manager
85
2321
    pub fn new() -> Self {
86
2321
        Self { active_drag: None }
87
2321
    }
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
}