use crate::rect; use sdl2::{rect::Rect, render::Canvas, video::Window}; #[derive(Debug, Clone)] pub struct Container { pub start: (i32, i32), pub width: u32, pub height: u32, } pub enum Size { Max, Absolute(u32), } #[derive(Debug, Copy, PartialEq, Clone)] pub enum Offset { Top(u32), Left(u32), Bottom(u32), Right(u32), } #[derive(Debug, Copy, PartialEq, Clone)] pub enum HorAlign { Left, Center, Right, } #[derive(Debug, Copy, PartialEq, Clone)] pub enum VertAlign { Top, Center, Bottom, } impl Offset { fn apply(self, size: u32) -> u32 { match self { Self::Top(t) => t, Self::Left(l) => l, Self::Bottom(b) => size - b, Self::Right(r) => size - r, } } } impl Container { pub fn uninit() -> Self { Self { start: (0, 0), width: 0, height: 0, } } pub fn new(start_x: Offset, start_y: Offset, canvas: &Canvas) -> Self { let (winsize_x, winsize_y) = canvas.window().size(); Self { start: ( start_x.apply(winsize_x) as i32, start_y.apply(winsize_y) as i32, ), width: 0, height: 0, } } pub fn width(mut self, size: Size, canvas: &Canvas) -> Self { match size { Size::Max => { let (winsize_x, _) = canvas.window().size(); self.width = winsize_x; } Size::Absolute(x) => { self.width = x; } } self } pub fn height(mut self, size: Size, canvas: &Canvas) -> Self { match size { Size::Max => { let (_, winsize_y) = canvas.window().size(); self.height = winsize_y; } Size::Absolute(y) => { self.height = y; } } self } pub fn place(&self, widget: &mut Container, hor_align: HorAlign, vert_align: VertAlign) { let x = self.start.0 + match hor_align { HorAlign::Left => 0, HorAlign::Center => ((self.width / 2).saturating_sub(widget.width / 2)) as i32, HorAlign::Right => (self.width - widget.width) as i32, }; let y = self.start.1 + match vert_align { VertAlign::Top => 0, VertAlign::Center => ((self.height / 2).saturating_sub(widget.height / 2)) as i32, VertAlign::Bottom => (self.height - widget.height) as i32, }; widget.start = (x, y); } pub fn area(&self) -> Rect { rect!(self.start.0, self.start.1, self.width, self.height) } } #[derive(Debug, Copy, Clone)] pub struct Widget { width: u32, height: u32, } impl Widget { pub fn linear_layout(widgets: &[Widget], padding: u32) -> Widget { Widget { width: widgets.iter().fold(0, |acc, x| acc + x.width + padding), height: widgets.iter().map(|x| x.height).max().unwrap_or(0), } } }