use std::num::NonZeroU32;
use derive_more::{From, TryInto};
use crate::math::{num, Normalized};
use crate::interface::controller::{size, Alignment, Area, Offset, Orientation, Size};
use super::impl_kind;
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct Layout {
pub orientation : (Orientation, Area),
pub variant : Variant
}
impl_kind!(Layout);
#[derive(Clone, Debug, Eq, PartialEq, From, TryInto)]
pub enum Variant {
Tiled (Tiled),
Free (Free, Area)
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Tiled {
Weighted (NonZeroU32),
Absolute (NonZeroU32)
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Free {
pub anchor : Alignment,
pub offset : Offset,
pub size : Size
}
impl From <Variant> for Layout {
fn from (variant : Variant) -> Self {
Layout {
orientation: Default::default(),
variant
}
}
}
impl From <Free> for Variant {
fn from (free : Free) -> Self {
Variant::Free (free, Area::default())
}
}
impl Default for Variant {
fn default() -> Self {
(Free::default(), Area::default()).into()
}
}
impl Free {
#[inline]
pub fn default_tile() -> Self {
Free {
anchor: Alignment::tile(),
offset: Offset::default_absolute(),
size: Size {
width: 24.into(),
height: 12.into()
}
}
}
#[inline]
pub fn default_pixel() -> Self {
Free {
anchor: Alignment::pixel(),
offset: Offset::default_absolute(),
size: Size {
width: 640.into(),
height: 480.into()
}
}
}
pub fn tile (size : Size) -> Self {
Free {
anchor: Alignment::tile(),
offset: Offset::default_absolute(),
size
}
}
pub fn pixel (size : Size) -> Self {
Free {
anchor: Alignment::pixel(),
offset: Offset::default_absolute(),
size
}
}
pub fn middle_center (size : Size) -> Self {
Free {
anchor: Alignment::middle_center(),
offset: Offset::default_absolute(),
size
}
}
#[inline]
pub fn middle_center_max() -> Self {
use num::One;
Free {
anchor: Alignment::middle_center(),
size: Size {
width: Normalized::<f32>::one().into(),
height: Normalized::<f32>::one().into()
},
offset: Offset::default_absolute()
}
}
#[inline]
pub fn offset_move_right (&mut self) {
self.offset = self.offset.move_right (self.anchor, 1);
}
#[inline]
pub fn offset_move_left (&mut self) {
self.offset = self.offset.move_left (self.anchor, 1);
}
#[inline]
pub fn offset_move_up (&mut self) {
self.offset = self.offset.move_up (self.anchor, 1);
}
#[inline]
pub fn offset_move_down (&mut self) {
self.offset = self.offset.move_down (self.anchor, 1);
}
#[inline]
pub fn size_grow_width (&mut self) {
match self.size.width {
size::Unsigned::Absolute (ref mut width) =>
*width = std::cmp::max (1, *width as i32 + 1) as u32,
size::Unsigned::Relative (ref mut width) =>
*width = Normalized::clamp (**width + 1.0/60.0)
}
}
#[inline]
pub fn size_grow_height (&mut self) {
match self.size.height {
size::Unsigned::Absolute (ref mut height) =>
*height = std::cmp::max (1, *height as i32 + 1) as u32,
size::Unsigned::Relative (ref mut height) =>
*height = Normalized::clamp (**height + 1.0/60.0)
}
}
#[inline]
pub fn size_shrink_width (&mut self) {
match self.size.width {
size::Unsigned::Absolute (ref mut width) =>
*width = std::cmp::max (1, *width as i32 - 1) as u32,
size::Unsigned::Relative (ref mut width) =>
*width = Normalized::clamp ((**width - 1.0/60.0).max (1.0/60.0))
}
}
#[inline]
pub fn size_shrink_height (&mut self) {
match self.size.height {
size::Unsigned::Absolute (ref mut height) =>
*height = std::cmp::max (1, *height as i32 - 1) as u32,
size::Unsigned::Relative (ref mut height) =>
*height = Normalized::clamp ((**height - 1.0/60.0).max (1.0/60.0))
}
}
}
impl Default for Free {
fn default() -> Self {
Self::default_tile()
}
}
impl Tiled {
pub fn modify_size (&mut self, modify : i32) {
let size = match self {
Tiled::Weighted (n) | Tiled::Absolute (n) => n
};
let s = size.get() as i64 + modify as i64;
let new_size = s.max (1).min (u32::MAX as i64) as u32;
*size = NonZeroU32::new (new_size).unwrap();
}
}
impl Default for Tiled {
fn default() -> Self {
Tiled::Weighted (NonZeroU32::new (1).unwrap())
}
}