001package jmri.util.javaworld; 002 003import java.awt.Component; 004import java.awt.Container; 005import java.awt.Dimension; 006import java.awt.GridLayout; 007import java.awt.Insets; 008 009/** 010 * Grid Layout which allows components of different sizes. 011 * From http://www.javaworld.com/javaworld/javatips/javatip121/GridLayout2.java 012 * Javaworld article by Bogdan Dorohonceanu. 013 */ 014public class GridLayout2 extends GridLayout { 015 016 public GridLayout2() { 017 this(1, 0, 0, 0); 018 } 019 020 public GridLayout2(int rows, int cols) { 021 this(rows, cols, 0, 0); 022 } 023 024 public GridLayout2(int rows, int cols, int hgap, int vgap) { 025 super(rows, cols, hgap, vgap); 026 } 027 028 @Override 029 public Dimension preferredLayoutSize(Container parent) { 030 synchronized (parent.getTreeLock()) { 031 Insets insets = parent.getInsets(); 032 int ncomponents = parent.getComponentCount(); 033 int nrows = getRows(); 034 int ncols = getColumns(); 035 if (nrows > 0) { 036 ncols = (ncomponents + nrows - 1) / nrows; 037 } else { 038 nrows = (ncomponents + ncols - 1) / ncols; 039 } 040 int[] w = new int[ncols]; 041 int[] h = new int[nrows]; 042 for (int i = 0; i < ncomponents; i++) { 043 int r = i / ncols; 044 int c = i % ncols; 045 Component comp = parent.getComponent(i); 046 Dimension d = comp.getPreferredSize(); 047 if (w[c] < d.width) { 048 w[c] = d.width; 049 } 050 if (h[r] < d.height) { 051 h[r] = d.height; 052 } 053 } 054 int nw = 0; 055 for (int j = 0; j < ncols; j++) { 056 nw += w[j]; 057 } 058 int nh = 0; 059 for (int i = 0; i < nrows; i++) { 060 nh += h[i]; 061 } 062 return new Dimension(insets.left + insets.right + nw + (ncols - 1) * getHgap(), 063 insets.top + insets.bottom + nh + (nrows - 1) * getVgap()); 064 } 065 } 066 067 @Override 068 public Dimension minimumLayoutSize(Container parent) { 069 synchronized (parent.getTreeLock()) { 070 Insets insets = parent.getInsets(); 071 int ncomponents = parent.getComponentCount(); 072 int nrows = getRows(); 073 int ncols = getColumns(); 074 if (nrows > 0) { 075 ncols = (ncomponents + nrows - 1) / nrows; 076 } else { 077 nrows = (ncomponents + ncols - 1) / ncols; 078 } 079 int[] w = new int[ncols]; 080 int[] h = new int[nrows]; 081 for (int i = 0; i < ncomponents; i++) { 082 int r = i / ncols; 083 int c = i % ncols; 084 Component comp = parent.getComponent(i); 085 Dimension d = comp.getMinimumSize(); 086 if (w[c] < d.width) { 087 w[c] = d.width; 088 } 089 if (h[r] < d.height) { 090 h[r] = d.height; 091 } 092 } 093 int nw = 0; 094 for (int j = 0; j < ncols; j++) { 095 nw += w[j]; 096 } 097 int nh = 0; 098 for (int i = 0; i < nrows; i++) { 099 nh += h[i]; 100 } 101 return new Dimension(insets.left + insets.right + nw + (ncols - 1) * getHgap(), 102 insets.top + insets.bottom + nh + (nrows - 1) * getVgap()); 103 } 104 } 105 106 @Override 107 public void layoutContainer(Container parent) { 108 synchronized (parent.getTreeLock()) { 109 Insets insets = parent.getInsets(); 110 int ncomponents = parent.getComponentCount(); 111 int nrows = getRows(); 112 int ncols = getColumns(); 113 if (ncomponents == 0) { 114 return; 115 } 116 if (nrows > 0) { 117 ncols = (ncomponents + nrows - 1) / nrows; 118 } else { 119 nrows = (ncomponents + ncols - 1) / ncols; 120 } 121 int hgap = getHgap(); 122 int vgap = getVgap(); 123 // scaling factors 124 Dimension pd = preferredLayoutSize(parent); 125 double sw = (1.0 * parent.getWidth()) / pd.width; 126 double sh = (1.0 * parent.getHeight()) / pd.height; 127 // scale 128 int[] w = new int[ncols]; 129 int[] h = new int[nrows]; 130 for (int i = 0; i < ncomponents; i++) { 131 int r = i / ncols; 132 int c = i % ncols; 133 Component comp = parent.getComponent(i); 134 Dimension d = comp.getPreferredSize(); 135 d.width = (int) (sw * d.width); 136 d.height = (int) (sh * d.height); 137 if (w[c] < d.width) { 138 w[c] = d.width; 139 } 140 if (h[r] < d.height) { 141 h[r] = d.height; 142 } 143 } 144 for (int c = 0, x = insets.left; c < ncols; c++) { 145 for (int r = 0, y = insets.top; r < nrows; r++) { 146 int i = r * ncols + c; 147 if (i < ncomponents) { 148 parent.getComponent(i).setBounds(x, y, w[c], h[r]); 149 } 150 y += h[r] + vgap; 151 } 152 x += w[c] + hgap; 153 } 154 } 155 } 156}