use super::types::{GridAlign, GridItem, TrackSize};
use crate::layout::Rect;
use crate::widget::traits::{View, WidgetProps};
use crate::{impl_props_builders, impl_styled_view};
pub struct Grid {
pub items: Vec<GridItem>,
pub columns: Vec<TrackSize>,
pub rows: Vec<TrackSize>,
pub col_gap: u16,
pub row_gap: u16,
pub justify_items: GridAlign,
pub align_items: GridAlign,
pub auto_flow_row: bool,
pub auto_cols: TrackSize,
pub auto_rows: TrackSize,
pub min_width: u16,
pub min_height: u16,
pub max_width: u16,
pub max_height: u16,
pub props: WidgetProps,
}
impl Grid {
pub fn new() -> Self {
Self {
items: Vec::new(),
columns: Vec::new(),
rows: Vec::new(),
col_gap: 0,
row_gap: 0,
justify_items: GridAlign::Stretch,
align_items: GridAlign::Stretch,
auto_flow_row: true,
auto_cols: TrackSize::Fr(1.0),
auto_rows: TrackSize::Fr(1.0),
min_width: 0,
min_height: 0,
max_width: 0,
max_height: 0,
props: WidgetProps::new(),
}
}
pub fn columns(mut self, cols: Vec<TrackSize>) -> Self {
self.columns = cols;
self
}
pub fn rows(mut self, rows: Vec<TrackSize>) -> Self {
self.rows = rows;
self
}
pub fn cols(mut self, count: usize) -> Self {
self.columns = vec![TrackSize::Fr(1.0); count];
self
}
pub fn rows_count(mut self, count: usize) -> Self {
self.rows = vec![TrackSize::Fr(1.0); count];
self
}
pub fn col_gap(mut self, gap: u16) -> Self {
self.col_gap = gap;
self
}
pub fn row_gap(mut self, gap: u16) -> Self {
self.row_gap = gap;
self
}
pub fn gap(mut self, gap: u16) -> Self {
self.col_gap = gap;
self.row_gap = gap;
self
}
pub fn justify_items(mut self, align: GridAlign) -> Self {
self.justify_items = align;
self
}
pub fn align_items(mut self, align: GridAlign) -> Self {
self.align_items = align;
self
}
pub fn auto_flow_row(mut self) -> Self {
self.auto_flow_row = true;
self
}
pub fn auto_flow_col(mut self) -> Self {
self.auto_flow_row = false;
self
}
pub fn auto_cols(mut self, size: TrackSize) -> Self {
self.auto_cols = size;
self
}
pub fn auto_rows(mut self, size: TrackSize) -> Self {
self.auto_rows = size;
self
}
pub fn item(mut self, item: GridItem) -> Self {
self.items.push(item);
self
}
pub fn child(mut self, widget: impl View + 'static) -> Self {
self.items.push(GridItem::new(widget));
self
}
pub fn children(mut self, widgets: Vec<Box<dyn View>>) -> Self {
for widget in widgets {
self.items.push(GridItem {
widget,
placement: Default::default(),
});
}
self
}
pub fn min_width(mut self, width: u16) -> Self {
self.min_width = width;
self
}
pub fn min_height(mut self, height: u16) -> Self {
self.min_height = height;
self
}
pub fn max_width(mut self, width: u16) -> Self {
self.max_width = width;
self
}
pub fn max_height(mut self, height: u16) -> Self {
self.max_height = height;
self
}
pub fn min_size(self, width: u16, height: u16) -> Self {
self.min_width(width).min_height(height)
}
pub fn max_size(self, width: u16, height: u16) -> Self {
self.max_width(width).max_height(height)
}
pub fn constrain(self, min_w: u16, min_h: u16, max_w: u16, max_h: u16) -> Self {
self.min_width(min_w)
.min_height(min_h)
.max_width(max_w)
.max_height(max_h)
}
pub fn apply_constraints(&self, area: Rect) -> Rect {
let eff_max_w = if self.max_width > 0 {
self.max_width.max(self.min_width)
} else {
u16::MAX
};
let eff_max_h = if self.max_height > 0 {
self.max_height.max(self.min_height)
} else {
u16::MAX
};
let width = area.width.clamp(self.min_width, eff_max_w);
let height = area.height.clamp(self.min_height, eff_max_h);
Rect::new(area.x, area.y, width, height)
}
}
impl Default for Grid {
fn default() -> Self {
Self::new()
}
}
impl_styled_view!(Grid);
impl_props_builders!(Grid);