package org.geogebra.desktop.gui.util; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.Insets; import java.awt.LayoutManager; /** * Layout manager which stretches all component to the full possible width, but * unlike GridLayout does not enforce any height. Unncessary space is left empty * at the bottom of the container. */ public class FullWidthLayout implements LayoutManager { private int vgap; private int minWidth = 0, minHeight = 0; private int preferredWidth = 0, preferredHeight = 0; private boolean sizeUnknown = true; /** * Creates a new instance of the layout manager with a vertical gap of 5px. */ public FullWidthLayout() { this(5); } /** * Creates a new instance of the layout manager. * * @param vgap * gap between two components in px */ public FullWidthLayout(int vgap) { this.vgap = vgap; } /** * Calculate the minimum and preferred size of the passed container. * * @param parent */ private void calculateSizes(Container parent) { preferredWidth = 0; preferredHeight = 0; minWidth = 0; minHeight = 0; Dimension pref = null, min = null; for (int i = 0; i < parent.getComponentCount(); i++) { Component c = parent.getComponent(i); if (c.isVisible()) { pref = c.getPreferredSize(); min = c.getMinimumSize(); preferredHeight += (i > 0 ? vgap : 0) + pref.height; preferredWidth = Math.max(pref.width, preferredWidth); minWidth = Math.max(min.width, minWidth); minHeight += (i > 0 ? vgap : 0) + min.height; } } } /** * @return The preferred size of the container. */ @Override public Dimension preferredLayoutSize(Container parent) { calculateSizes(parent); sizeUnknown = false; Insets insets = parent.getInsets(); return new Dimension(preferredWidth + insets.left + insets.right, preferredHeight + insets.top + insets.bottom); } /** * @return The minimum size of the container. */ @Override public Dimension minimumLayoutSize(Container parent) { if (sizeUnknown) { calculateSizes(parent); sizeUnknown = false; } Insets insets = parent.getInsets(); return new Dimension(minWidth + insets.left + insets.right, minHeight + insets.top + insets.bottom); } /** * Layout components. */ @Override public void layoutContainer(Container parent) { Insets insets = parent.getInsets(); int maxWidth = parent.getWidth() - (insets.left + insets.right); int y = insets.top; if (sizeUnknown) { calculateSizes(parent); } for (int i = 0; i < parent.getComponentCount(); i++) { Component c = parent.getComponent(i); if (c.isVisible()) { Dimension pref = c.getPreferredSize(); if (i > 0) { y += vgap; } c.setBounds(insets.left, y, maxWidth, pref.height); y += pref.height; } } } /** * Not implemented. */ @Override public void addLayoutComponent(String name, Component comp) { // not needed } /** * Not implemented. */ @Override public void removeLayoutComponent(Component comp) { // not needed } /** * The class name and vertical gap as string. */ @Override public String toString() { return getClass().getName() + "[vgap=" + vgap + "]"; } }