Skip to main content

fresh/app/types/
drag.rs

1use crate::model::event::{BufferId, LeafId};
2
3/// Drop zone for tab drag-and-drop
4/// Indicates where a dragged tab will be placed when released
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum TabDropZone {
7    /// Drop into an existing split's tab bar (before tab at index, or at end if None)
8    /// (target_split_id, insert_index)
9    TabBar(LeafId, Option<usize>),
10    /// Create a new split on the left edge of the target split
11    SplitLeft(LeafId),
12    /// Create a new split on the right edge of the target split
13    SplitRight(LeafId),
14    /// Create a new split on the top edge of the target split
15    SplitTop(LeafId),
16    /// Create a new split on the bottom edge of the target split
17    SplitBottom(LeafId),
18    /// Drop into the center of a split (switch to that split's tab bar)
19    SplitCenter(LeafId),
20}
21
22impl TabDropZone {
23    /// Get the split ID this drop zone is associated with
24    pub fn split_id(&self) -> LeafId {
25        match self {
26            Self::TabBar(id, _)
27            | Self::SplitLeft(id)
28            | Self::SplitRight(id)
29            | Self::SplitTop(id)
30            | Self::SplitBottom(id)
31            | Self::SplitCenter(id) => *id,
32        }
33    }
34}
35
36/// State for a tab being dragged
37#[derive(Debug, Clone)]
38pub struct TabDragState {
39    /// The buffer being dragged
40    pub buffer_id: BufferId,
41    /// The split the tab was dragged from
42    pub source_split_id: LeafId,
43    /// Starting mouse position when drag began
44    pub start_position: (u16, u16),
45    /// Current mouse position
46    pub current_position: (u16, u16),
47    /// Currently detected drop zone (if any)
48    pub drop_zone: Option<TabDropZone>,
49}
50
51impl TabDragState {
52    /// Create a new tab drag state
53    pub fn new(buffer_id: BufferId, source_split_id: LeafId, start_position: (u16, u16)) -> Self {
54        Self {
55            buffer_id,
56            source_split_id,
57            start_position,
58            current_position: start_position,
59            drop_zone: None,
60        }
61    }
62
63    /// Check if the drag has moved enough to be considered a real drag (not just a click)
64    pub fn is_dragging(&self) -> bool {
65        let dx = (self.current_position.0 as i32 - self.start_position.0 as i32).abs();
66        let dy = (self.current_position.1 as i32 - self.start_position.1 as i32).abs();
67        dx > 3 || dy > 3 // Threshold of 3 pixels before drag activates
68    }
69}