mod block;
mod empty;
mod error;
mod horizontal;
mod vertical;
use agape_core::{Bounds, GlobalId};
pub use agape_core::{Position, Size};
pub use block::BlockLayout;
pub use empty::EmptyLayout;
pub use error::LayoutError;
pub use horizontal::HorizontalLayout;
use std::fmt::Debug;
pub use vertical::VerticalLayout;
pub struct LayoutSolver;
impl LayoutSolver {
pub fn solve(root: &mut dyn Layout, window_size: Size) -> Vec<LayoutError> {
root.set_max_width(window_size.width);
root.set_max_height(window_size.height);
let _ = root.solve_min_constraints();
root.solve_max_contraints(window_size);
root.update_size();
root.position_children();
vec![]
}
}
pub trait Layout: Debug + Send + Sync {
fn solve_min_constraints(&mut self) -> (f32, f32);
fn solve_max_contraints(&mut self, space: Size);
fn position_children(&mut self);
fn update_size(&mut self);
fn collect_errors(&mut self) -> Vec<LayoutError>;
fn id(&self) -> GlobalId;
fn constraints(&self) -> BoxConstraints;
fn intrinsic_size(&self) -> IntrinsicSize;
fn size(&self) -> Size;
fn position(&self) -> Position;
fn bounds(&self) -> Bounds {
Bounds::new(self.position(), self.size())
}
fn children(&self) -> &[Box<dyn Layout>];
fn set_max_width(&mut self, width: f32);
fn set_max_height(&mut self, height: f32);
fn set_min_width(&mut self, width: f32);
fn set_min_height(&mut self, height: f32);
fn set_position(&mut self, position: Position);
fn set_x(&mut self, x: f32);
fn set_y(&mut self, y: f32);
fn iter(&self) -> LayoutIter;
fn get(&self, id: GlobalId) -> Option<&dyn Layout> {
self.iter().find(|&layout| layout.id() == id)
}
}
pub struct LayoutIter<'a> {
stack: Vec<&'a dyn Layout>,
}
impl<'a> Iterator for LayoutIter<'a> {
type Item = &'a dyn Layout;
fn next(&mut self) -> Option<Self::Item> {
if let Some(layout) = self.stack.pop() {
let children = layout.children();
let k = children.iter().map(|child| {
child.as_ref()
});
self.stack.extend(k.rev());
return Some(layout);
}
None
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, PartialOrd)]
pub enum BoxSizing {
Fixed(f32),
#[default]
Shrink,
Flex(u8),
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord)]
pub enum AxisAlignment {
#[default]
Start,
Center,
End,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, PartialOrd)]
pub struct BoxConstraints {
pub max_width: f32,
pub max_height: f32,
pub min_height: f32,
pub min_width: f32,
}
impl BoxConstraints {
pub fn new() -> Self {
Self::default()
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, PartialOrd)]
pub struct IntrinsicSize {
pub width: BoxSizing,
pub height: BoxSizing,
}
impl IntrinsicSize {
pub fn fill() -> Self {
Self {
width: BoxSizing::Flex(1),
height: BoxSizing::Flex(1),
}
}
pub fn fixed(width: f32, height: f32) -> Self {
Self {
width: BoxSizing::Fixed(width),
height: BoxSizing::Fixed(height),
}
}
}