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