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}