use crate::constraints::impl_constraints;
use crate::{
BoxConstraints, BoxSizing, GlobalId, IntrinsicSize, Layout, LayoutIter, Position, Size,
};
#[derive(Debug, Default, Clone, PartialEq, PartialOrd)]
pub struct EmptyLayout {
id: GlobalId,
pub(crate) size: Size,
position: Position,
intrinsic_size: IntrinsicSize,
constraints: BoxConstraints,
errors: Vec<crate::LayoutError>,
label: Option<String>,
}
impl EmptyLayout {
pub fn new() -> Self {
Self::default()
}
pub fn set_id(mut self, id: GlobalId) -> Self {
self.id = id;
self
}
pub fn with_label(mut self, label: &str) -> Self {
self.label = Some(label.to_string());
self
}
impl_constraints!();
}
impl Layout for EmptyLayout {
fn label(&self) -> String {
self.label.clone().unwrap_or("EmptyLayout".to_string())
}
fn solve_min_constraints(&mut self) -> (f32, f32) {
if let BoxSizing::Fixed(width) = self.intrinsic_size.width {
self.constraints.min_width = Some(width);
}
if let BoxSizing::Fixed(height) = self.intrinsic_size.height {
self.constraints.min_height = Some(height);
}
(
self.constraints.min_width.unwrap_or_default(),
self.constraints.min_height.unwrap_or_default(),
)
}
fn solve_max_constraints(&mut self) {}
fn position_children(&mut self) {}
fn update_size(&mut self) {
match self.intrinsic_size.width {
BoxSizing::Flex(_) => {
self.size.width = self.constraints.max_width.unwrap_or_default();
}
BoxSizing::Shrink => {
self.size.width = self.constraints.min_width.unwrap_or_default();
}
BoxSizing::Fixed(width) => {
self.size.width = width;
}
}
match self.intrinsic_size.height {
BoxSizing::Flex(_) => {
self.size.height = self.constraints.max_height.unwrap_or_default();
}
BoxSizing::Shrink => {
self.size.height = self.constraints.min_height.unwrap_or_default();
}
BoxSizing::Fixed(height) => {
self.size.height = height;
}
}
}
fn collect_errors(&mut self) -> Vec<crate::LayoutError> {
self.errors.drain(..).collect::<Vec<_>>()
}
fn id(&self) -> GlobalId {
self.id
}
fn constraints(&self) -> BoxConstraints {
self.constraints
}
fn get_intrinsic_size(&self) -> IntrinsicSize {
self.intrinsic_size
}
fn size(&self) -> Size {
self.size
}
fn position(&self) -> Position {
self.position
}
fn children(&self) -> &[Box<dyn Layout>] {
&[]
}
fn set_max_width(&mut self, width: f32) {
self.constraints.max_width = Some(width);
}
fn set_max_height(&mut self, height: f32) {
self.constraints.max_height = Some(height);
}
fn set_min_width(&mut self, width: f32) {
self.constraints.min_width = Some(width);
}
fn set_min_height(&mut self, height: f32) {
self.constraints.min_height = Some(height);
}
fn set_position(&mut self, position: Position) {
self.position = position;
}
fn set_x(&mut self, x: f32) {
self.position.x = x;
}
fn set_y(&mut self, y: f32) {
self.position.y = y;
}
fn iter(&self) -> LayoutIter<'_> {
LayoutIter { stack: vec![self] }
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::solve_layout;
#[test]
fn flex_sizing() {
let window = Size::new(800.0, 800.0);
let mut root = EmptyLayout::new();
root.intrinsic_size.width = BoxSizing::Flex(2);
root.intrinsic_size.height = BoxSizing::Flex(2);
solve_layout(&mut root, window);
assert_eq!(root.size(), window);
}
#[test]
fn fixed_min_width_precedence() {
let mut root = EmptyLayout::new()
.intrinsic_size(IntrinsicSize::fixed(30.0, 50.0))
.min_width(20.0);
let (width, _) = root.solve_min_constraints();
assert_eq!(width, 30.0);
}
#[test]
fn min_width() {
let mut root = EmptyLayout::new().min_width(20.0);
let (width, _) = root.solve_min_constraints();
assert_eq!(width, 20.0);
}
#[test]
fn min_height() {
let mut root = EmptyLayout::new().min_height(20.0);
let (_, height) = root.solve_min_constraints();
assert_eq!(height, 20.0);
}
#[test]
fn fixed_sizing() {
let window = Size::new(800.0, 800.0);
let mut root = EmptyLayout::new();
root.intrinsic_size.width = BoxSizing::Fixed(200.0);
root.intrinsic_size.height = BoxSizing::Fixed(125.0);
solve_layout(&mut root, window);
assert_eq!(root.size(), Size::new(200.0, 125.0));
}
#[test]
fn shrink_sizing() {
let window = Size::new(800.0, 800.0);
let mut root = EmptyLayout::new();
solve_layout(&mut root, window);
assert_eq!(root.size(), Size::default());
}
}