use super::layout_manager::{LayoutStrategy, LayoutConstraints, LayoutResult, ComponentId};
use std::collections::HashMap;
pub struct HorizontalLayout {
children: HashMap<ComponentId, f32>, spacing: f32,
padding: f32,
}
impl HorizontalLayout {
pub fn new(spacing: f32, padding: f32) -> Self {
Self {
children: HashMap::new(),
spacing,
padding,
}
}
}
impl LayoutStrategy for HorizontalLayout {
fn calculate_layout(&self, constraints: LayoutConstraints) -> LayoutResult {
let total_weight: f32 = self.children.values().sum();
let child_count = self.children.len() as f32;
let available_width = constraints.max_width - (self.padding * 2.0) -
(self.spacing * (child_count - 1.0)).max(0.0);
let width = constraints.max_width.min(constraints.min_width.max(
self.padding * 2.0 +
(if total_weight > 0.0 { available_width } else { 0.0 }) +
(self.spacing * (child_count - 1.0)).max(0.0)
));
LayoutResult {
x: 0.0,
y: 0.0,
width,
height: constraints.max_height,
}
}
fn add_child(&mut self, child_id: ComponentId, weight: f32) {
self.children.insert(child_id, weight.max(0.01));
}
fn remove_child(&mut self, child_id: ComponentId) {
self.children.remove(&child_id);
}
fn update_child_constraints(&self,
child_id: ComponentId,
parent_constraints: LayoutConstraints) -> LayoutConstraints {
if let Some(weight) = self.children.get(&child_id) {
let total_weight: f32 = self.children.values().sum();
let child_count = self.children.len() as f32;
let available_width = parent_constraints.max_width - (self.padding * 2.0) -
(self.spacing * (child_count - 1.0)).max(0.0);
let child_width = if total_weight > 0.0 {
(available_width * weight / total_weight).max(0.0)
} else {
0.0
};
LayoutConstraints {
min_width: child_width,
max_width: child_width,
min_height: 0.0,
max_height: parent_constraints.max_height - (self.padding * 2.0),
}
} else {
parent_constraints
}
}
}
pub struct VerticalLayout {
children: HashMap<ComponentId, f32>, spacing: f32,
padding: f32,
}
impl VerticalLayout {
pub fn new(spacing: f32, padding: f32) -> Self {
Self {
children: HashMap::new(),
spacing,
padding,
}
}
}
impl LayoutStrategy for VerticalLayout {
fn calculate_layout(&self, constraints: LayoutConstraints) -> LayoutResult {
let total_weight: f32 = self.children.values().sum();
let child_count = self.children.len() as f32;
let available_height = constraints.max_height - (self.padding * 2.0) -
(self.spacing * (child_count - 1.0)).max(0.0);
let height = constraints.max_height.min(constraints.min_height.max(
self.padding * 2.0 +
(if total_weight > 0.0 { available_height } else { 0.0 }) +
(self.spacing * (child_count - 1.0)).max(0.0)
));
LayoutResult {
x: 0.0,
y: 0.0,
width: constraints.max_width,
height,
}
}
fn add_child(&mut self, child_id: ComponentId, weight: f32) {
self.children.insert(child_id, weight.max(0.01));
}
fn remove_child(&mut self, child_id: ComponentId) {
self.children.remove(&child_id);
}
fn update_child_constraints(&self,
child_id: ComponentId,
parent_constraints: LayoutConstraints) -> LayoutConstraints {
if let Some(weight) = self.children.get(&child_id) {
let total_weight: f32 = self.children.values().sum();
let child_count = self.children.len() as f32;
let available_height = parent_constraints.max_height - (self.padding * 2.0) -
(self.spacing * (child_count - 1.0)).max(0.0);
let child_height = if total_weight > 0.0 {
(available_height * weight / total_weight).max(0.0)
} else {
0.0
};
LayoutConstraints {
min_width: 0.0,
max_width: parent_constraints.max_width - (self.padding * 2.0),
min_height: child_height,
max_height: child_height,
}
} else {
parent_constraints
}
}
}
pub struct GridLayout {
rows: u32,
cols: u32,
cell_width: f32,
cell_height: f32,
spacing: f32,
padding: f32,
cell_span: HashMap<ComponentId, (u32, u32, u32, u32)>, }
impl GridLayout {
pub fn new(rows: u32, cols: u32, cell_width: f32, cell_height: f32, spacing: f32, padding: f32) -> Self {
Self {
rows,
cols,
cell_width,
cell_height,
spacing,
padding,
cell_span: HashMap::new(),
}
}
pub fn set_cell_span(&mut self, child_id: ComponentId, row: u32, col: u32, row_span: u32, col_span: u32) {
if row < self.rows && col < self.cols {
self.cell_span.insert(child_id, (row, col, row_span.max(1), col_span.max(1)));
}
}
}
impl LayoutStrategy for GridLayout {
fn calculate_layout(&self, constraints: LayoutConstraints) -> LayoutResult {
let total_width = (self.cell_width * self.cols as f32) +
(self.spacing * (self.cols - 1) as f32) +
(self.padding * 2.0);
let total_height = (self.cell_height * self.rows as f32) +
(self.spacing * (self.rows - 1) as f32) +
(self.padding * 2.0);
LayoutResult {
x: 0.0,
y: 0.0,
width: total_width.min(constraints.max_width),
height: total_height.min(constraints.max_height),
}
}
fn add_child(&mut self, child_id: ComponentId, weight: f32) {
let index = self.cell_span.len();
let row = (index as u32) / self.cols;
let col = (index as u32) % self.cols;
if row < self.rows {
self.set_cell_span(child_id, row, col, 1, 1);
}
}
fn remove_child(&mut self, child_id: ComponentId) {
self.cell_span.remove(&child_id);
}
fn update_child_constraints(&self,
child_id: ComponentId,
parent_constraints: LayoutConstraints) -> LayoutConstraints {
if let Some((row, col, row_span, col_span)) = self.cell_span.get(&child_id) {
let cell_width = self.cell_width;
let cell_height = self.cell_height;
let width = (cell_width * *col_span as f32) +
(self.spacing * (*col_span - 1) as f32);
let height = (cell_height * *row_span as f32) +
(self.spacing * (*row_span - 1) as f32);
LayoutConstraints {
min_width: width,
max_width: width,
min_height: height,
max_height: height,
}
} else {
parent_constraints
}
}
}