// vega-view-transforms `gridLayout`: arrange groups in rows and columns.
///|
priv struct GridOpt {
/// "each" | "all" | "" for columns / rows
align_col : String
align_row : String
pad_col : Double
pad_row : Double
/// number of columns (0 means one per group)
columns : Int32
center_col : Bool
center_row : Bool
/// measure groups by their size (`bounds: flush`) instead of their bounds
flush : Bool
anchor_x : Double
anchor_y : Double
/// "start" | "middle" | "end" for the grid anchor
anchor_col : String
anchor_row : String
}
///|
fn bbox_of(item : @scene.Item, flush : Bool) -> @scene.Bounds {
if flush {
let b = @scene.Bounds::new()
ignore(b.set(0.0, 0.0, item.num0("width"), item.num0("height")))
b
} else {
let b = item.bounds.copy()
if b.is_empty() {
ignore(b.set(0.0, 0.0, 0.0, 0.0))
} else {
ignore(b.translate(-item.num0("x"), -item.num0("y")))
}
b
}
}
///|
fn offset_value(v : Double) -> Double {
if v < 0.0 {
ceil(-v)
} else {
0.0
}
}
///|
/// Lay out `groups` (whose containing marks are `marks`), returning the
/// bounds of the resulting grid.
fn grid_layout(
groups : Array[@scene.Item],
marks : Array[@scene.Mark],
o : GridOpt,
) -> @scene.Bounds {
let n = groups.length()
let ncols = if o.columns > 0 { o.columns } else { n }
let nrows = if ncols <= 0 { 1 } else { (n + ncols - 1) / ncols }
let x_offset : Array[Double] = Array::make(n, 0.0)
let y_offset : Array[Double] = Array::make(n, 0.0)
let x_extent : Array[Double] = Array::make(ncols, 0.0)
let y_extent : Array[Double] = Array::make(nrows, 0.0)
let dx : Array[Double] = Array::make(n, 0.0)
let dy : Array[Double] = Array::make(n, 0.0)
let boxes : Array[@scene.Bounds] = []
let mut x_max = 0.0
let mut y_max = 0.0
for i in 0.. 1 {
for i in 0.. 0.0 {
dx[i] = dx[i] + v / 2.0
}
}
}
if align_row != "" && o.center_row && ncols != 1 {
for i in 0.. 0.0 {
dy[i] = dy[i] + v / 2.0
}
}
}
// anchor
let bounds = @scene.Bounds::new()
ignore(bounds.set(0.0, 0.0, 0.0, 0.0))
for i in 0.. ax = ax - bounds.width()
"middle" => ax = ax - bounds.width() / 2.0
_ => ()
}
match o.anchor_row {
"end" => ay = ay - bounds.height()
"middle" => ay = ay - bounds.height() / 2.0
_ => ()
}
ax = round(ax)
ay = round(ay)
// apply
ignore(bounds.clear())
for i in 0..