/revolsys-swing/src/main/java/com/revolsys/swing/layout/SpringLayoutUtil.java

https://github.com/revolsys/com.revolsys.open · Java · 320 lines · 252 code · 30 blank · 38 comment · 47 complexity · 352f3265f073c365016eaa375b162d95 MD5 · raw file

  1. package com.revolsys.swing.layout;
  2. import java.awt.Component;
  3. import java.awt.Container;
  4. import java.awt.LayoutManager;
  5. import java.awt.MenuContainer;
  6. import java.awt.MenuItem;
  7. import java.awt.Window;
  8. import javax.swing.JMenuItem;
  9. import javax.swing.JPopupMenu;
  10. import javax.swing.Spring;
  11. import javax.swing.SpringLayout;
  12. import javax.swing.SpringLayout.Constraints;
  13. import javax.swing.SwingUtilities;
  14. public class SpringLayoutUtil {
  15. /* Used by makeCompactGrid. */
  16. private static SpringLayout.Constraints getConstraintsForCell(final int row, final int col,
  17. final Container parent, final int cols) {
  18. final SpringLayout layout = (SpringLayout)parent.getLayout();
  19. final Component c = parent.getComponent(row * cols + col);
  20. return layout.getConstraints(c);
  21. }
  22. public static Window getWindow(final Object source) {
  23. if (source instanceof JMenuItem) {
  24. final JMenuItem menuItem = (JMenuItem)source;
  25. MenuContainer menuContainer = menuItem.getParent();
  26. while (menuContainer != null && !(menuContainer instanceof JPopupMenu)) {
  27. if (menuContainer instanceof MenuItem) {
  28. menuContainer = ((MenuItem)menuContainer).getParent();
  29. } else {
  30. menuContainer = null;
  31. }
  32. }
  33. if (menuContainer != null) {
  34. final JPopupMenu menu = (JPopupMenu)menuContainer;
  35. final Component invoker = menu.getInvoker();
  36. return SwingUtilities.getWindowAncestor(invoker);
  37. }
  38. } else if (source instanceof Component) {
  39. return SwingUtilities.getWindowAncestor((Component)source);
  40. }
  41. return null;
  42. }
  43. public static void makeColumns(final Container container, final int numColumns,
  44. final int initialX, final int initialY, final int xPad, final int yPad) {
  45. final Spring xPadSpring = Spring.constant(xPad);
  46. final Spring yPadSpring = Spring.constant(yPad);
  47. LayoutManager layout = container.getLayout();
  48. if (!(layout instanceof SpringLayout)) {
  49. layout = new SpringLayout();
  50. container.setLayout(layout);
  51. }
  52. final SpringLayout springLayout = (SpringLayout)layout;
  53. final Component[] components = container.getComponents();
  54. if (components.length > 0) {
  55. final Spring[] columnWidths = new Spring[numColumns];
  56. for (int i = 0; i < columnWidths.length; i++) {
  57. columnWidths[i] = Spring.constant(0);
  58. }
  59. final int numRows = (int)Math.ceil((double)components.length / numColumns);
  60. final Spring[] rowHeights = new Spring[numRows];
  61. for (int i = 0; i < rowHeights.length; i++) {
  62. rowHeights[i] = Spring.constant(0);
  63. }
  64. for (int i = 0; i < components.length; i++) {
  65. final Component component = components[i];
  66. final Constraints componentConstraints = springLayout.getConstraints(component);
  67. final Spring width = componentConstraints.getWidth();
  68. final Spring height = componentConstraints.getHeight();
  69. final int column = i % numColumns;
  70. final int row = (int)Math.floor((double)i / numColumns);
  71. columnWidths[column] = Spring.max(columnWidths[column], width);
  72. rowHeights[row] = Spring.max(rowHeights[row], height);
  73. }
  74. final Spring[] columnX = new Spring[numColumns];
  75. final Spring initialXSpring = Spring.constant(initialX);
  76. columnX[0] = initialXSpring;
  77. for (int i = 1; i < columnX.length; i++) {
  78. columnX[i] = Spring.sum(columnX[i - 1], Spring.sum(xPadSpring, columnWidths[i - 1]));
  79. }
  80. final Spring[] rowY = new Spring[numRows];
  81. final Spring initialYSpring = Spring.constant(initialY);
  82. rowY[0] = initialYSpring;
  83. for (int i = 1; i < rowY.length; i++) {
  84. rowY[i] = Spring.sum(rowY[i - 1], Spring.sum(yPadSpring, rowHeights[i - 1]));
  85. }
  86. final Constraints containerConstraints = springLayout.getConstraints(container);
  87. containerConstraints.setWidth(Spring.sum(columnX[numColumns - 1],
  88. Spring.sum(columnWidths[numColumns - 1], initialXSpring)));
  89. containerConstraints.setHeight(
  90. Spring.sum(rowY[numRows - 1], Spring.sum(rowHeights[numRows - 1], initialYSpring)));
  91. for (int i = 0; i < components.length; i++) {
  92. final Component component = components[i];
  93. final Constraints componentConstraints = springLayout.getConstraints(component);
  94. final int column = i % numColumns;
  95. final int row = (int)Math.floor((double)i / numColumns);
  96. componentConstraints.setX(columnX[column]);
  97. componentConstraints.setWidth(Spring.width(component));
  98. componentConstraints.setY(rowY[row]);
  99. componentConstraints.setHeight(Spring.height(component));
  100. }
  101. }
  102. }
  103. /**
  104. * Aligns the first <code>rows</code> <code>cols</code> components of
  105. * <code>parent</code> in a grid. Each component in a column is as wide as the
  106. * maximum preferred width of the components in that column; height is
  107. * similarly determined for each row. The parent is made just big enough to
  108. * fit them all.
  109. *
  110. * @param rows number of rows
  111. * @param cols number of columns
  112. * @param initialX x location to start the grid at
  113. * @param initialY y location to start the grid at
  114. * @param xPad x padding between cells
  115. * @param yPad y padding between cells
  116. */
  117. public static void makeCompactGrid(final Container parent, final int rows, final int cols,
  118. final int initialX, final int initialY, final int xPad, final int yPad) {
  119. SpringLayout layout;
  120. try {
  121. layout = (SpringLayout)parent.getLayout();
  122. } catch (final ClassCastException exc) {
  123. layout = new SpringLayout();
  124. parent.setLayout(layout);
  125. }
  126. // Align all cells in each column and make them the same width.
  127. Spring x = Spring.constant(initialX);
  128. for (int c = 0; c < cols; c++) {
  129. Spring width = Spring.constant(0);
  130. for (int r = 0; r < rows; r++) {
  131. width = Spring.max(width, getConstraintsForCell(r, c, parent, cols).getWidth());
  132. }
  133. for (int r = 0; r < rows; r++) {
  134. final SpringLayout.Constraints constraints = getConstraintsForCell(r, c, parent, cols);
  135. constraints.setX(x);
  136. constraints.setWidth(width);
  137. }
  138. x = Spring.sum(x, Spring.sum(width, Spring.constant(xPad)));
  139. }
  140. // Align all cells in each row and make them the same height.
  141. Spring y = Spring.constant(initialY);
  142. for (int r = 0; r < rows; r++) {
  143. Spring height = Spring.constant(0);
  144. for (int c = 0; c < cols; c++) {
  145. height = Spring.max(height, getConstraintsForCell(r, c, parent, cols).getHeight());
  146. }
  147. for (int c = 0; c < cols; c++) {
  148. final SpringLayout.Constraints constraints = getConstraintsForCell(r, c, parent, cols);
  149. constraints.setY(y);
  150. constraints.setHeight(height);
  151. }
  152. y = Spring.sum(y, Spring.sum(height, Spring.constant(yPad)));
  153. }
  154. // Set the parent's size.
  155. final SpringLayout.Constraints parenConstraints = layout.getConstraints(parent);
  156. parenConstraints.setConstraint(SpringLayout.SOUTH, y);
  157. parenConstraints.setConstraint(SpringLayout.EAST, x);
  158. }
  159. /**
  160. * Aligns the first <code>rows</code> <code>cols</code> components of
  161. * <code>parent</code> in a grid. Each component is as big as the maximum
  162. * preferred width and height of the components. The parent is made just big
  163. * enough to fit them all.
  164. *
  165. * @param rows number of rows
  166. * @param cols number of columns
  167. * @param initialX x location to start the grid at
  168. * @param initialY y location to start the grid at
  169. * @param xPad x padding between cells
  170. * @param yPad y padding between cells
  171. */
  172. public static void makeGrid(final Container parent, final int rows, final int cols,
  173. final int initialX, final int initialY, final int xPad, final int yPad) {
  174. LayoutManager layout = parent.getLayout();
  175. if (!(layout instanceof SpringLayout)) {
  176. layout = new SpringLayout();
  177. parent.setLayout(layout);
  178. }
  179. final SpringLayout springLayout = (SpringLayout)parent.getLayout();
  180. final Spring xPadSpring = Spring.constant(xPad);
  181. final Spring yPadSpring = Spring.constant(yPad);
  182. final Spring initialXSpring = Spring.constant(initialX);
  183. final Spring initialYSpring = Spring.constant(initialY);
  184. final int max = rows * cols;
  185. // Calculate Springs that are the max of the width/height so that all
  186. // cells have the same size.
  187. Spring maxWidthSpring = springLayout.getConstraints(parent.getComponent(0)).getWidth();
  188. Spring maxHeightSpring = springLayout.getConstraints(parent.getComponent(0)).getWidth();
  189. for (int i = 1; i < max; i++) {
  190. final SpringLayout.Constraints cons = springLayout.getConstraints(parent.getComponent(i));
  191. maxWidthSpring = Spring.max(maxWidthSpring, cons.getWidth());
  192. maxHeightSpring = Spring.max(maxHeightSpring, cons.getHeight());
  193. }
  194. // Apply the new width/height Spring. This forces all the
  195. // components to have the same size.
  196. for (int i = 0; i < max; i++) {
  197. final SpringLayout.Constraints cons = springLayout.getConstraints(parent.getComponent(i));
  198. cons.setWidth(maxWidthSpring);
  199. cons.setHeight(maxHeightSpring);
  200. }
  201. // Then adjust the x/y constraints of all the cells so that they
  202. // are aligned in a grid.
  203. SpringLayout.Constraints lastCons = null;
  204. SpringLayout.Constraints lastRowCons = null;
  205. for (int i = 0; i < max; i++) {
  206. final SpringLayout.Constraints cons = springLayout.getConstraints(parent.getComponent(i));
  207. if (i % cols == 0) { // start of new row
  208. lastRowCons = lastCons;
  209. cons.setX(initialXSpring);
  210. } else { // x position depends on previous component
  211. cons.setX(Spring.sum(lastCons.getConstraint(SpringLayout.EAST), xPadSpring));
  212. }
  213. if (i / cols == 0) { // first row
  214. cons.setY(initialYSpring);
  215. } else { // y position depends on previous row
  216. cons.setY(Spring.sum(lastRowCons.getConstraint(SpringLayout.SOUTH), yPadSpring));
  217. }
  218. lastCons = cons;
  219. }
  220. // Set the parent's size.
  221. final SpringLayout.Constraints pCons = springLayout.getConstraints(parent);
  222. pCons.setConstraint(SpringLayout.SOUTH,
  223. Spring.sum(Spring.constant(yPad), lastCons.getConstraint(SpringLayout.SOUTH)));
  224. pCons.setConstraint(SpringLayout.EAST,
  225. Spring.sum(Spring.constant(xPad), lastCons.getConstraint(SpringLayout.EAST)));
  226. }
  227. public static void makeRows(final Container container, final int initialX, final int initialY,
  228. final int xPad, final int yPad, final int... componentsPerRow) {
  229. final SpringLayout layout = (SpringLayout)container.getLayout();
  230. final Spring xPadSpring = Spring.constant(xPad);
  231. final Spring yPadSpring = Spring.constant(yPad);
  232. final Spring initialXSpring = Spring.constant(initialX);
  233. final Spring initialYSpring = Spring.constant(initialY);
  234. int i = 0;
  235. Spring width = null;
  236. final int componentCount = container.getComponentCount();
  237. Spring y = initialYSpring;
  238. for (int row = 0; row < componentsPerRow.length && i < componentCount; row++) {
  239. final int numComponents = componentsPerRow[row];
  240. Spring rowHeight = Spring.constant(0);
  241. if (row > 0) {
  242. y = Spring.sum(y, yPadSpring);
  243. }
  244. Spring x = initialXSpring;
  245. for (int col = 0; col < numComponents && i < componentCount; col++) {
  246. final Component component = container.getComponent(i);
  247. if (col > 0) {
  248. x = Spring.sum(x, xPadSpring);
  249. }
  250. final Constraints componentConstraints = layout.getConstraints(component);
  251. componentConstraints.setX(x);
  252. componentConstraints.setWidth(Spring.width(component));
  253. componentConstraints.setY(y);
  254. componentConstraints.setHeight(Spring.height(component));
  255. x = Spring.sum(x, Spring.width(component));
  256. rowHeight = Spring.max(rowHeight, Spring.height(component));
  257. i++;
  258. }
  259. y = Spring.sum(y, rowHeight);
  260. if (width == null) {
  261. width = x;
  262. } else {
  263. width = Spring.max(width, x);
  264. }
  265. }
  266. final Constraints containerConstraints = layout.getConstraints(container);
  267. containerConstraints.setWidth(Spring.sum(initialXSpring, width));
  268. containerConstraints.setHeight(Spring.sum(initialYSpring, y));
  269. }
  270. public static void singleColumn(final Container container, final int initialY, final int yPad) {
  271. Spring height = Spring.constant(initialY + yPad * container.getComponentCount());
  272. Spring width = Spring.constant(0);
  273. final SpringLayout layout = (SpringLayout)container.getLayout();
  274. Component previous = container;
  275. for (final Component component : container.getComponents()) {
  276. final Constraints constraints = layout.getConstraints(component);
  277. width = Spring.max(width, constraints.getWidth());
  278. height = Spring.sum(height, constraints.getHeight());
  279. if (previous == container) {
  280. layout.putConstraint(SpringLayout.NORTH, previous, initialY, SpringLayout.NORTH, component);
  281. } else {
  282. layout.putConstraint(SpringLayout.SOUTH, previous, yPad, SpringLayout.NORTH, component);
  283. }
  284. previous = component;
  285. }
  286. final Constraints containerConstraints = layout.getConstraints(container);
  287. containerConstraints.setConstraint(SpringLayout.SOUTH, height);
  288. containerConstraints.setConstraint(SpringLayout.EAST, width);
  289. }
  290. }