use duat_core::ui::Axis;
use super::{VarPoint, variables::Variables};
use crate::area::Coord;
mod combinations;
pub use combinations::*;
#[derive(Default, Clone, Copy, Debug)]
pub enum BorderStyle {
#[default]
Regular,
Thick,
Dashed,
ThickDashed,
Double,
Rounded,
Ascii,
Custom(char),
}
#[derive(Debug, Clone)]
pub struct Edge {
lhs: VarPoint,
rhs: VarPoint,
axis: Axis,
fr: Border,
}
impl Edge {
pub fn new(lhs: VarPoint, rhs: VarPoint, axis: Axis, fr: Border) -> Self {
Self { lhs, rhs, axis, fr }
}
pub fn coords(&self, vars: &mut Variables) -> Option<EdgeCoords> {
let (lhs, _) = vars.coord(self.lhs, false);
let (rhs, _) = vars.coord(self.rhs, false);
if lhs.x == rhs.x || lhs.y == rhs.y {
return None;
}
let start = match self.axis {
Axis::Horizontal => Coord::new(rhs.x, lhs.y),
Axis::Vertical => Coord::new(lhs.x, rhs.y),
};
let end = match self.axis {
Axis::Horizontal => Coord::new(lhs.x, rhs.y),
Axis::Vertical => Coord::new(rhs.x, lhs.y),
};
Some(EdgeCoords::new(start, end, self.axis, self.fr.style()))
}
}
#[derive(Debug, Clone, Copy)]
pub struct EdgeCoords {
pub tl: Coord,
pub br: Coord,
pub axis: Axis,
pub line: Option<BorderStyle>,
}
impl EdgeCoords {
fn new(tl: Coord, br: Coord, axis: Axis, line: Option<BorderStyle>) -> Self {
Self { tl, br, axis, line }
}
pub fn crossing(&self, other: EdgeCoords) -> Option<(Coord, [Option<BorderStyle>; 4])> {
if let Axis::Vertical = self.axis {
if let Axis::Vertical = other.axis {
if self.br.x == other.tl.x && self.br.y + 2 == other.tl.y {
let coord = Coord::new(self.br.x, self.br.y + 1);
return Some((coord, [None, self.line, None, other.line]));
} else {
return None;
}
} else {
return other.crossing(*self);
}
}
if let Axis::Horizontal = other.axis {
if self.br.y == other.br.y && self.br.x + 2 == other.tl.x {
let coord = Coord::new(self.br.x + 1, self.br.y);
Some((coord, [other.line, None, self.line, None]))
} else {
None
}
} else if self.tl.x <= other.tl.x + 1 && other.tl.x <= self.br.x + 1 {
let right_height = (other.tl.y..=other.br.y + 2).contains(&(self.br.y + 1));
let right = match right_height && other.br.x <= self.br.x {
true => self.line,
false => None,
};
let up = match other.tl.y <= self.tl.y && self.br.y <= other.br.y + 1 {
true => other.line,
false => None,
};
let left = match right_height && self.tl.x <= other.tl.x {
true => self.line,
false => None,
};
let down = match self.br.y <= other.br.y && other.tl.y <= self.tl.y + 1 {
true => other.line,
false => None,
};
if up.is_some() || down.is_some() {
let coord = Coord { x: other.tl.x, y: self.tl.y };
Some((coord, [right, up, left, down]))
} else {
None
}
} else {
None
}
}
}
#[derive(Clone, Copy, Debug)]
pub enum Border {
Empty,
Surround(BorderStyle),
Border(BorderStyle),
Vertical(BorderStyle),
VerBorder(BorderStyle),
Horizontal(BorderStyle),
HorBorder(BorderStyle),
}
impl Default for Border {
fn default() -> Self {
Self::Border(BorderStyle::Regular)
}
}
impl Border {
pub(crate) fn buffers_len_on(&self, axis: Axis) -> f64 {
let (hor_len, ver_len) = self.buffers_edges();
match axis {
Axis::Horizontal => hor_len,
Axis::Vertical => ver_len,
}
}
pub(crate) fn len_on(&self, axis: Axis) -> f64 {
let (hor_len, ver_len) = self.border_edges();
match axis {
Axis::Horizontal => hor_len,
Axis::Vertical => ver_len,
}
}
fn style(&self) -> Option<BorderStyle> {
match self {
Self::Empty => None,
Self::Surround(style)
| Self::Border(style)
| Self::Vertical(style)
| Self::VerBorder(style)
| Self::Horizontal(style)
| Self::HorBorder(style) => Some(*style),
}
}
fn buffers_edges(&self) -> (f64, f64) {
match self {
Self::Surround(_) => (1.0, 1.0),
Self::Vertical(_) => (1.0, 0.0),
Self::Horizontal(_) => (0.0, 1.0),
_ => (0.0, 0.0),
}
}
fn border_edges(&self) -> (f64, f64) {
match self {
Self::Surround(_) | Self::Border(_) => (1.0, 1.0),
Self::Vertical(_) | Self::VerBorder(_) => (1.0, 0.0),
Self::Horizontal(_) | Self::HorBorder(_) => (0.0, 1.0),
Self::Empty => (0.0, 0.0),
}
}
}