1/*
2 * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.tools.jconsole;
27
28import java.awt.*;
29
30import javax.swing.*;
31
32@SuppressWarnings("serial")
33public class VariableGridLayout extends GridLayout {
34
35    private boolean fillRows, fillColumns;
36
37    public VariableGridLayout(int rows, int cols,
38                              int hgap, int vgap,
39                              boolean fillRows, boolean fillColumns) {
40        super(rows, cols, hgap, vgap);
41
42        this.fillRows    = fillRows;
43        this.fillColumns = fillColumns;
44    }
45
46    public void setFillRow(JComponent c, boolean b) {
47        c.putClientProperty("VariableGridLayout.fillRow", b);
48    }
49
50    public void setFillColumn(JComponent c, boolean b) {
51        c.putClientProperty("VariableGridLayout.fillColumn", b);
52    }
53
54    public boolean getFillRow(JComponent c) {
55        Boolean b = (Boolean)c.getClientProperty("VariableGridLayout.fillRow");
56        return (b != null) ? b : fillRows;
57    }
58
59    public boolean getFillColumn(JComponent c) {
60        Boolean b = (Boolean)c.getClientProperty("VariableGridLayout.fillColumn");
61        return (b != null) ? b : fillColumns;
62    }
63
64    public void layoutContainer(Container parent) {
65        Insets insets = parent.getInsets();
66        int ncomponents = parent.getComponentCount();
67        int nrows = getRows();
68        int ncols = getColumns();
69        int hgap =  getHgap();
70        int vgap =  getVgap();
71
72        if (nrows > 0) {
73            ncols = (ncomponents + nrows - 1) / nrows;
74        } else {
75            nrows = (ncomponents + ncols - 1) / ncols;
76        }
77
78        // Set heights
79        int x;
80        int y;
81        int nFills = 0;
82        boolean[] fills = new boolean[nrows];
83        int lastFillRow = -1;
84        int nComps = parent.getComponentCount();
85
86        y = insets.top;
87        for (int row = 0; row < nrows; row++) {
88            // Find largest minimum height for this row
89            int h = 0;
90            for (int col = 0; col < ncols; col++) {
91                if (row * ncols + col < nComps) {
92                    Component c = parent.getComponent(row * ncols + col);
93                    h = Math.max(h, c.getMinimumSize().height);
94                }
95            }
96            // Set heights for this row
97            x = insets.left;
98            for (int col = 0; col < ncols; col++) {
99                if (row * ncols + col < nComps) {
100                    JComponent c = (JComponent)parent.getComponent(row * ncols + col);
101                    int w = c.getWidth();
102                    c.setBounds(x, y, w, h);
103                    x += w + hgap;
104                    if (col == 0 && getFillRow(c)) {
105                        fills[row] = true;
106                    }
107                }
108            }
109            y += h + vgap;
110            if (fills[row]) {
111                nFills++;
112                lastFillRow = row;
113            }
114        }
115
116        // Fill heights
117        if (nFills > 0 && y < parent.getHeight()) {
118            // How much height to add
119            int hAdd = (parent.getHeight() - y) / nFills;
120            int hAdded = 0;
121            for (int row = 0; row < nrows; row++) {
122                if (fills[row]) {
123                    if (row == lastFillRow) {
124                        // Compensate for rounding error
125                        hAdd = parent.getHeight() - (y+hAdded);
126                    }
127                    for (int col = 0; col < ncols; col++) {
128                        if (row * ncols + col < nComps) {
129                            Component c = parent.getComponent(row * ncols + col);
130                            Rectangle b = c.getBounds();
131                            c.setBounds(b.x, b.y + hAdded, b.width, b.height + hAdd);
132                        }
133                    }
134                    hAdded += hAdd;
135                }
136            }
137        }
138
139        // Set widths
140        nFills = 0;
141        fills = new boolean[ncols];
142        int lastFillCol = -1;
143
144        x = insets.left;
145        for (int col = 0; col < ncols; col++) {
146            // Find largest minimum width for this column
147            int w = 0;
148            for (int row = 0; row < nrows; row++) {
149                if (row * ncols + col < nComps) {
150                    Component c = parent.getComponent(row * ncols + col);
151                    w = Math.max(w, c.getMinimumSize().width);
152                }
153            }
154            // Set widths for this column
155            y = insets.top;
156            for (int row = 0; row < nrows; row++) {
157                if (row * ncols + col < nComps) {
158                    JComponent c = (JComponent)parent.getComponent(row * ncols + col);
159                    int h = c.getHeight();
160                    c.setBounds(x, y, w, h);
161                    y += h + vgap;
162                    if (row == 0 && getFillColumn(c)) {
163                        fills[col] = true;
164                    }
165                }
166            }
167            x += w + hgap;
168            if (fills[col]) {
169                nFills++;
170                lastFillCol = col;
171            }
172        }
173
174        // Fill widths
175        if (nFills > 0 && x < parent.getWidth()) {
176            // How much width to add
177            int wAdd = (parent.getWidth() - x) / nFills;
178            int wAdded = 0;
179            for (int col = 0; col < ncols; col++) {
180                if (fills[col]) {
181                    if (col == lastFillCol) {
182                        wAdd = parent.getWidth() - (x+wAdded);
183                    }
184                    for (int row = 0; row < nrows; row++) {
185                        if (row * ncols + col < nComps) {
186                            Component c = parent.getComponent(row * ncols + col);
187                            Rectangle b = c.getBounds();
188                            c.setBounds(b.x + wAdded, b.y, b.width + wAdd, b.height);
189                        }
190                    }
191                    wAdded += wAdd;
192                }
193            }
194        }
195    }
196
197    public Dimension preferredLayoutSize(Container parent) {
198        Insets insets = parent.getInsets();
199        int ncomponents = parent.getComponentCount();
200        int nrows = getRows();
201        int ncols = getColumns();
202        int hgap =  getHgap();
203        int vgap =  getVgap();
204
205        if (nrows > 0) {
206            ncols = (ncomponents + nrows - 1) / nrows;
207        } else {
208            nrows = (ncomponents + ncols - 1) / ncols;
209        }
210
211        int nComps = parent.getComponentCount();
212
213        int y = insets.top;
214        for (int row = 0; row < nrows; row++) {
215            int h = 0;
216            for (int col = 0; col < ncols; col++) {
217                if (row * ncols + col < nComps) {
218                    Component c = parent.getComponent(row * ncols + col);
219                    h = Math.max(h, c.getMinimumSize().height);
220                }
221            }
222            y += h + vgap;
223        }
224
225        int x = insets.left;
226        for (int col = 0; col < ncols; col++) {
227            int w = 0;
228            for (int row = 0; row < nrows; row++) {
229                if (row * ncols + col < nComps) {
230                    Component c = parent.getComponent(row * ncols + col);
231                    w = Math.max(w, c.getMinimumSize().width);
232                }
233            }
234            x += w + hgap;
235        }
236        return new Dimension(x, y);
237    }
238}
239