PageRenderTime 49ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/tags/jedit-4-3-pre5/installer/VariableGridLayout.java

#
Java | 334 lines | 183 code | 53 blank | 98 comment | 40 complexity | 39bcb51e0afeb0ff91021f07ddc57984 MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  1. /*
  2. * VariableGridLayout.java - a grid layout manager with variable cell sizes
  3. *
  4. * Originally written by Dirk Moebius for the jEdit project. This work has been
  5. * placed into the public domain. You may use this work in any way and for any
  6. * purpose you wish.
  7. *
  8. * THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, NOT EVEN THE
  9. * IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE, ASSUMES
  10. * _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE RESULTING FROM THE USE, MODIFICATION,
  11. * OR REDISTRIBUTION OF THIS SOFTWARE.
  12. */
  13. package installer;
  14. import java.awt.*;
  15. // This is copied from jEdit's org.gjt.sp.jedit.gui package.
  16. /**
  17. * The <code>VariableGridLayout</code> class is a layout manager
  18. * that lays out a container's components in a rectangular grid
  19. * with variable cell sizes.<p>
  20. *
  21. * The container is divided into rectangles, and one component is placed
  22. * in each rectangle. Each row is as large as the largest component in
  23. * that row, and each column is as wide as the widest component in
  24. * that column.<p>
  25. *
  26. * This behavior is basically the same as in
  27. * <code>java.awt.GridLayout</code>, but with different row heights and
  28. * column widths for each row/column.<p>
  29. *
  30. * For example, the following is an applet that lays out six buttons
  31. * into three rows and two columns:<p>
  32. *
  33. * <blockquote><pre>
  34. * import java.awt.*;
  35. * import java.applet.Applet;
  36. * public class ButtonGrid extends Applet {
  37. * public void init() {
  38. * setLayout(new VariableGridLayout(VariableGridLayout.FIXED_NUM_COLUMNS, 2));
  39. * add(new Button("1"));
  40. * add(new Button("2"));
  41. * add(new Button("3"));
  42. * add(new Button("4"));
  43. * add(new Button("5"));
  44. * add(new Button("6"));
  45. * }
  46. * }
  47. * </pre></blockquote><p>
  48. *
  49. * <b>Programmer's remark:</b> VariableGridLayout could be faster, if it would
  50. * reside in the package java.awt, because then it could access some
  51. * package private fields of <code>Container</code> or
  52. * <code>Component</code>. Instead, it has to call
  53. * <code>Component.getSize()</code>,
  54. * which allocates memory on the heap.<p>
  55. *
  56. * <b>Todo:</b>
  57. * <ul>
  58. * <li>Use alignmentX/Y property if the grid cell is larger than the preferred size of the component.
  59. * <li>Ability to span components over more than one cell horizontally
  60. * </ul>
  61. *
  62. * @author Dirk Moebius
  63. * @version 1.0
  64. * @see java.awt.GridLayout
  65. */
  66. public class VariableGridLayout implements LayoutManager2, java.io.Serializable
  67. {
  68. public static final int FIXED_NUM_ROWS = 1;
  69. public static final int FIXED_NUM_COLUMNS = 2;
  70. public VariableGridLayout(int mode, int size, int hgap, int vgap) {
  71. if (mode != FIXED_NUM_ROWS && mode != FIXED_NUM_COLUMNS) {
  72. throw new IllegalArgumentException("illegal mode; value is " + mode);
  73. }
  74. if (size <= 0) {
  75. throw new IllegalArgumentException("size cannot be zero or less; value is " + size);
  76. }
  77. if (hgap < 0) {
  78. throw new IllegalArgumentException("hgap cannot be negative; value is " + hgap);
  79. }
  80. if (vgap < 0) {
  81. throw new IllegalArgumentException("vgap cannot be negative; value is " + vgap);
  82. }
  83. this.mode = mode;
  84. this.size = size;
  85. this.hgap = hgap;
  86. this.vgap = vgap;
  87. }
  88. /**
  89. * Creates a variable grid layout manager with the specified mode
  90. * and zero horizontal and vertical gap.
  91. */
  92. public VariableGridLayout(int mode, int size) {
  93. this(mode, size, 0, 0);
  94. }
  95. /**
  96. * Creates a variable grid layout manager with mode FIXED_NUM_ROWS,
  97. * number of rows == 1 and zero horizontal and vertical gap.
  98. */
  99. public VariableGridLayout() {
  100. this(FIXED_NUM_ROWS, 1, 0, 0);
  101. }
  102. /**
  103. * Not used in this class.
  104. */
  105. public void addLayoutComponent(String name, Component component) { }
  106. /**
  107. * Not used in this class.
  108. */
  109. public void addLayoutComponent(Component component, Object constraints) { }
  110. /**
  111. * Not used in this class.
  112. */
  113. public void removeLayoutComponent(Component component) { }
  114. /**
  115. * Always returns 0.5.
  116. */
  117. public float getLayoutAlignmentX(Container container) {
  118. return 0.5f;
  119. }
  120. /**
  121. * Always returns 0.5.
  122. */
  123. public float getLayoutAlignmentY(Container container) {
  124. return 0.5f;
  125. }
  126. public Dimension preferredLayoutSize(Container parent) {
  127. return getLayoutSize(parent, 2);
  128. }
  129. public Dimension minimumLayoutSize(Container parent) {
  130. return getLayoutSize(parent, 0);
  131. }
  132. public Dimension maximumLayoutSize(Container parent) {
  133. return getLayoutSize(parent, 1);
  134. }
  135. public void layoutContainer(Container parent) {
  136. synchronized (parent.getTreeLock()) {
  137. update(parent);
  138. int ncomponents = parent.getComponentCount();
  139. if (ncomponents == 0) {
  140. return;
  141. }
  142. // Pass 1: compute preferred row heights / column widths
  143. int total_height = 0;
  144. for (int r = 0, i = 0; r < nrows; r++) {
  145. for (int c = 0; c < ncols; c++, i++) {
  146. if (i < ncomponents) {
  147. Dimension d = parent.getComponent(i).getPreferredSize();
  148. row_heights[r] = Math.max(row_heights[r], d.height);
  149. col_widths[c] = Math.max(col_widths[c], d.width);
  150. } else {
  151. break;
  152. }
  153. }
  154. total_height += row_heights[r];
  155. }
  156. int total_width = 0;
  157. for (int c = 0; c < ncols; c++) {
  158. total_width += col_widths[c];
  159. }
  160. // Pass 2: redistribute free space
  161. Dimension parent_size = parent.getSize();
  162. Insets insets = parent.getInsets();
  163. int free_height = parent_size.height - insets.top - insets.bottom - (nrows - 1) * vgap;
  164. int free_width = parent_size.width - insets.left - insets.right - (ncols - 1) * hgap;
  165. if (total_height != free_height) {
  166. double dy = (double)free_height / (double)total_height;
  167. for (int r = 0; r < nrows; r++) {
  168. row_heights[r] = (int) ((double)row_heights[r] * dy);
  169. }
  170. }
  171. if (total_width != free_width) {
  172. double dx = ((double)free_width) / ((double)total_width);
  173. for (int c = 0; c < ncols; c++) {
  174. col_widths[c] = (int) ((double)col_widths[c] * dx);
  175. }
  176. }
  177. // Pass 3: layout components
  178. for (int r = 0, y = insets.top, i = 0; r < nrows; y += row_heights[r] + vgap, r++) {
  179. for (int c = 0, x = insets.left; c < ncols; x += col_widths[c] + hgap, c++, i++) {
  180. if (i < ncomponents) {
  181. parent.getComponent(i).setBounds(x, y, col_widths[c], row_heights[r]);
  182. }
  183. }
  184. }
  185. } // synchronized
  186. }
  187. public void invalidateLayout(Container container) {}
  188. /**
  189. * Returns the string representation of this variable grid layout's values.
  190. * @return a string representation of this variable grid layout.
  191. */
  192. public String toString() {
  193. return getClass().getName() + "[mode=" + mode + ",size=" + size
  194. + ",hgap=" + hgap + ",vgap=" + vgap + "]";
  195. }
  196. /**
  197. * @param which if 0 compute minimum layout size,
  198. * if 1 compute maximum layout size,
  199. * otherwise compute preferred layout size.
  200. */
  201. private Dimension getLayoutSize(Container parent, int which) {
  202. synchronized (parent.getTreeLock()){
  203. update(parent);
  204. int ncomponents = parent.getComponentCount();
  205. int h = 0;
  206. int w = 0;
  207. for (int r = 0, i = 0; r < nrows; r++) {
  208. int row_height = 0;
  209. for (int c = 0; c < ncols; c++, i++) {
  210. if (i < ncomponents) {
  211. switch (which) {
  212. case 0:
  213. row_height = Math.max(row_height, parent.getComponent(i).getMinimumSize().height);
  214. break;
  215. case 1:
  216. row_height = Math.max(row_height, parent.getComponent(i).getMaximumSize().height);
  217. break;
  218. default:
  219. row_height = Math.max(row_height, parent.getComponent(i).getPreferredSize().height);
  220. break;
  221. }
  222. } else {
  223. break;
  224. }
  225. }
  226. h += row_height;
  227. }
  228. for (int c = 0; c < ncols; c++) {
  229. int col_width = 0;
  230. for (int r = 0; r < nrows; r++) {
  231. int i = r * ncols + c;
  232. if (i < ncomponents) {
  233. switch (which) {
  234. case 0:
  235. col_width = Math.max(col_width, parent.getComponent(i).getMinimumSize().width);
  236. break;
  237. case 1:
  238. col_width = Math.max(col_width, parent.getComponent(i).getMaximumSize().width);
  239. break;
  240. default:
  241. col_width = Math.max(col_width, parent.getComponent(i).getPreferredSize().width);
  242. break;
  243. }
  244. } else {
  245. break;
  246. }
  247. }
  248. w += col_width;
  249. }
  250. Insets insets = parent.getInsets();
  251. return new Dimension(w + insets.left + insets.right + ((ncols - 1) * hgap),
  252. h + insets.top + insets.bottom + ((nrows - 1) * vgap));
  253. }
  254. }
  255. private void update(Container container) {
  256. int ncomponents = container.getComponentCount();
  257. int old_nrows = nrows;
  258. int old_ncols = ncols;
  259. if (this.mode == FIXED_NUM_ROWS) {
  260. nrows = this.size;
  261. ncols = (ncomponents + nrows - 1) / nrows;
  262. } else {
  263. ncols = this.size;
  264. nrows = (ncomponents + ncols - 1) / ncols;
  265. }
  266. if (old_nrows != nrows) {
  267. row_heights = new int[nrows];
  268. }
  269. if (old_ncols != ncols) {
  270. col_widths = new int[ncols];
  271. }
  272. }
  273. private int mode;
  274. private int size;
  275. private int hgap;
  276. private int vgap;
  277. private transient int nrows = -1;
  278. private transient int ncols = -1;
  279. private transient int[] row_heights = null;
  280. private transient int[] col_widths = null;
  281. }