|
@@ -1,6 +1,9 @@
|
|
|
use super::{do_fit, ArrangementCalculator};
|
|
|
use crate::{
|
|
|
- layout::{cache::NodeState, LayoutNodeAccess, SizePolicy},
|
|
|
+ layout::{
|
|
|
+ cache::{LayoutCacheKey, NodeState},
|
|
|
+ LayoutNodeAccess, SizePolicy, TableCell, TableSize,
|
|
|
+ },
|
|
|
math::{PixelBox, PixelPoint, PixelSize},
|
|
|
};
|
|
|
use std::ops::Add;
|
|
@@ -8,30 +11,105 @@ use std::ops::Add;
|
|
|
#[derive(Clone, Debug)]
|
|
|
pub struct TableArrangement;
|
|
|
|
|
|
+#[derive(Default)]
|
|
|
+struct TableState {
|
|
|
+ row_policies: Vec<SizePolicy>,
|
|
|
+ col_policies: Vec<SizePolicy>,
|
|
|
+}
|
|
|
+
|
|
|
impl TableArrangement {
|
|
|
- fn max_coord(&self, node: &LayoutNodeAccess) -> Option<(usize, usize)> {
|
|
|
- let Some(tc) = &node.table_cells else {
|
|
|
- return None;
|
|
|
+ fn table_size(&self, node: &LayoutNodeAccess) -> Option<TableSize> {
|
|
|
+ let mut max_point = Some(TableCell::zero());
|
|
|
+ for ch in node.child_iter() {
|
|
|
+ if let Some(cell) = ch.table_cell() {
|
|
|
+ let mp = max_point.unwrap_or_default();
|
|
|
+ max_point = Some(TableCell::new(mp.x.max(cell.x), mp.y.max(cell.y)));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ max_point.and_then(|p| Some(TableSize::new(p.x + 1, p.y + 1)))
|
|
|
+ }
|
|
|
+
|
|
|
+ fn build_table_state(&self, node: &LayoutNodeAccess) -> TableState {
|
|
|
+ let mut tstate = TableState {
|
|
|
+ row_policies: vec![],
|
|
|
+ col_policies: vec![],
|
|
|
};
|
|
|
- let mut max_row = None;
|
|
|
- let mut max_col = None;
|
|
|
- for cell in tc.iter() {
|
|
|
- max_col = max_col.max(Some(cell.0 .0));
|
|
|
- max_row = max_row.max(Some(cell.0 .1));
|
|
|
+
|
|
|
+ // pull row/column information from child node properties
|
|
|
+ for ch in node.child_iter() {
|
|
|
+ let Some(cell) = ch.table_cell() else {
|
|
|
+ continue;
|
|
|
+ };
|
|
|
+
|
|
|
+ if cell.x >= tstate.col_policies.len() {
|
|
|
+ tstate
|
|
|
+ .col_policies
|
|
|
+ .resize(cell.x + 1, SizePolicy::default());
|
|
|
+ }
|
|
|
+ if cell.y >= tstate.row_policies.len() {
|
|
|
+ tstate
|
|
|
+ .row_policies
|
|
|
+ .resize(cell.y + 1, SizePolicy::default());
|
|
|
+ }
|
|
|
+
|
|
|
+ let child_policy = node
|
|
|
+ .cache
|
|
|
+ .with_state(ch.cache_key, |v| v.net_policy)
|
|
|
+ .unwrap();
|
|
|
+ tstate.col_policies[cell.x] = tstate.col_policies[cell.x].max(child_policy.0);
|
|
|
+ tstate.row_policies[cell.y] = tstate.row_policies[cell.y].max(child_policy.1);
|
|
|
}
|
|
|
- max_row.zip(max_col)
|
|
|
+
|
|
|
+ tstate
|
|
|
}
|
|
|
}
|
|
|
|
|
|
impl ArrangementCalculator for TableArrangement {
|
|
|
- fn arrange_step(
|
|
|
- &self,
|
|
|
- node: LayoutNodeAccess,
|
|
|
- child_policies: Vec<(SizePolicy, SizePolicy)>,
|
|
|
- ) -> (SizePolicy, SizePolicy) {
|
|
|
- // pull row/column information from child node properties
|
|
|
- todo!()
|
|
|
+ fn arrange_step(&self, node: LayoutNodeAccess) -> (SizePolicy, SizePolicy) {
|
|
|
+ let tstate = self.build_table_state(&node);
|
|
|
+
|
|
|
+ // if there are no table cells...
|
|
|
+ if tstate.row_policies.len() == 0 || tstate.col_policies.len() == 0 {
|
|
|
+ println!("returning early");
|
|
|
+ return (node.width_policy(), node.height_policy());
|
|
|
+ }
|
|
|
+
|
|
|
+ let net_rows = tstate
|
|
|
+ .row_policies
|
|
|
+ .into_iter()
|
|
|
+ .reduce(SizePolicy::add)
|
|
|
+ .unwrap();
|
|
|
+ let net_cols = tstate
|
|
|
+ .col_policies
|
|
|
+ .into_iter()
|
|
|
+ .reduce(SizePolicy::add)
|
|
|
+ .unwrap();
|
|
|
+
|
|
|
+ (
|
|
|
+ node.width_policy.max_preserve_slack(net_cols),
|
|
|
+ node.height_policy.max_preserve_slack(net_rows),
|
|
|
+ )
|
|
|
}
|
|
|
|
|
|
- fn layout_step(&self, node: LayoutNodeAccess, inside: PixelBox) {}
|
|
|
+ fn layout_step(&self, node: LayoutNodeAccess, inside: PixelBox) {
|
|
|
+ let tstate = self.build_table_state(&node);
|
|
|
+
|
|
|
+ let mut col_offsets = vec![0];
|
|
|
+ col_offsets.extend(do_fit(inside.width(), tstate.col_policies.into_iter()));
|
|
|
+ let mut row_offsets = vec![0];
|
|
|
+ row_offsets.extend(do_fit(inside.height(), tstate.row_policies.into_iter()));
|
|
|
+
|
|
|
+ for ch in node.child_iter() {
|
|
|
+ let Some(cell) = ch.table_cell() else {
|
|
|
+ continue;
|
|
|
+ };
|
|
|
+
|
|
|
+ let cbox = PixelBox::new(
|
|
|
+ PixelPoint::new(col_offsets[cell.x], row_offsets[cell.y]),
|
|
|
+ PixelPoint::new(col_offsets[cell.x + 1], row_offsets[cell.y + 1]),
|
|
|
+ );
|
|
|
+
|
|
|
+ ch.child_arrangement.layout_step(ch, cbox);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|