package com.link_intersystems.swing; import java.awt.Component; import java.awt.Dimension; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.text.MessageFormat; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.Set; public class RelativeWidthResizer<T> extends ComponentAdapter { private Map<T, Double> relativeWidths = new HashMap<T, Double>(); private ComponentResize<T> componentResize; private boolean fillLastComponent = true; public RelativeWidthResizer(ComponentResize<T> componentResize) { this.componentResize = componentResize; } public void setRelativeWidth(T component, double relativeWidth) { if (relativeWidth < 0.0) { throw new IllegalArgumentException( "Relative width must be greater or equal to 0.0"); } if (relativeWidth > 1.0) { throw new IllegalArgumentException( "Relative width must be less or equal to 1.0"); } double totalRelativeWidth = 0.0; for (Double relativeComponentWidth : relativeWidths.values()) { totalRelativeWidth += relativeComponentWidth.doubleValue(); } double availableRelativeWidth = 1.0d - (totalRelativeWidth + relativeWidth); boolean totalPercentageExceeded = availableRelativeWidth < 0; if (totalPercentageExceeded) { double remainingRelativeWidth = 1.0d - totalRelativeWidth; String message = MessageFormat.format( "Can't set component's relative width to {0}." + " {1} relative width remaining", relativeWidth, remainingRelativeWidth); throw new IllegalArgumentException(message); } relativeWidths.put(component, relativeWidth); } public void setFillLastComponent(boolean fillLastComponent) { this.fillLastComponent = fillLastComponent; } public boolean isFillLastComponent() { return this.fillLastComponent; } @Override public void componentResized(ComponentEvent e) { Component component = e.getComponent(); apply(component); } public void apply(Component baseComponent) { Dimension size = baseComponent.getSize(); int maxWidth = (int) size.getWidth(); int remainingWidth = maxWidth; Set<Entry<T, Double>> entrySet = relativeWidths.entrySet(); Iterator<Entry<T, Double>> entrySetIter = entrySet.iterator(); while (entrySetIter.hasNext()) { Entry<T, Double> componentEntry = entrySetIter.next(); T componentToResize = componentEntry.getKey(); Double relativeWidth = componentEntry.getValue(); boolean lastComponent = !entrySetIter.hasNext(); ResizeCalcParams<T> resizeCalcParams = new ResizeCalcParams<T>( componentToResize, maxWidth, remainingWidth, lastComponent, relativeWidth); remainingWidth -= resizeCalcParams.getRemainingWidth(); int width = calculateWidth(resizeCalcParams); componentResize.setWidth(componentToResize, width); } } protected int calculateWidth(ResizeCalcParams<T> componentResize) { int width = (int) (componentResize.getMaxWidth() * componentResize .getRelativeWidth()); componentResize.substractRemaining(width); if (componentResize.isLastComponent() && componentResize.hasRemaining() && fillLastComponent) { width += componentResize.getRemainingWidth(); } return width; } protected static class ResizeCalcParams<T> { private int maxWidth; private int remainingWidth; private boolean lastComponent; private Double relativeWidth; private T componentToResize; public ResizeCalcParams(T componentToResize, int maxWidth, int remainingWidth, boolean lastComponent, Double relativeWidth) { this.componentToResize = componentToResize; this.maxWidth = maxWidth; this.remainingWidth = remainingWidth; this.lastComponent = lastComponent; this.relativeWidth = relativeWidth; } public Double getRelativeWidth() { return relativeWidth; } public boolean isLastComponent() { return lastComponent; } public int getMaxWidth() { return maxWidth; } public boolean hasRemaining() { return remainingWidth > 0; } public void substractRemaining(int size) { this.remainingWidth -= size; } public int getRemainingWidth() { return remainingWidth; } public T getComponentToResize() { return componentToResize; } } }