/** 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 // flag indicating if we're going to draw grid lines var drawGrid = true /** 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] } /** Sets the flagi if we're going to draw boxes around each cell. */ drawBoxes[flag] := { drawGrid = flag } /** Lay out the grid (with equal-sized rectangles) and return a graphics object. */ layout[] := { g = new graphics verts = new OrderedList horiz = new OrderedList //g.color[0,0,0] CELL: for i = rangeOf[garray] { g1 = garray@i if g1 == undef next CELL [cx, cy, width, height, left, right, top, bottom] = getCenter[i] verts.insertUnique[left] verts.insertUnique[right] horiz.insertUnique[top] horiz.insertUnique[bottom] if g1 != undef { //g.save[] // save and restore are already done by addCenter g.addCenter[g1, cx, cy, width, height] //g.restore[] } } if drawGrid { // Draw borders // Draw vertical lines g.color[0,0,0,.5] minx = first[verts] maxx = last[verts] miny = first[horiz] maxy = last[horiz] for x = verts g.line[x, miny, x, maxy] for y = horiz g.line[minx, y, maxx, y] } 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, left, right, top, bottom] */ 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, col-1/2, col+1/2, row-1/2, row+1/2] } }