/*
* Copyright (C) 2010 Brockmann Consult GmbH (info@brockmann-consult.de)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 3 of the License, or (at your option)
* any later version.
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, see http://www.gnu.org/licenses/
*/
package org.esa.snap.ui;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Insets;
/**
* A grid layout which allows components of differrent sizes.
*/
public class GridLayout2 extends GridLayout {
public GridLayout2() {
this(1, 0, 0, 0);
}
public GridLayout2(int rows, int cols) {
this(rows, cols, 0, 0);
}
public GridLayout2(int rows, int cols, int hgap, int vgap) {
super(rows, cols, hgap, vgap);
}
@Override
public Dimension preferredLayoutSize(Container parent) {
//System.err.println("preferredLayoutSize");
synchronized (parent.getTreeLock()) {
Insets insets = parent.getInsets();
int ncomponents = parent.getComponentCount();
int nrows = getRows();
int ncols = getColumns();
if (nrows > 0) {
ncols = (ncomponents + nrows - 1) / nrows;
} else {
nrows = (ncomponents + ncols - 1) / ncols;
}
int[] w = new int[ncols];
int[] h = new int[nrows];
for (int i = 0; i < ncomponents; i++) {
int r = i / ncols;
int c = i % ncols;
Component comp = parent.getComponent(i);
Dimension d = comp.getPreferredSize();
if (w[c] < d.width) {
w[c] = d.width;
}
if (h[r] < d.height) {
h[r] = d.height;
}
}
int nw = 0;
for (int j = 0; j < ncols; j++) {
nw += w[j];
}
int nh = 0;
for (int i = 0; i < nrows; i++) {
nh += h[i];
}
return new Dimension(insets.left + insets.right + nw + (ncols - 1) * getHgap(),
insets.top + insets.bottom + nh + (nrows - 1) * getVgap());
}
}
@Override
public Dimension minimumLayoutSize(Container parent) {
//System.err.println("minimumLayoutSize");
synchronized (parent.getTreeLock()) {
Insets insets = parent.getInsets();
int ncomponents = parent.getComponentCount();
int nrows = getRows();
int ncols = getColumns();
if (nrows > 0) {
ncols = (ncomponents + nrows - 1) / nrows;
} else {
nrows = (ncomponents + ncols - 1) / ncols;
}
int[] w = new int[ncols];
int[] h = new int[nrows];
for (int i = 0; i < ncomponents; i++) {
int r = i / ncols;
int c = i % ncols;
Component comp = parent.getComponent(i);
Dimension d = comp.getMinimumSize();
if (w[c] < d.width) {
w[c] = d.width;
}
if (h[r] < d.height) {
h[r] = d.height;
}
}
int nw = 0;
for (int j = 0; j < ncols; j++) {
nw += w[j];
}
int nh = 0;
for (int i = 0; i < nrows; i++) {
nh += h[i];
}
return new Dimension(insets.left + insets.right + nw + (ncols - 1) * getHgap(),
insets.top + insets.bottom + nh + (nrows - 1) * getVgap());
}
}
@Override
public void layoutContainer(Container parent) {
//System.err.println("layoutContainer");
synchronized (parent.getTreeLock()) {
Insets insets = parent.getInsets();
int ncomponents = parent.getComponentCount();
int nrows = getRows();
int ncols = getColumns();
if (ncomponents == 0) {
return;
}
if (nrows > 0) {
ncols = (ncomponents + nrows - 1) / nrows;
} else {
nrows = (ncomponents + ncols - 1) / ncols;
}
int hgap = getHgap();
int vgap = getVgap();
// scaling factors
Dimension pd = preferredLayoutSize(parent);
double sw = (1.0 * parent.getWidth()) / pd.width;
double sh = (1.0 * parent.getHeight()) / pd.height;
// scale
int[] w = new int[ncols];
int[] h = new int[nrows];
for (int i = 0; i < ncomponents; i++) {
int r = i / ncols;
int c = i % ncols;
Component comp = parent.getComponent(i);
Dimension d = comp.getPreferredSize();
d.width = (int) (sw * d.width);
d.height = (int) (sh * d.height);
if (w[c] < d.width) {
w[c] = d.width;
}
if (h[r] < d.height) {
h[r] = d.height;
}
}
for (int c = 0, x = insets.left; c < ncols; c++) {
for (int r = 0, y = insets.top; r < nrows; r++) {
int i = r * ncols + c;
if (i < ncomponents) {
parent.getComponent(i).setBounds(x, y, w[c], h[r]);
}
y += h[r] + vgap;
}
x += w[c] + hgap;
}
}
}
}