1use duat_core::ui::Axis;
2
3use super::variables::Variables;
4use crate::{area::Coord, print::VarPoint};
5
6#[derive(Default, Clone, Copy, Debug)]
8pub enum Brush {
9 #[default]
11 Regular,
12 Thick,
14 Dashed,
16 ThickDashed,
18 Double,
20 Rounded,
22 Ascii,
24 Custom(char),
26}
27
28#[derive(Debug)]
30pub struct Edge {
31 lhs: VarPoint,
32 rhs: VarPoint,
33 axis: Axis,
34 fr: Frame,
35}
36
37impl Edge {
38 pub fn new(lhs: VarPoint, rhs: VarPoint, axis: Axis, fr: Frame) -> Self {
40 Self { lhs, rhs, axis, fr }
41 }
42
43 pub fn coords(&self, vars: &mut Variables) -> Option<EdgeCoords> {
45 let (lhs, _) = vars.coord(self.lhs, false);
46 let (rhs, _) = vars.coord(self.rhs, false);
47 if lhs.x == rhs.x || lhs.y == rhs.y {
48 return None;
49 }
50
51 let start = match self.axis {
52 Axis::Horizontal => Coord::new(rhs.x, lhs.y),
53 Axis::Vertical => Coord::new(lhs.x, rhs.y),
54 };
55 let end = match self.axis {
56 Axis::Horizontal => Coord::new(lhs.x, rhs.y),
57 Axis::Vertical => Coord::new(rhs.x, lhs.y),
58 };
59
60 Some(EdgeCoords::new(start, end, self.axis, self.fr.brush()))
61 }
62}
63
64#[derive(Clone, Copy)]
65pub struct EdgeCoords {
66 pub tl: Coord,
67 pub br: Coord,
68 pub axis: Axis,
69 pub line: Option<Brush>,
70}
71
72impl EdgeCoords {
73 fn new(tl: Coord, br: Coord, axis: Axis, line: Option<Brush>) -> Self {
74 Self { tl, br, axis, line }
75 }
76
77 #[allow(clippy::type_complexity)]
78 pub fn crossing(&self, other: EdgeCoords) -> Option<(Coord, [Option<Brush>; 4])> {
79 if let Axis::Vertical = self.axis {
80 if let Axis::Vertical = other.axis
81 && self.br.x == other.tl.x
82 && self.br.y + 2 == other.tl.y
83 {
84 let coord = Coord::new(self.br.x, self.br.y + 1);
85 return Some((coord, [None, self.line, None, other.line]));
86 } else {
87 return other.crossing(*self);
88 }
89 }
90
91 if let Axis::Horizontal = other.axis {
92 if self.br.y == other.br.y && self.br.x + 2 == other.tl.x {
93 let coord = Coord::new(self.br.x + 1, self.br.y);
94 Some((coord, [other.line, None, self.line, None]))
95 } else {
96 None
97 }
98 } else if self.tl.x <= other.tl.x + 1 && other.tl.x <= self.br.x + 1 {
99 let right_height = (other.tl.y..=other.br.y + 2).contains(&(self.br.y + 1));
100 let right = match right_height && other.br.x <= self.br.x {
101 true => self.line,
102 false => None,
103 };
104 let up = match other.tl.y <= self.tl.y && self.br.y <= other.br.y + 1 {
105 true => other.line,
106 false => None,
107 };
108 let left = match right_height && self.tl.x <= other.tl.x {
109 true => self.line,
110 false => None,
111 };
112 let down = match self.br.y <= other.br.y && other.tl.y <= self.tl.y + 1 {
113 true => other.line,
114 false => None,
115 };
116
117 if up.is_some() || down.is_some() {
118 let coord = Coord { x: other.tl.x, y: self.tl.y };
119
120 Some((coord, [right, up, left, down]))
121 } else {
122 None
123 }
124 } else {
125 None
126 }
127 }
128}
129
130#[derive(Clone, Copy, Debug)]
151pub enum Frame {
152 Empty,
154 Surround(Brush),
156 Border(Brush),
158 Vertical(Brush),
160 VerBorder(Brush),
162 Horizontal(Brush),
164 HorBorder(Brush),
166}
167
168impl Default for Frame {
169 fn default() -> Self {
170 Self::Border(Brush::Regular)
171 }
172}
173
174impl Frame {
175 pub(crate) fn files_edge_on(&self, axis: Axis) -> f64 {
179 let (hor_fr, ver_fr) = self.files_edges();
180 match axis {
181 Axis::Horizontal => hor_fr,
182 Axis::Vertical => ver_fr,
183 }
184 }
185
186 pub(crate) fn border_edge_on(&self, axis: Axis) -> f64 {
190 let (hor_fr, ver_fr) = self.border_edges();
191 match axis {
192 Axis::Horizontal => hor_fr,
193 Axis::Vertical => ver_fr,
194 }
195 }
196
197 fn brush(&self) -> Option<Brush> {
199 match self {
200 Self::Empty => None,
201 Self::Surround(brush)
202 | Self::Border(brush)
203 | Self::Vertical(brush)
204 | Self::VerBorder(brush)
205 | Self::Horizontal(brush)
206 | Self::HorBorder(brush) => Some(*brush),
207 }
208 }
209
210 fn files_edges(&self) -> (f64, f64) {
214 match self {
215 Self::Surround(_) => (1.0, 1.0),
216 Self::Vertical(_) => (1.0, 0.0),
217 Self::Horizontal(_) => (0.0, 1.0),
218 _ => (0.0, 0.0),
219 }
220 }
221
222 fn border_edges(&self) -> (f64, f64) {
226 match self {
227 Self::Surround(_) | Self::Border(_) => (1.0, 1.0),
228 Self::Vertical(_) | Self::VerBorder(_) => (1.0, 0.0),
229 Self::Horizontal(_) | Self::HorBorder(_) => (0.0, 1.0),
230 Self::Empty => (0.0, 0.0),
231 }
232 }
233}