use crate::internal::InternalLower;
use crate::lowering::{InternalIrBuilder, InternalLoweringCx};
use crate::ui::Widget;
use fission_ir::{
op::{GridPlacement, GridTrack, LayoutOp, Op},
WidgetId,
};
use serde::{Deserialize, Serialize};
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct Grid {
pub id: Option<WidgetId>,
pub children: Vec<Widget>,
pub columns: Vec<GridTrack>,
pub rows: Vec<GridTrack>,
pub column_gap: Option<f32>,
pub row_gap: Option<f32>,
pub padding: [f32; 4],
}
impl Grid {}
impl InternalLower for Grid {
fn lower(&self, cx: &mut InternalLoweringCx) -> WidgetId {
let id = self.id.map(Into::into).unwrap_or_else(|| cx.next_node_id());
cx.push_scope(id);
let mut builder = InternalIrBuilder::new(
id,
Op::Layout(LayoutOp::Grid {
columns: self.columns.clone(),
rows: self.rows.clone(),
column_gap: self.column_gap,
row_gap: self.row_gap,
padding: self.padding,
}),
);
for child in &self.children {
builder.add_child(child.lower(cx));
}
cx.pop_scope();
builder.build(cx)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GridItem {
pub id: Option<WidgetId>,
pub child: Widget,
pub row_start: GridPlacement,
pub row_end: GridPlacement,
pub col_start: GridPlacement,
pub col_end: GridPlacement,
}
impl Default for GridItem {
fn default() -> Self {
Self {
id: None,
child: crate::ui::Row::default().into(),
row_start: GridPlacement::Auto,
row_end: GridPlacement::Auto,
col_start: GridPlacement::Auto,
col_end: GridPlacement::Auto,
}
}
}
impl GridItem {
pub fn new(child: impl Into<Widget>) -> Self {
Self {
child: child.into(),
..Default::default()
}
}
pub fn cell(mut self, row: i16, col: i16) -> Self {
self.row_start = GridPlacement::Line(row);
self.col_start = GridPlacement::Line(col);
self
}
pub fn span(mut self, row_span: u16, col_span: u16) -> Self {
self.row_end = GridPlacement::Span(row_span);
self.col_end = GridPlacement::Span(col_span);
self
}
}
impl InternalLower for GridItem {
fn lower(&self, cx: &mut InternalLoweringCx) -> WidgetId {
let id = self.id.map(Into::into).unwrap_or_else(|| cx.next_node_id());
cx.push_scope(id);
let child_id = self.child.lower(cx);
cx.pop_scope();
let mut builder = InternalIrBuilder::new(
id,
Op::Layout(LayoutOp::GridItem {
row_start: self.row_start,
row_end: self.row_end,
col_start: self.col_start,
col_end: self.col_end,
}),
);
builder.add_child(child_id);
builder.build(cx)
}
}