use crate::geom::graph::node;
use crate::geom::{self, Point2, Point3};
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Properties<S = geom::scalar::Default> {
pub x: Option<Position<S>>,
pub y: Option<Position<S>>,
pub z: Option<Position<S>>,
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Position<S = geom::scalar::Default> {
Absolute(S),
Relative(Relative<S>, Option<node::Index>),
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Relative<S = geom::scalar::Default> {
Scalar(S),
Align(Align<S>),
Direction(Direction, S),
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Direction {
Forwards,
Backwards,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Align<S = geom::scalar::Default> {
Start(Option<S>),
Middle,
End(Option<S>),
}
pub trait SetPosition<S>: Sized {
fn properties(&mut self) -> &mut Properties<S>;
fn x_position(mut self, position: Position<S>) -> Self {
self.properties().x = Some(position);
self
}
fn y_position(mut self, position: Position<S>) -> Self {
self.properties().y = Some(position);
self
}
fn z_position(mut self, position: Position<S>) -> Self {
self.properties().z = Some(position);
self
}
fn x(self, x: S) -> Self {
self.x_position(Position::Absolute(x))
}
fn y(self, y: S) -> Self {
self.y_position(Position::Absolute(y))
}
fn z(self, y: S) -> Self {
self.z_position(Position::Absolute(y))
}
fn xy(self, p: Point2<S>) -> Self {
self.x(p.x).y(p.y)
}
fn xyz(self, p: Point3<S>) -> Self {
self.x(p.x).y(p.y).z(p.z)
}
fn x_y(self, x: S, y: S) -> Self {
self.xy(Point2 { x, y })
}
fn x_y_z(self, x: S, y: S, z: S) -> Self {
self.xyz(Point3 { x, y, z })
}
fn x_position_relative(self, x: Relative<S>) -> Self {
self.x_position(Position::Relative(x, None))
}
fn y_position_relative(self, y: Relative<S>) -> Self {
self.y_position(Position::Relative(y, None))
}
fn z_position_relative(self, z: Relative<S>) -> Self {
self.z_position(Position::Relative(z, None))
}
fn x_y_position_relative(self, x: Relative<S>, y: Relative<S>) -> Self {
self.x_position_relative(x).y_position_relative(y)
}
fn x_y_z_position_relative(self, x: Relative<S>, y: Relative<S>, z: Relative<S>) -> Self {
self.x_y_position_relative(x, y).z_position_relative(z)
}
fn x_position_relative_to(self, other: node::Index, x: Relative<S>) -> Self {
self.x_position(Position::Relative(x, Some(other)))
}
fn y_position_relative_to(self, other: node::Index, y: Relative<S>) -> Self {
self.y_position(Position::Relative(y, Some(other)))
}
fn z_position_relative_to(self, other: node::Index, z: Relative<S>) -> Self {
self.z_position(Position::Relative(z, Some(other)))
}
fn x_y_position_relative_to(self, other: node::Index, x: Relative<S>, y: Relative<S>) -> Self {
self.x_position_relative_to(other, x)
.y_position_relative_to(other, y)
}
fn x_y_z_position_relative_to(
self,
other: node::Index,
x: Relative<S>,
y: Relative<S>,
z: Relative<S>,
) -> Self {
self.x_y_position_relative_to(other, x, y)
.z_position_relative_to(other, z)
}
fn x_relative(self, x: S) -> Self {
self.x_position_relative(Relative::Scalar(x))
}
fn y_relative(self, y: S) -> Self {
self.y_position_relative(Relative::Scalar(y))
}
fn z_relative(self, z: S) -> Self {
self.z_position_relative(Relative::Scalar(z))
}
fn xy_relative(self, p: Point2<S>) -> Self {
self.x_relative(p.x).y_relative(p.y)
}
fn xyz_relative(self, p: Point3<S>) -> Self {
self.x_relative(p.x).y_relative(p.y).z_relative(p.z)
}
fn x_y_relative(self, x: S, y: S) -> Self {
self.xy_relative(Point2 { x, y })
}
fn x_y_z_relative(self, x: S, y: S, z: S) -> Self {
self.xyz_relative(Point3 { x, y, z })
}
fn x_relative_to(self, other: node::Index, x: S) -> Self {
self.x_position_relative_to(other, Relative::Scalar(x))
}
fn y_relative_to(self, other: node::Index, y: S) -> Self {
self.y_position_relative_to(other, Relative::Scalar(y))
}
fn z_relative_to(self, other: node::Index, z: S) -> Self {
self.z_position_relative_to(other, Relative::Scalar(z))
}
fn xy_relative_to(self, other: node::Index, p: Point2<S>) -> Self {
self.x_relative_to(other, p.x).y_relative_to(other, p.y)
}
fn xyz_relative_to(self, other: node::Index, p: Point3<S>) -> Self {
self.x_relative_to(other, p.x)
.y_relative_to(other, p.y)
.z_relative_to(other, p.z)
}
fn x_y_relative_to(self, other: node::Index, x: S, y: S) -> Self {
self.xy_relative_to(other, Point2 { x, y })
}
fn x_y_z_relative_to(self, other: node::Index, x: S, y: S, z: S) -> Self {
self.xyz_relative_to(other, Point3 { x, y, z })
}
fn x_direction(self, direction: Direction, x: S) -> Self {
self.x_position_relative(Relative::Direction(direction, x))
}
fn y_direction(self, direction: Direction, y: S) -> Self {
self.y_position_relative(Relative::Direction(direction, y))
}
fn z_direction(self, direction: Direction, z: S) -> Self {
self.z_position_relative(Relative::Direction(direction, z))
}
fn left(self, x: S) -> Self {
self.x_direction(Direction::Backwards, x)
}
fn right(self, x: S) -> Self {
self.x_direction(Direction::Forwards, x)
}
fn down(self, y: S) -> Self {
self.y_direction(Direction::Backwards, y)
}
fn up(self, y: S) -> Self {
self.y_direction(Direction::Forwards, y)
}
fn backwards(self, z: S) -> Self {
self.z_direction(Direction::Backwards, z)
}
fn forwards(self, z: S) -> Self {
self.z_direction(Direction::Forwards, z)
}
fn x_direction_from(self, other: node::Index, direction: Direction, x: S) -> Self {
self.x_position_relative_to(other, Relative::Direction(direction, x))
}
fn y_direction_from(self, other: node::Index, direction: Direction, y: S) -> Self {
self.y_position_relative_to(other, Relative::Direction(direction, y))
}
fn z_direction_from(self, other: node::Index, direction: Direction, z: S) -> Self {
self.z_position_relative_to(other, Relative::Direction(direction, z))
}
fn left_from(self, other: node::Index, x: S) -> Self {
self.x_direction_from(other, Direction::Backwards, x)
}
fn right_from(self, other: node::Index, x: S) -> Self {
self.x_direction_from(other, Direction::Forwards, x)
}
fn down_from(self, other: node::Index, y: S) -> Self {
self.y_direction_from(other, Direction::Backwards, y)
}
fn up_from(self, other: node::Index, y: S) -> Self {
self.y_direction_from(other, Direction::Forwards, y)
}
fn backwards_from(self, other: node::Index, z: S) -> Self {
self.z_direction_from(other, Direction::Backwards, z)
}
fn forwards_from(self, other: node::Index, z: S) -> Self {
self.z_direction_from(other, Direction::Forwards, z)
}
fn x_align(self, align: Align<S>) -> Self {
self.x_position_relative(Relative::Align(align))
}
fn y_align(self, align: Align<S>) -> Self {
self.y_position_relative(Relative::Align(align))
}
fn z_align(self, align: Align<S>) -> Self {
self.z_position_relative(Relative::Align(align))
}
fn align_left(self) -> Self {
self.x_align(Align::Start(None))
}
fn align_left_with_margin(self, margin: S) -> Self {
self.x_align(Align::Start(Some(margin)))
}
fn align_middle_x(self) -> Self {
self.x_align(Align::Middle)
}
fn align_right(self) -> Self {
self.x_align(Align::End(None))
}
fn align_right_with_margin(self, margin: S) -> Self {
self.x_align(Align::End(Some(margin)))
}
fn align_bottom(self) -> Self {
self.y_align(Align::Start(None))
}
fn align_bottom_with_margin(self, margin: S) -> Self {
self.y_align(Align::Start(Some(margin)))
}
fn align_middle_y(self) -> Self {
self.y_align(Align::Middle)
}
fn align_top(self) -> Self {
self.y_align(Align::End(None))
}
fn align_top_with_margin(self, margin: S) -> Self {
self.y_align(Align::End(Some(margin)))
}
fn align_front(self) -> Self {
self.z_align(Align::Start(None))
}
fn align_front_with_margin(self, margin: S) -> Self {
self.z_align(Align::Start(Some(margin)))
}
fn align_middle_z(self) -> Self {
self.z_align(Align::Middle)
}
fn align_back(self) -> Self {
self.z_align(Align::End(None))
}
fn align_back_with_margin(self, margin: S) -> Self {
self.z_align(Align::End(Some(margin)))
}
fn x_align_to(self, other: node::Index, align: Align<S>) -> Self {
self.x_position_relative_to(other, Relative::Align(align))
}
fn y_align_to(self, other: node::Index, align: Align<S>) -> Self {
self.y_position_relative_to(other, Relative::Align(align))
}
fn z_align_to(self, other: node::Index, align: Align<S>) -> Self {
self.z_position_relative_to(other, Relative::Align(align))
}
fn align_left_of(self, other: node::Index) -> Self {
self.x_align_to(other, Align::Start(None))
}
fn align_left_of_with_margin(self, other: node::Index, margin: S) -> Self {
self.x_align_to(other, Align::Start(Some(margin)))
}
fn align_middle_x_of(self, other: node::Index) -> Self {
self.x_align_to(other, Align::Middle)
}
fn align_right_of(self, other: node::Index) -> Self {
self.x_align_to(other, Align::End(None))
}
fn align_right_of_with_margin(self, other: node::Index, margin: S) -> Self {
self.x_align_to(other, Align::End(Some(margin)))
}
fn align_bottom_of(self, other: node::Index) -> Self {
self.y_align_to(other, Align::Start(None))
}
fn align_bottom_of_with_margin(self, other: node::Index, margin: S) -> Self {
self.y_align_to(other, Align::Start(Some(margin)))
}
fn align_middle_y_of(self, other: node::Index) -> Self {
self.y_align_to(other, Align::Middle)
}
fn align_top_of(self, other: node::Index) -> Self {
self.y_align_to(other, Align::End(None))
}
fn align_top_of_with_margin(self, other: node::Index, margin: S) -> Self {
self.y_align_to(other, Align::End(Some(margin)))
}
fn align_front_of(self, other: node::Index) -> Self {
self.z_align_to(other, Align::Start(None))
}
fn align_front_of_with_margin(self, other: node::Index, margin: S) -> Self {
self.z_align_to(other, Align::Start(Some(margin)))
}
fn align_middle_z_of(self, other: node::Index) -> Self {
self.z_align_to(other, Align::Middle)
}
fn align_back_of(self, other: node::Index) -> Self {
self.z_align_to(other, Align::End(None))
}
fn align_back_of_with_margin(self, other: node::Index, margin: S) -> Self {
self.z_align_to(other, Align::End(Some(margin)))
}
fn middle(self) -> Self {
self.align_middle_x().align_middle_y().align_middle_z()
}
fn bottom_left(self) -> Self {
self.align_left().align_bottom()
}
fn mid_left(self) -> Self {
self.align_left().align_middle_y()
}
fn top_left(self) -> Self {
self.align_left().align_top()
}
fn mid_top(self) -> Self {
self.align_middle_x().align_top()
}
fn top_right(self) -> Self {
self.align_right().align_top()
}
fn mid_right(self) -> Self {
self.align_right().align_middle_y()
}
fn bottom_right(self) -> Self {
self.align_right().align_bottom()
}
fn mid_bottom(self) -> Self {
self.align_middle_x().align_bottom()
}
fn middle_of(self, other: node::Index) -> Self {
self.align_middle_x_of(other)
.align_middle_y_of(other)
.align_middle_z_of(other)
}
fn bottom_left_of(self, other: node::Index) -> Self {
self.align_left_of(other).align_bottom_of(other)
}
fn mid_left_of(self, other: node::Index) -> Self {
self.align_left_of(other).align_middle_y_of(other)
}
fn top_left_of(self, other: node::Index) -> Self {
self.align_left_of(other).align_top_of(other)
}
fn mid_top_of(self, other: node::Index) -> Self {
self.align_middle_x_of(other).align_top_of(other)
}
fn top_right_of(self, other: node::Index) -> Self {
self.align_right_of(other).align_top_of(other)
}
fn mid_right_of(self, other: node::Index) -> Self {
self.align_right_of(other).align_middle_y_of(other)
}
fn bottom_right_of(self, other: node::Index) -> Self {
self.align_right_of(other).align_bottom_of(other)
}
fn mid_bottom_of(self, other: node::Index) -> Self {
self.align_middle_x_of(other).align_bottom_of(other)
}
}
impl<S> SetPosition<S> for Properties<S> {
fn properties(&mut self) -> &mut Properties<S> {
self
}
}
impl<S> Default for Properties<S> {
fn default() -> Self {
let x = None;
let y = None;
let z = None;
Properties { x, y, z }
}
}