public void invalidateLayout(Container target) {}
public void addLayoutComponent(Component comp, Object constraint) {
//we accept an Insets, a ResizeBehavior, or a Constraint.
if (constraint instanceof Insets) {
constraint = new Constraint((Insets)constraint);
} else if (constraint instanceof Constraint.ResizeBehavior) {
constraint = new Constraint((Constraint.ResizeBehavior)constraint);
}
constraints.put(comp, (Constraint)constraint);
}
public Dimension preferredLayoutSize(Container parent) {
Dimension prefSize = new Dimension();
int count = 0;
for (Component comp : constraints.keySet()) {
Constraint c = constraints.get(comp);
Dimension d = comp.getPreferredSize();
int prefWidth = 0;
if (c != null) {
Insets i = c.getInsets();
d.width += i.left + i.right;
d.height += i.top + i.bottom;
prefWidth = c.getFixedWidth();
}
prefSize.height = Math.max(prefSize.height, d.height);
prefSize.width += Math.max(d.width, prefWidth);
//If this is not the last component, add extra space between each
//component (for the separator).
count++;
if (includeSeparators() && constraints.size() < count) {
prefSize.width += getSeparatorWidth();
}
}
Insets insets = parent.getInsets();
prefSize.height += insets.top + insets.bottom;
prefSize.width += insets.left + insets.right;
return prefSize;
}
public void layoutContainer(Container parent) {
/*
* Layout algorithm:
* If the parent width is less than the sum of the preferred
* widths of the components (including separators), where
* preferred width means either the component preferred width +
* constraint insets, or fixed width + constraint insets, then
* simply layout the container from left to right and let the
* right hand components flow off the parent.
*
* Otherwise, lay out each component according to its preferred
* width except for components with a FILL constraint. For these,
* resize them evenly for each FILL constraint.
*/
//the insets of the parent component.
Insets parentInsets = parent.getInsets();
//the available width for putting components.
int availableWidth = parent.getWidth() - parentInsets.left - parentInsets.right;
if (includeSeparators()) {
//remove from availableWidth the amount of space the separators will take
availableWidth -= (parent.getComponentCount() - 1) * getSeparatorWidth();
}
//the preferred widths of all of the components -- where preferred
//width mean the preferred width after calculating fixed widths and
//constraint insets
int[] preferredWidths = new int[parent.getComponentCount()];
int sumPreferredWidths = 0;
for (int i=0; i<preferredWidths.length; i++) {
preferredWidths[i] = getPreferredWidth(parent.getComponent(i));
sumPreferredWidths += preferredWidths[i];
}
//if the availableWidth is greater than the sum of preferred
//sizes, then adjust the preferred width of each component that
//has a FILL constraint, to evenly use up the extra space.
if (availableWidth > sumPreferredWidths) {
//the number of components with a fill constraint
int numFilledComponents = 0;
for (Component comp : parent.getComponents()) {
Constraint c = constraints.get(comp);
if (c != null && c.getResizeBehavior() == Constraint.ResizeBehavior.FILL) {
numFilledComponents++;
}
}
if (numFilledComponents > 0) {
//calculate the share of free space each FILL component will take
availableWidth -= sumPreferredWidths;
double weight = 1.0 / (double)numFilledComponents;
int share = (int)(availableWidth * weight);
int remaining = numFilledComponents;
for (int i=0; i<parent.getComponentCount(); i++) {
Component comp = parent.getComponent(i);
Constraint c = constraints.get(comp);
if (c != null && c.getResizeBehavior() == Constraint.ResizeBehavior.FILL) {
if (remaining > 1) {
preferredWidths[i] += share;
availableWidth -= share;
} else {
preferredWidths[i] += availableWidth;
}
remaining--;
}
}
}
}
//now lay out the components
int nextX = parentInsets.left;
int height = parent.getHeight() - parentInsets.top - parentInsets.bottom;
for (int i=0; i<parent.getComponentCount(); i++) {
Component comp = parent.getComponent(i);
Constraint c = constraints.get(comp);
Insets insets = c == null ? new Insets(0,0,0,0) : c.getInsets();
int width = preferredWidths[i] - (insets.left + insets.right);
int x = nextX + insets.left;
int y = parentInsets.top + insets.top;
comp.setSize(width, height);
comp.setLocation(x, y);
nextX = x + width + insets.right;
//If this is not the last component, add extra space
//for the separator
if (includeSeparators() && i < parent.getComponentCount() - 1) {
nextX += getSeparatorWidth();
}
}
}
/**
* @return the "preferred" width, where that means either
* comp.getPreferredSize().width + constraintInsets, or
* constraint.fixedWidth + constraintInsets.
*/
private int getPreferredWidth(Component comp) {
Constraint c = constraints.get(comp);
if (c == null) {
return comp.getPreferredSize().width;
} else {
Insets insets = c.getInsets();
assert insets != null;
if (c.getFixedWidth() <= 0) {
return comp.getPreferredSize().width + insets.left + insets.right;
} else {
return c.getFixedWidth() + insets.left + insets.right;
}
}
}
};