From 774177390e15dfc6b5bd8ff10100dc997e87a881 Mon Sep 17 00:00:00 2001 From: kossLAN Date: Fri, 29 May 2026 21:13:54 -0400 Subject: [PATCH] tree: split container drag destinations --- src/tree/container.rs | 128 +----------------------- src/tree/container/drag_destination.rs | 133 +++++++++++++++++++++++++ 2 files changed, 136 insertions(+), 125 deletions(-) create mode 100644 src/tree/container/drag_destination.rs diff --git a/src/tree/container.rs b/src/tree/container.rs index 72d6eef7..3b981490 100644 --- a/src/tree/container.rs +++ b/src/tree/container.rs @@ -1,8 +1,11 @@ +mod drag_destination; mod tasks; +pub use drag_destination::default_tile_drag_destination; pub use tasks::{container_layout, container_render_positions, container_tab_render_textures}; use { + drag_destination::direction_to_split, crate::{ backend::ButtonState, cursor::KnownCursor, @@ -2521,128 +2524,3 @@ impl ToplevelNodeBase for ContainerNode { } } } - -fn direction_to_split(dir: Direction) -> (ContainerSplit, bool) { - match dir { - Direction::Left => (ContainerSplit::Horizontal, true), - Direction::Down => (ContainerSplit::Vertical, false), - Direction::Up => (ContainerSplit::Vertical, true), - Direction::Right => (ContainerSplit::Horizontal, false), - Direction::Unspecified => (ContainerSplit::Horizontal, true), - } -} - -fn tile_drag_destination_in_mono( - tl: Rc, - abs_bounds: Rect, - abs_x: i32, - abs_y: i32, -) -> TileDragDestination { - let mut x1 = abs_bounds.x1(); - let mut x2 = abs_bounds.x2(); - let mut y1 = abs_bounds.y1(); - let mut y2 = abs_bounds.y2(); - let dx = (x2 - x1) / 3; - let dy = (y2 - y1) / 3; - let mut split_before = true; - let mut split = ContainerSplit::Horizontal; - if abs_x < x1 + dx { - x2 = x1 + dx; - } else if abs_x > x2 - dx { - split_before = false; - x1 = x2 - dx; - } else { - split = ContainerSplit::Vertical; - x1 += dx; - x2 -= dx; - if abs_y < y1 + dy { - y2 = y1 + dy; - } else if abs_y > y2 - dy { - split_before = false; - y1 = y2 - dy; - } else { - let rect = Rect::new_saturating(x1, y1 + dy, x2, y2 - dy); - return TileDragDestination { - highlight: rect, - ty: TddType::Replace(tl), - }; - } - } - let rect = Rect::new_saturating(x1, y1, x2, y2); - TileDragDestination { - highlight: rect, - ty: TddType::Split { - node: tl, - split, - before: split_before, - }, - } -} - -fn tile_drag_destination_in_split( - tl: Rc, - split: ContainerSplit, - abs_bounds: Rect, - mut abs_x: i32, - mut abs_y: i32, -) -> TileDragDestination { - let mut x1 = abs_bounds.x1(); - let mut x2 = abs_bounds.x2(); - let mut y1 = abs_bounds.y1(); - let mut y2 = abs_bounds.y2(); - macro_rules! swap { - () => { - if split == ContainerSplit::Horizontal { - mem::swap(&mut x1, &mut y1); - mem::swap(&mut x2, &mut y2); - mem::swap(&mut abs_x, &mut abs_y); - } - }; - } - swap!(); - let mut split_before = false; - let mut split_after = false; - let dx = (x2 - x1) / 3; - if abs_x < x1 + dx { - split_before = true; - x2 = x1 + dx; - } else if abs_x < x2 - dx { - x1 += dx; - x2 -= dx; - } else { - split_after = true; - x1 = x2 - dx; - } - swap!(); - let rect = Rect::new_saturating(x1, y1, x2, y2); - let ty = if split_before || split_after { - TddType::Split { - node: tl, - split: split.other(), - before: split_before, - } - } else { - TddType::Replace(tl) - }; - TileDragDestination { - highlight: rect, - ty, - } -} - -pub fn default_tile_drag_destination( - tl: Rc, - source: NodeId, - split: Option, - abs_bounds: Rect, - abs_x: i32, - abs_y: i32, -) -> Option { - if tl.node_id() == source { - return None; - } - Some(match split { - None => tile_drag_destination_in_mono(tl, abs_bounds, abs_x, abs_y), - Some(s) => tile_drag_destination_in_split(tl, s, abs_bounds, abs_x, abs_y), - }) -} diff --git a/src/tree/container/drag_destination.rs b/src/tree/container/drag_destination.rs new file mode 100644 index 00000000..81b9f197 --- /dev/null +++ b/src/tree/container/drag_destination.rs @@ -0,0 +1,133 @@ +use { + super::ContainerSplit, + crate::{ + rect::Rect, + tree::{Direction, NodeId, TddType, TileDragDestination, ToplevelNode}, + }, + std::{mem, rc::Rc}, +}; + +pub(super) fn direction_to_split(dir: Direction) -> (ContainerSplit, bool) { + match dir { + Direction::Left => (ContainerSplit::Horizontal, true), + Direction::Down => (ContainerSplit::Vertical, false), + Direction::Up => (ContainerSplit::Vertical, true), + Direction::Right => (ContainerSplit::Horizontal, false), + Direction::Unspecified => (ContainerSplit::Horizontal, true), + } +} + +fn tile_drag_destination_in_mono( + tl: Rc, + abs_bounds: Rect, + abs_x: i32, + abs_y: i32, +) -> TileDragDestination { + let mut x1 = abs_bounds.x1(); + let mut x2 = abs_bounds.x2(); + let mut y1 = abs_bounds.y1(); + let mut y2 = abs_bounds.y2(); + let dx = (x2 - x1) / 3; + let dy = (y2 - y1) / 3; + let mut split_before = true; + let mut split = ContainerSplit::Horizontal; + if abs_x < x1 + dx { + x2 = x1 + dx; + } else if abs_x > x2 - dx { + split_before = false; + x1 = x2 - dx; + } else { + split = ContainerSplit::Vertical; + x1 += dx; + x2 -= dx; + if abs_y < y1 + dy { + y2 = y1 + dy; + } else if abs_y > y2 - dy { + split_before = false; + y1 = y2 - dy; + } else { + let rect = Rect::new_saturating(x1, y1 + dy, x2, y2 - dy); + return TileDragDestination { + highlight: rect, + ty: TddType::Replace(tl), + }; + } + } + let rect = Rect::new_saturating(x1, y1, x2, y2); + TileDragDestination { + highlight: rect, + ty: TddType::Split { + node: tl, + split, + before: split_before, + }, + } +} + +fn tile_drag_destination_in_split( + tl: Rc, + split: ContainerSplit, + abs_bounds: Rect, + mut abs_x: i32, + mut abs_y: i32, +) -> TileDragDestination { + let mut x1 = abs_bounds.x1(); + let mut x2 = abs_bounds.x2(); + let mut y1 = abs_bounds.y1(); + let mut y2 = abs_bounds.y2(); + macro_rules! swap { + () => { + if split == ContainerSplit::Horizontal { + mem::swap(&mut x1, &mut y1); + mem::swap(&mut x2, &mut y2); + mem::swap(&mut abs_x, &mut abs_y); + } + }; + } + swap!(); + let mut split_before = false; + let mut split_after = false; + let dx = (x2 - x1) / 3; + if abs_x < x1 + dx { + split_before = true; + x2 = x1 + dx; + } else if abs_x < x2 - dx { + x1 += dx; + x2 -= dx; + } else { + split_after = true; + x1 = x2 - dx; + } + swap!(); + let rect = Rect::new_saturating(x1, y1, x2, y2); + let ty = if split_before || split_after { + TddType::Split { + node: tl, + split: split.other(), + before: split_before, + } + } else { + TddType::Replace(tl) + }; + TileDragDestination { + highlight: rect, + ty, + } +} + +pub fn default_tile_drag_destination( + tl: Rc, + source: NodeId, + split: Option, + abs_bounds: Rect, + abs_x: i32, + abs_y: i32, +) -> Option { + if tl.node_id() == source { + return None; + } + Some(match split { + None => tile_drag_destination_in_mono(tl, abs_bounds, abs_x, abs_y), + Some(s) => tile_drag_destination_in_split(tl, s, abs_bounds, abs_x, abs_y), + }) +}