/** This is a class for laying out graphics objects in a grid. See GraphicsGridTest.frink for examples of its use. */ class GraphicsGrid { // Array of graphics objects var garray = new array // Desired number of colums or undef. var cols = undef // Insets for each graphic object from 0 to 1 var insets = 0.95 /** Construct a GraphicsGrid with arbitrary number of columns. The number of columns is chosen perhaps from the square root of the number of items. */ new[] := { } /** Construct a GraphicsGrid with a desired maximum number of columns. */ new[cols] := { this.cols = cols } /** Add a graphics object to the grid. */ add[g1] := { // TODO: Test for GraphicsExpression and turn other expression types // into graphics garray.push[g1] } /** Lay out the grid and return a graphics object. */ layout[] := { g = new graphics //g.color[0,0,0] CELL: for i = rangeOf[garray] { g1 = garray@i if g1 == undef next CELL [cx, cy, width, height] = getCenter[i] if g1 != undef { //g.save[] // save and restore are already done by addCenter g.addCenter[g1, cx, cy, width, height] //g.restore[] } } return g } /** Sets the inset size of each box from 0 to 1. If insets is 0.95, each grid box will take up 95% of width and height. If insets is 1, each grid box will take up 100% of width and height. */ setInsets[n] := { insets = n } /** Private method to return the center coordinates and size for the specified index. Returns [cx, cy, width, height] */ getCenter[index] := { wcols = cols // Working columns value if wcols == undef // Try to make approximately square if undefined wcols = ceil[sqrt[length[garray]]] // This is laying out left-to-right with specified number of columns row = index div wcols col = index mod wcols return [col, row, 1 insets, 1 insets] } }