package com.revolsys.swing.layout; import java.awt.Component; import java.awt.Container; import java.awt.LayoutManager; import java.awt.MenuContainer; import java.awt.MenuItem; import java.awt.Window; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; import javax.swing.Spring; import javax.swing.SpringLayout; import javax.swing.SpringLayout.Constraints; import javax.swing.SwingUtilities; public class SpringLayoutUtil { /* Used by makeCompactGrid. */ private static SpringLayout.Constraints getConstraintsForCell(final int row, final int col, final Container parent, final int cols) { final SpringLayout layout = (SpringLayout)parent.getLayout(); final Component c = parent.getComponent(row * cols + col); return layout.getConstraints(c); } public static Window getWindow(final Object source) { if (source instanceof JMenuItem) { final JMenuItem menuItem = (JMenuItem)source; MenuContainer menuContainer = menuItem.getParent(); while (menuContainer != null && !(menuContainer instanceof JPopupMenu)) { if (menuContainer instanceof MenuItem) { menuContainer = ((MenuItem)menuContainer).getParent(); } else { menuContainer = null; } } if (menuContainer != null) { final JPopupMenu menu = (JPopupMenu)menuContainer; final Component invoker = menu.getInvoker(); return SwingUtilities.getWindowAncestor(invoker); } } else if (source instanceof Component) { return SwingUtilities.getWindowAncestor((Component)source); } return null; } public static void makeColumns(final Container container, final int numColumns, final int initialX, final int initialY, final int xPad, final int yPad) { final Spring xPadSpring = Spring.constant(xPad); final Spring yPadSpring = Spring.constant(yPad); LayoutManager layout = container.getLayout(); if (!(layout instanceof SpringLayout)) { layout = new SpringLayout(); container.setLayout(layout); } final SpringLayout springLayout = (SpringLayout)layout; final Component[] components = container.getComponents(); if (components.length > 0) { final Spring[] columnWidths = new Spring[numColumns]; for (int i = 0; i < columnWidths.length; i++) { columnWidths[i] = Spring.constant(0); } final int numRows = (int)Math.ceil((double)components.length / numColumns); final Spring[] rowHeights = new Spring[numRows]; for (int i = 0; i < rowHeights.length; i++) { rowHeights[i] = Spring.constant(0); } for (int i = 0; i < components.length; i++) { final Component component = components[i]; final Constraints componentConstraints = springLayout.getConstraints(component); final Spring width = componentConstraints.getWidth(); final Spring height = componentConstraints.getHeight(); final int column = i % numColumns; final int row = (int)Math.floor((double)i / numColumns); columnWidths[column] = Spring.max(columnWidths[column], width); rowHeights[row] = Spring.max(rowHeights[row], height); } final Spring[] columnX = new Spring[numColumns]; final Spring initialXSpring = Spring.constant(initialX); columnX[0] = initialXSpring; for (int i = 1; i < columnX.length; i++) { columnX[i] = Spring.sum(columnX[i - 1], Spring.sum(xPadSpring, columnWidths[i - 1])); } final Spring[] rowY = new Spring[numRows]; final Spring initialYSpring = Spring.constant(initialY); rowY[0] = initialYSpring; for (int i = 1; i < rowY.length; i++) { rowY[i] = Spring.sum(rowY[i - 1], Spring.sum(yPadSpring, rowHeights[i - 1])); } final Constraints containerConstraints = springLayout.getConstraints(container); containerConstraints.setWidth(Spring.sum(columnX[numColumns - 1], Spring.sum(columnWidths[numColumns - 1], initialXSpring))); containerConstraints.setHeight( Spring.sum(rowY[numRows - 1], Spring.sum(rowHeights[numRows - 1], initialYSpring))); for (int i = 0; i < components.length; i++) { final Component component = components[i]; final Constraints componentConstraints = springLayout.getConstraints(component); final int column = i % numColumns; final int row = (int)Math.floor((double)i / numColumns); componentConstraints.setX(columnX[column]); componentConstraints.setWidth(Spring.width(component)); componentConstraints.setY(rowY[row]); componentConstraints.setHeight(Spring.height(component)); } } } /** * Aligns the first <code>rows</code> <code>cols</code> components of * <code>parent</code> in a grid. Each component in a column is as wide as the * maximum preferred width of the components in that column; height is * similarly determined for each row. The parent is made just big enough to * fit them all. * * @param rows number of rows * @param cols number of columns * @param initialX x location to start the grid at * @param initialY y location to start the grid at * @param xPad x padding between cells * @param yPad y padding between cells */ public static void makeCompactGrid(final Container parent, final int rows, final int cols, final int initialX, final int initialY, final int xPad, final int yPad) { SpringLayout layout; try { layout = (SpringLayout)parent.getLayout(); } catch (final ClassCastException exc) { layout = new SpringLayout(); parent.setLayout(layout); } // Align all cells in each column and make them the same width. Spring x = Spring.constant(initialX); for (int c = 0; c < cols; c++) { Spring width = Spring.constant(0); for (int r = 0; r < rows; r++) { width = Spring.max(width, getConstraintsForCell(r, c, parent, cols).getWidth()); } for (int r = 0; r < rows; r++) { final SpringLayout.Constraints constraints = getConstraintsForCell(r, c, parent, cols); constraints.setX(x); constraints.setWidth(width); } x = Spring.sum(x, Spring.sum(width, Spring.constant(xPad))); } // Align all cells in each row and make them the same height. Spring y = Spring.constant(initialY); for (int r = 0; r < rows; r++) { Spring height = Spring.constant(0); for (int c = 0; c < cols; c++) { height = Spring.max(height, getConstraintsForCell(r, c, parent, cols).getHeight()); } for (int c = 0; c < cols; c++) { final SpringLayout.Constraints constraints = getConstraintsForCell(r, c, parent, cols); constraints.setY(y); constraints.setHeight(height); } y = Spring.sum(y, Spring.sum(height, Spring.constant(yPad))); } // Set the parent's size. final SpringLayout.Constraints parenConstraints = layout.getConstraints(parent); parenConstraints.setConstraint(SpringLayout.SOUTH, y); parenConstraints.setConstraint(SpringLayout.EAST, x); } /** * Aligns the first <code>rows</code> <code>cols</code> components of * <code>parent</code> in a grid. Each component is as big as the maximum * preferred width and height of the components. The parent is made just big * enough to fit them all. * * @param rows number of rows * @param cols number of columns * @param initialX x location to start the grid at * @param initialY y location to start the grid at * @param xPad x padding between cells * @param yPad y padding between cells */ public static void makeGrid(final Container parent, final int rows, final int cols, final int initialX, final int initialY, final int xPad, final int yPad) { LayoutManager layout = parent.getLayout(); if (!(layout instanceof SpringLayout)) { layout = new SpringLayout(); parent.setLayout(layout); } final SpringLayout springLayout = (SpringLayout)parent.getLayout(); final Spring xPadSpring = Spring.constant(xPad); final Spring yPadSpring = Spring.constant(yPad); final Spring initialXSpring = Spring.constant(initialX); final Spring initialYSpring = Spring.constant(initialY); final int max = rows * cols; // Calculate Springs that are the max of the width/height so that all // cells have the same size. Spring maxWidthSpring = springLayout.getConstraints(parent.getComponent(0)).getWidth(); Spring maxHeightSpring = springLayout.getConstraints(parent.getComponent(0)).getWidth(); for (int i = 1; i < max; i++) { final SpringLayout.Constraints cons = springLayout.getConstraints(parent.getComponent(i)); maxWidthSpring = Spring.max(maxWidthSpring, cons.getWidth()); maxHeightSpring = Spring.max(maxHeightSpring, cons.getHeight()); } // Apply the new width/height Spring. This forces all the // components to have the same size. for (int i = 0; i < max; i++) { final SpringLayout.Constraints cons = springLayout.getConstraints(parent.getComponent(i)); cons.setWidth(maxWidthSpring); cons.setHeight(maxHeightSpring); } // Then adjust the x/y constraints of all the cells so that they // are aligned in a grid. SpringLayout.Constraints lastCons = null; SpringLayout.Constraints lastRowCons = null; for (int i = 0; i < max; i++) { final SpringLayout.Constraints cons = springLayout.getConstraints(parent.getComponent(i)); if (i % cols == 0) { // start of new row lastRowCons = lastCons; cons.setX(initialXSpring); } else { // x position depends on previous component cons.setX(Spring.sum(lastCons.getConstraint(SpringLayout.EAST), xPadSpring)); } if (i / cols == 0) { // first row cons.setY(initialYSpring); } else { // y position depends on previous row cons.setY(Spring.sum(lastRowCons.getConstraint(SpringLayout.SOUTH), yPadSpring)); } lastCons = cons; } // Set the parent's size. final SpringLayout.Constraints pCons = springLayout.getConstraints(parent); pCons.setConstraint(SpringLayout.SOUTH, Spring.sum(Spring.constant(yPad), lastCons.getConstraint(SpringLayout.SOUTH))); pCons.setConstraint(SpringLayout.EAST, Spring.sum(Spring.constant(xPad), lastCons.getConstraint(SpringLayout.EAST))); } public static void makeRows(final Container container, final int initialX, final int initialY, final int xPad, final int yPad, final int... componentsPerRow) { final SpringLayout layout = (SpringLayout)container.getLayout(); final Spring xPadSpring = Spring.constant(xPad); final Spring yPadSpring = Spring.constant(yPad); final Spring initialXSpring = Spring.constant(initialX); final Spring initialYSpring = Spring.constant(initialY); int i = 0; Spring width = null; final int componentCount = container.getComponentCount(); Spring y = initialYSpring; for (int row = 0; row < componentsPerRow.length && i < componentCount; row++) { final int numComponents = componentsPerRow[row]; Spring rowHeight = Spring.constant(0); if (row > 0) { y = Spring.sum(y, yPadSpring); } Spring x = initialXSpring; for (int col = 0; col < numComponents && i < componentCount; col++) { final Component component = container.getComponent(i); if (col > 0) { x = Spring.sum(x, xPadSpring); } final Constraints componentConstraints = layout.getConstraints(component); componentConstraints.setX(x); componentConstraints.setWidth(Spring.width(component)); componentConstraints.setY(y); componentConstraints.setHeight(Spring.height(component)); x = Spring.sum(x, Spring.width(component)); rowHeight = Spring.max(rowHeight, Spring.height(component)); i++; } y = Spring.sum(y, rowHeight); if (width == null) { width = x; } else { width = Spring.max(width, x); } } final Constraints containerConstraints = layout.getConstraints(container); containerConstraints.setWidth(Spring.sum(initialXSpring, width)); containerConstraints.setHeight(Spring.sum(initialYSpring, y)); } public static void singleColumn(final Container container, final int initialY, final int yPad) { Spring height = Spring.constant(initialY + yPad * container.getComponentCount()); Spring width = Spring.constant(0); final SpringLayout layout = (SpringLayout)container.getLayout(); Component previous = container; for (final Component component : container.getComponents()) { final Constraints constraints = layout.getConstraints(component); width = Spring.max(width, constraints.getWidth()); height = Spring.sum(height, constraints.getHeight()); if (previous == container) { layout.putConstraint(SpringLayout.NORTH, previous, initialY, SpringLayout.NORTH, component); } else { layout.putConstraint(SpringLayout.SOUTH, previous, yPad, SpringLayout.NORTH, component); } previous = component; } final Constraints containerConstraints = layout.getConstraints(container); containerConstraints.setConstraint(SpringLayout.SOUTH, height); containerConstraints.setConstraint(SpringLayout.EAST, width); } }