package common; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.LayoutManager; import java.awt.Rectangle; import java.util.LinkedList; import javax.swing.JComponent; /** * * @author Michel Bartsch * * This LayoutManager places components without any dependencies between each * other. Scaling the layouted container will make every component scaled * proportional. */ public class TotalScaleLayout implements LayoutManager { /** The container to layout. */ Container parent; /** The containers preferred size. */ Dimension preferredSize; /** The containers minimum size. */ Dimension minimumSize; /** List of all components to layout on the container */ LinkedList<TotalScaleComponent> comps = new LinkedList<TotalScaleComponent>(); /** * Creates a new TotalScaleLayout. * * @param parent The container to layout. * */ public TotalScaleLayout(Container parent) { this.parent = parent; preferredSize = parent.getPreferredSize(); minimumSize = parent.getMinimumSize(); } /** * This will add a Component to the container to be layout. Use this instead * of the add-method of the container itself. * * @param x Left-edge position on the container between 0 and 1. * @param y Top-edge position on the container between 0 and 1. * @param width Width on the container between 0 and 1. * @param height Height on the container between 0 and 1. * @param comp Component to be added. * */ public void add(double x, double y, double width, double height, JComponent comp) { parent.add(comp); comps.add(new TotalScaleComponent(x, y, width, height, comp)); } /** * Not supported because of own add-method. */ @Override public void addLayoutComponent(String name, Component comp) {} /** * Gets called to remove Component. * * @param comp Component to remove. */ @Override public void removeLayoutComponent(Component comp) { for (TotalScaleComponent tscomp : comps) { if (tscomp.comp == comp) { comps.remove(tscomp); break; } } } /** * Because all of the Components`s sizes are adapted to the containers size * this will allways return the size of the container when the layout was * created. * * @param parent Container this layout belongs to. * * @return This layouts preferred size. */ @Override public Dimension preferredLayoutSize(Container parent) { return preferredSize; } /** * Because all of the Components`s sizes are adapted to the containers size * this will allways return the size of the container when the layout was * created. * * @param parent Container this layout belongs to. * * @return This layouts minimum size. */ @Override public Dimension minimumLayoutSize(Container parent) { return minimumSize; } /** * This gets called automatically to adapt position and size of all * components. * * @param parent Container to layout. */ @Override public void layoutContainer(Container parent) { Rectangle parentBounds = parent.getBounds(); for (TotalScaleComponent comp : comps) { comp.comp.setBounds( (int)(comp.x*parentBounds.width), (int)(comp.y*parentBounds.height), (int)(comp.width*parentBounds.width), (int)(comp.height*parentBounds.height)); } } /** * This class simply wraps some attributes like a struct. */ class TotalScaleComponent { /* Left-edge position on the container between 0 and 1. */ double x; /* Top-edge position on the container between 0 and 1. */ double y; /* Width on the container between 0 and 1. */ double width; /* Height on the container between 0 and 1. */ double height; /* Component to be layouted on the container. */ Component comp; /** * Creates a new TotalScaleComponent. * * @param x Left-edge position on the container between 0 and 1. * @param y Top-edge position on the container between 0 and 1. * @param width Width on the container between 0 and 1. * @param height Height on the container between 0 and 1. * @param comp Component to be layouted on the container. * */ TotalScaleComponent(double x, double y, double width, double height, Component comp) { this.x = x; this.y = y; this.width = width; this.height = height; this.comp = comp; } } }