use graphics::character::CharacterCache;
use graphics::math::Scalar;
use theme::Theme;
use ui::GlyphCache;
use widget::WidgetId;
pub type Depth = f32;
pub type Dimensions = [Scalar; 2];
pub type Point = [Scalar; 2];
#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
pub enum Position {
Absolute(Scalar, Scalar),
Relative(Scalar, Scalar, Option<WidgetId>),
Direction(Direction, Scalar, Option<WidgetId>),
Place(Place, Option<WidgetId>),
}
impl Position {
pub fn default() -> Position{
Position::Direction(Direction::Down, 20.0, None)
}
}
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, PartialEq, Eq)]
pub enum Direction {
Up,
Down,
Left,
Right,
}
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, PartialEq, Eq)]
pub struct HorizontalAlign(pub Horizontal, pub Option<WidgetId>);
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, PartialEq, Eq)]
pub enum Horizontal {
Left,
Middle,
Right,
}
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, PartialEq, Eq)]
pub struct VerticalAlign(pub Vertical, pub Option<WidgetId>);
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, PartialEq, Eq)]
pub enum Vertical {
Top,
Middle,
Bottom,
}
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, PartialEq, Eq)]
pub enum Place {
Middle,
TopLeft,
TopRight,
BottomLeft,
BottomRight,
MidTop,
MidBottom,
MidLeft,
MidRight,
}
pub trait Positionable: Sized {
fn position(self, pos: Position) -> Self;
fn get_position(&self, theme: &Theme) -> Position;
fn point(self, point: Point) -> Self {
self.position(Position::Absolute(point[0], point[1]))
}
fn xy(self, x: Scalar, y: Scalar) -> Self {
self.position(Position::Absolute(x, y))
}
fn relative(self, point: Point) -> Self {
self.position(Position::Relative(point[0], point[1], None))
}
fn relative_xy(self, x: Scalar, y: Scalar) -> Self {
self.position(Position::Relative(x, y, None))
}
fn relative_to(self, other: WidgetId, point: Point) -> Self {
self.position(Position::Relative(point[0], point[1], Some(other)))
}
fn relative_xy_to(self, other: WidgetId, x: Scalar, y: Scalar) -> Self {
self.position(Position::Relative(x, y, Some(other)))
}
fn down(self, pixels: Scalar) -> Self {
self.position(Position::Direction(Direction::Down, pixels, None))
}
fn up(self, pixels: Scalar) -> Self {
self.position(Position::Direction(Direction::Up, pixels, None))
}
fn left(self, pixels: Scalar) -> Self {
self.position(Position::Direction(Direction::Left, pixels, None))
}
fn right(self, pixels: Scalar) -> Self {
self.position(Position::Direction(Direction::Right, pixels, None))
}
fn down_from(self, other: WidgetId, pixels: Scalar) -> Self {
self.position(Position::Direction(Direction::Down, pixels, Some(other)))
}
fn up_from(self, other: WidgetId, pixels: Scalar) -> Self {
self.position(Position::Direction(Direction::Up, pixels, Some(other)))
}
fn left_from(self, other: WidgetId, pixels: Scalar) -> Self {
self.position(Position::Direction(Direction::Left, pixels, Some(other)))
}
fn right_from(self, other: WidgetId, pixels: Scalar) -> Self {
self.position(Position::Direction(Direction::Right, pixels, Some(other)))
}
fn horizontal_align(self, align: HorizontalAlign) -> Self;
fn vertical_align(self, align: VerticalAlign) -> Self;
fn get_horizontal_align(&self, theme: &Theme) -> HorizontalAlign;
fn get_vertical_align(&self, theme: &Theme) -> VerticalAlign;
fn get_alignment(&self, theme: &Theme) -> (HorizontalAlign, VerticalAlign) {
(self.get_horizontal_align(theme), self.get_vertical_align(theme))
}
fn align_left(self) -> Self {
self.horizontal_align(HorizontalAlign(Horizontal::Left, None))
}
fn align_middle_x(self) -> Self {
self.horizontal_align(HorizontalAlign(Horizontal::Middle, None))
}
fn align_right(self) -> Self {
self.horizontal_align(HorizontalAlign(Horizontal::Right, None))
}
fn align_top(self) -> Self {
self.vertical_align(VerticalAlign(Vertical::Top, None))
}
fn align_middle_y(self) -> Self {
self.vertical_align(VerticalAlign(Vertical::Middle, None))
}
fn align_bottom(self) -> Self {
self.vertical_align(VerticalAlign(Vertical::Bottom, None))
}
fn align_left_of(self, other: WidgetId) -> Self {
self.horizontal_align(HorizontalAlign(Horizontal::Left, Some(other)))
}
fn align_middle_x_of(self, other: WidgetId) -> Self {
self.horizontal_align(HorizontalAlign(Horizontal::Middle, Some(other)))
}
fn align_right_of(self, other: WidgetId) -> Self {
self.horizontal_align(HorizontalAlign(Horizontal::Right, Some(other)))
}
fn align_top_of(self, other: WidgetId) -> Self {
self.vertical_align(VerticalAlign(Vertical::Top, Some(other)))
}
fn align_middle_y_of(self, other: WidgetId) -> Self {
self.vertical_align(VerticalAlign(Vertical::Middle, Some(other)))
}
fn align_bottom_of(self, other: WidgetId) -> Self {
self.vertical_align(VerticalAlign(Vertical::Bottom, Some(other)))
}
fn place(self, place: Place, maybe_id: Option<WidgetId>) -> Self {
self.position(Position::Place(place, maybe_id))
}
fn middle_of(self, id: WidgetId) -> Self { self.place(Place::Middle, Some(id)) }
fn top_left_of(self, id: WidgetId) -> Self { self.place(Place::TopLeft, Some(id)) }
fn top_right_of(self, id: WidgetId) -> Self { self.place(Place::TopRight, Some(id)) }
fn bottom_left_of(self, id: WidgetId) -> Self { self.place(Place::BottomLeft, Some(id)) }
fn bottom_right_of(self, id: WidgetId) -> Self { self.place(Place::BottomRight, Some(id)) }
fn mid_top_of(self, id: WidgetId) -> Self { self.place(Place::MidTop, Some(id)) }
fn mid_bottom_of(self, id: WidgetId) -> Self { self.place(Place::MidBottom, Some(id)) }
fn mid_left_of(self, id: WidgetId) -> Self { self.place(Place::MidLeft, Some(id)) }
fn mid_right_of(self, id: WidgetId) -> Self { self.place(Place::MidRight, Some(id)) }
fn middle(self) -> Self { self.place(Place::Middle, None) }
fn top_left(self) -> Self { self.place(Place::TopLeft, None) }
fn top_right(self) -> Self { self.place(Place::TopRight, None) }
fn bottom_left(self) -> Self { self.place(Place::BottomLeft, None) }
fn bottom_right(self) -> Self { self.place(Place::BottomRight, None) }
fn mid_top(self) -> Self { self.place(Place::MidTop, None) }
fn mid_bottom(self) -> Self { self.place(Place::MidBottom, None) }
fn mid_left(self) -> Self { self.place(Place::MidLeft, None) }
fn mid_right(self) -> Self { self.place(Place::MidRight, None) }
fn depth(self, depth: Depth) -> Self;
fn get_depth(&self) -> Depth;
}
pub trait Sizeable: Sized {
fn width(self, width: Scalar) -> Self;
fn height(self, height: Scalar) -> Self;
fn get_width<C: CharacterCache>(&self, theme: &Theme, glyph_cache: &GlyphCache<C>) -> Scalar;
fn get_height(&self, theme: &Theme) -> Scalar;
#[inline]
fn dim(self, dim: Dimensions) -> Self {
self.width(dim[0]).height(dim[1])
}
#[inline]
fn dimensions(self, width: Scalar, height: Scalar) -> Self {
self.dim([width, height])
}
fn get_dimensions<C: CharacterCache>(&self,
theme: &Theme,
glyph_cache: &GlyphCache<C>) -> Dimensions {
[self.get_width(theme, glyph_cache), self.get_height(theme)]
}
}
#[derive(Copy, Clone)]
pub enum Corner {
TopLeft,
TopRight,
BottomLeft,
BottomRight,
}
pub fn corner(xy: Point, dim: Dimensions) -> Corner {
use utils::map_range;
let x_perc = map_range(xy[0], -dim[0] / 2.0, dim[0] / 2.0, -1.0, 1.0);
let y_perc = map_range(xy[1], -dim[1] / 2.0, dim[1] / 2.0, -1.0, 1.0);
if x_perc <= 0.0 && y_perc <= 0.0 { Corner::BottomLeft }
else if x_perc > 0.0 && y_perc <= 0.0 { Corner::BottomRight }
else if x_perc <= 0.0 && y_perc > 0.0 { Corner::TopLeft }
else { Corner::TopRight }
}
pub fn align_left_of(target_width: Scalar, width: Scalar) -> Scalar {
width / 2.0 - target_width / 2.0
}
pub fn align_right_of(target_width: Scalar, width: Scalar) -> Scalar {
target_width / 2.0 - width / 2.0
}
pub fn align_bottom_of(target_height: Scalar, height: Scalar) -> Scalar {
height / 2.0 - target_height / 2.0
}
pub fn align_top_of(target_height: Scalar, height: Scalar) -> Scalar {
target_height / 2.0 - height / 2.0
}
impl Horizontal {
pub fn to(&self, target_width: Scalar, width: Scalar) -> Scalar {
match *self {
Horizontal::Left => align_left_of(target_width, width),
Horizontal::Right => align_right_of(target_width, width),
Horizontal::Middle => 0.0,
}
}
}
impl Vertical {
pub fn to(&self, target_height: Scalar, height: Scalar) -> Scalar {
match *self {
Vertical::Top => align_top_of(target_height, height),
Vertical::Bottom => align_bottom_of(target_height, height),
Vertical::Middle => 0.0,
}
}
}
pub fn middle_of(_target: Dimensions, _dim: Dimensions) -> Point {
[0.0, 0.0]
}
pub fn top_left_of(target: Dimensions, dim: Dimensions) -> Point {
[align_left_of(target[0], dim[0]), align_top_of(target[1], dim[1])]
}
pub fn top_right_of(target: Dimensions, dim: Dimensions) -> Point {
[align_right_of(target[0], dim[0]), align_top_of(target[1], dim[1])]
}
pub fn bottom_left_of(target: Dimensions, dim: Dimensions) -> Point {
[align_left_of(target[0], dim[0]), align_bottom_of(target[1], dim[1])]
}
pub fn bottom_right_of(target: Dimensions, dim: Dimensions) -> Point {
[align_right_of(target[0], dim[0]), align_bottom_of(target[1], dim[1])]
}
pub fn mid_top_of(target: Dimensions, dim: Dimensions) -> Point {
[0.0, align_top_of(target[1], dim[1])]
}
pub fn mid_bottom_of(target: Dimensions, dim: Dimensions) -> Point {
[0.0, align_bottom_of(target[1], dim[1])]
}
pub fn mid_left_of(target: Dimensions, dim: Dimensions) -> Point {
[align_left_of(target[0], dim[0]), 0.0]
}
pub fn mid_right_of(target: Dimensions, dim: Dimensions) -> Point {
[align_right_of(target[0], dim[0]), 0.0]
}
impl Place {
pub fn within(&self, target_dim: Dimensions, dim: Dimensions) -> Point {
match *self {
Place::Middle => middle_of(target_dim, dim),
Place::TopLeft => top_left_of(target_dim, dim),
Place::TopRight => top_right_of(target_dim, dim),
Place::BottomLeft => bottom_left_of(target_dim, dim),
Place::BottomRight => bottom_right_of(target_dim, dim),
Place::MidTop => mid_top_of(target_dim, dim),
Place::MidBottom => mid_bottom_of(target_dim, dim),
Place::MidLeft => mid_left_of(target_dim, dim),
Place::MidRight => mid_right_of(target_dim, dim),
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
pub struct Padding {
pub top: f64,
pub bottom: f64,
pub left: f64,
pub right: f64,
}
impl Padding {
pub fn none() -> Padding {
Padding { top: 0.0, bottom: 0.0, left: 0.0, right: 0.0 }
}
pub fn offset_from(&self, place: Place) -> Point {
match place {
Place::Middle => [0.0, 0.0],
Place::TopLeft => [self.left, -self.top],
Place::TopRight => [-self.right, -self.top],
Place::BottomLeft => [self.left, self.bottom],
Place::BottomRight => [-self.right, self.bottom],
Place::MidTop => [0.0, -self.top],
Place::MidBottom => [0.0, self.bottom],
Place::MidLeft => [self.left, 0.0],
Place::MidRight => [-self.right, 0.0],
}
}
}
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct Margin {
pub top: f64,
pub bottom: f64,
pub left: f64,
pub right: f64,
}
impl Margin {
pub fn none() -> Margin {
Margin { top: 0.0, bottom: 0.0, left: 0.0, right: 0.0 }
}
}