1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
use cassowary::strength::*; use cassowary::WeightedRelation::*; use super::{LayoutVars, Layout, Constraint, LayoutContainer}; use super::constraint::*; #[derive(Debug, Clone)] pub struct GridLayout { num_columns: usize, column: usize, rows: Vec<LayoutVars>, columns: Vec<LayoutVars>, row_end: Option<Constraint>, } impl GridLayout { pub fn new(parent: &mut Layout, num_columns: usize) -> Self { assert!(num_columns > 0, "can't create grid layout with no columns"); let mut columns = Vec::new(); for col in 0..num_columns { let column = LayoutVars::new(); let mut constraints = vec![ column.top | EQ(REQUIRED) | parent.vars.top, column.bottom | EQ(REQUIRED) | parent.vars.bottom, column.right - column.left | EQ(REQUIRED) | column.width, column.bottom - column.top | EQ(REQUIRED) | column.height, ]; if let Some(last_column) = columns.last() { let last_column: &LayoutVars = last_column; constraints.push(column.left | EQ(REQUIRED) | last_column.right); constraints.push(column.width | EQ(REQUIRED) | last_column.width); } else { constraints.push(column.left | EQ(REQUIRED) | parent.vars.left); } if col == num_columns - 1 { constraints.push(column.right | EQ(REQUIRED) | parent.vars.right); } parent.add(constraints); parent.add_associated_vars(&column, &format!("column_{}", col)); columns.push(column); } GridLayout { num_columns: num_columns, column: 0, rows: Vec::new(), columns: columns, row_end: None, } } } impl LayoutContainer for GridLayout { fn add_child(&mut self, parent: &mut Layout, child: &mut Layout) { if self.column == self.num_columns || self.rows.len() == 0 { let row = LayoutVars::new(); let mut constraints = vec![ row.left | EQ(REQUIRED) | parent.vars.left, row.right | EQ(REQUIRED) | parent.vars.right, row.right - row.left | EQ(REQUIRED) | row.width, row.bottom - row.top | EQ(REQUIRED) | row.height, ]; if let Some(last_row) = self.rows.last() { constraints.push(row.top | EQ(REQUIRED) | last_row.bottom); constraints.push(row.height | EQ(REQUIRED) | last_row.height); } else { constraints.push(row.top | EQ(REQUIRED) | parent.vars.top); } if let Some(row_end) = self.row_end.take() { parent.remove_constraint(row_end); } let row_end = row.bottom | EQ(REQUIRED) | parent.vars.bottom; self.row_end = Some(row_end.clone()); constraints.push(row_end); parent.add(constraints); parent.add_associated_vars(&row, &format!("row_{}", self.rows.len())); self.rows.push(row); self.column = 0; } let (row, col) = (self.rows.last().unwrap(), self.columns.get(self.column).unwrap()); child.add(constraints![ bound_by(row), bound_by(col), match_layout(&parent).strength(STRONG), ]); self.column += 1; } }