2016-07-15 03:27:15 +00:00
|
|
|
//! Direction-related structures.
|
|
|
|
//!
|
|
|
|
//! This module defines two main concepts: [Orientation] and [Direction].
|
|
|
|
//!
|
|
|
|
//! ### Orientation
|
|
|
|
//!
|
|
|
|
//! `Orientation` is a simple enum that can take two values:
|
|
|
|
//! `Horizontal` or `Vertical`.
|
|
|
|
//!
|
|
|
|
//! ### Direction
|
|
|
|
//!
|
|
|
|
//! `Direction` is a bit more complex, and can be of two kinds:
|
2016-07-15 05:50:35 +00:00
|
|
|
//!
|
2016-07-15 03:27:15 +00:00
|
|
|
//! * Absolute direction: left, up, right, or down
|
|
|
|
//! * Relative direction: front or back.
|
|
|
|
//! Its actual direction depends on the orientation.
|
|
|
|
|
2017-02-07 02:18:17 +00:00
|
|
|
use vec::Vec2;
|
2018-05-18 00:37:39 +00:00
|
|
|
use XY;
|
2016-07-15 03:27:15 +00:00
|
|
|
|
|
|
|
/// Describes a vertical or horizontal orientation for a view.
|
2017-10-12 23:38:55 +00:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
2016-07-15 03:27:15 +00:00
|
|
|
pub enum Orientation {
|
|
|
|
/// Horizontal orientation
|
|
|
|
Horizontal,
|
|
|
|
/// Vertical orientation
|
|
|
|
Vertical,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Orientation {
|
2018-06-15 23:41:20 +00:00
|
|
|
/// Returns a `XY(Horizontal, Vertical)`.
|
|
|
|
pub fn pair() -> XY<Orientation> {
|
|
|
|
XY::new(Orientation::Horizontal, Orientation::Vertical)
|
|
|
|
}
|
|
|
|
|
2016-07-15 03:27:15 +00:00
|
|
|
/// Returns the component of `v` corresponding to this orientation.
|
|
|
|
///
|
|
|
|
/// (`Horizontal` will return the x value,
|
|
|
|
/// and `Vertical` will return the y value.)
|
2017-01-11 01:39:21 +00:00
|
|
|
pub fn get<T: Clone>(&self, v: &XY<T>) -> T {
|
|
|
|
v.get(*self).clone()
|
2016-07-15 03:27:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the other orientation.
|
|
|
|
pub fn swap(&self) -> Self {
|
|
|
|
match *self {
|
|
|
|
Orientation::Horizontal => Orientation::Vertical,
|
|
|
|
Orientation::Vertical => Orientation::Horizontal,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns a mutable reference to the component of the given vector
|
|
|
|
/// corresponding to this orientation.
|
2017-01-11 01:39:21 +00:00
|
|
|
pub fn get_ref<'a, 'b, T>(&'a self, v: &'b mut XY<T>) -> &'b mut T {
|
2016-07-15 03:27:15 +00:00
|
|
|
match *self {
|
|
|
|
Orientation::Horizontal => &mut v.x,
|
|
|
|
Orientation::Vertical => &mut v.y,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Takes an iterator on sizes, and stack them in the current orientation,
|
|
|
|
/// returning the size of the required bounding box.
|
|
|
|
///
|
|
|
|
/// For an horizontal view, returns (Sum(x), Max(y)).
|
|
|
|
/// For a vertical view, returns (Max(x),Sum(y)).
|
|
|
|
pub fn stack<'a, T: Iterator<Item = &'a Vec2>>(&self, iter: T) -> Vec2 {
|
|
|
|
match *self {
|
|
|
|
Orientation::Horizontal => {
|
|
|
|
iter.fold(Vec2::zero(), |a, b| a.stack_horizontal(b))
|
|
|
|
}
|
|
|
|
Orientation::Vertical => {
|
|
|
|
iter.fold(Vec2::zero(), |a, b| a.stack_vertical(b))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Creates a new `Vec2` with `value` in `self`'s axis.
|
2016-08-13 08:03:40 +00:00
|
|
|
pub fn make_vec(&self, main_axis: usize, second_axis: usize) -> Vec2 {
|
2016-07-15 03:27:15 +00:00
|
|
|
let mut result = Vec2::zero();
|
2016-08-13 08:03:40 +00:00
|
|
|
*self.get_ref(&mut result) = main_axis;
|
|
|
|
*self.swap().get_ref(&mut result) = second_axis;
|
2016-07-15 03:27:15 +00:00
|
|
|
result
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Represents a direction, either absolute or orientation-dependent.
|
|
|
|
///
|
|
|
|
/// * Absolute directions are Up, Down, Left, and Right.
|
|
|
|
/// * Relative directions are Front and Back.
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
|
|
|
pub enum Direction {
|
|
|
|
/// An absolute direction.
|
|
|
|
Abs(Absolute),
|
|
|
|
/// A direction relative to the current orientation.
|
|
|
|
Rel(Relative),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Direction {
|
|
|
|
/// Returns the relative direction for the given orientation.
|
|
|
|
pub fn relative(self, orientation: Orientation) -> Option<Relative> {
|
|
|
|
match self {
|
|
|
|
Direction::Abs(abs) => abs.relative(orientation),
|
|
|
|
Direction::Rel(rel) => Some(rel),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the absolute direction in the given `orientation`.
|
|
|
|
pub fn absolute(self, orientation: Orientation) -> Absolute {
|
|
|
|
match self {
|
|
|
|
Direction::Abs(abs) => abs,
|
|
|
|
Direction::Rel(rel) => rel.absolute(orientation),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Shortcut to create `Direction::Rel(Relative::Back)`
|
|
|
|
pub fn back() -> Self {
|
|
|
|
Direction::Rel(Relative::Back)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Shortcut to create `Direction::Rel(Relative::Front)`
|
|
|
|
pub fn front() -> Self {
|
|
|
|
Direction::Rel(Relative::Front)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Shortcut to create `Direction::Abs(Absolute::Left)`
|
|
|
|
pub fn left() -> Self {
|
|
|
|
Direction::Abs(Absolute::Left)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Shortcut to create `Direction::Abs(Absolute::Right)`
|
|
|
|
pub fn right() -> Self {
|
|
|
|
Direction::Abs(Absolute::Right)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Shortcut to create `Direction::Abs(Absolute::Up)`
|
|
|
|
pub fn up() -> Self {
|
|
|
|
Direction::Abs(Absolute::Up)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Shortcut to create `Direction::Abs(Absolute::Down)`
|
|
|
|
pub fn down() -> Self {
|
|
|
|
Direction::Abs(Absolute::Down)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Shortcut to create `Direction::Abs(Absolute::None)`
|
|
|
|
pub fn none() -> Self {
|
|
|
|
Direction::Abs(Absolute::None)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Direction relative to an orientation.
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
|
|
|
pub enum Relative {
|
|
|
|
/// Front relative direction.
|
|
|
|
///
|
|
|
|
/// * Horizontally, this means `Left`
|
|
|
|
/// * Vertically, this means `Up`
|
|
|
|
///
|
|
|
|
/// TODO: handle right-to-left?
|
|
|
|
Front,
|
|
|
|
|
|
|
|
/// Back relative direction.
|
|
|
|
///
|
|
|
|
/// * Horizontally, this means `Right`
|
|
|
|
/// * Vertically, this means `Down`.
|
|
|
|
Back,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Relative {
|
|
|
|
/// Returns the absolute direction in the given `orientation`.
|
|
|
|
pub fn absolute(self, orientation: Orientation) -> Absolute {
|
|
|
|
match (orientation, self) {
|
|
|
|
(Orientation::Horizontal, Relative::Front) => Absolute::Left,
|
|
|
|
(Orientation::Horizontal, Relative::Back) => Absolute::Right,
|
|
|
|
(Orientation::Vertical, Relative::Front) => Absolute::Up,
|
|
|
|
(Orientation::Vertical, Relative::Back) => Absolute::Down,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Absolute direction (up, down, left, right).
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
|
|
|
pub enum Absolute {
|
|
|
|
/// Left
|
|
|
|
Left,
|
|
|
|
/// Up
|
|
|
|
Up,
|
|
|
|
/// Right
|
|
|
|
Right,
|
|
|
|
/// Down
|
|
|
|
Down,
|
|
|
|
|
2016-07-15 05:50:35 +00:00
|
|
|
/// No real direction.
|
|
|
|
///
|
|
|
|
/// Used when the "direction" is accross layers for instance.
|
2016-07-15 03:27:15 +00:00
|
|
|
None,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Absolute {
|
|
|
|
/// Returns the relative direction for the given orientation.
|
|
|
|
///
|
|
|
|
/// Returns `None` when the direction does not apply to the given
|
|
|
|
/// orientation (ex: `Left` and `Vertical`).
|
|
|
|
pub fn relative(self, orientation: Orientation) -> Option<Relative> {
|
|
|
|
match (orientation, self) {
|
2017-12-30 22:03:42 +00:00
|
|
|
(Orientation::Horizontal, Absolute::Left)
|
|
|
|
| (Orientation::Vertical, Absolute::Up) => Some(Relative::Front),
|
|
|
|
(Orientation::Horizontal, Absolute::Right)
|
|
|
|
| (Orientation::Vertical, Absolute::Down) => Some(Relative::Back),
|
2016-07-15 03:27:15 +00:00
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|