/* * Copyright (c) 1996, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.awt; import java.awt.*; /** * Extends the FlowLayout class to support both vertical and horizontal * layout of components. Orientation can be changed dynamically after * creation by calling either of the methods @method orientHorizontally or * @method orientVertically. Separate values for alignment, vertical gap, * and horizontal gap can be specified for horizontal and vertical * orientation. * * @author Terry Cline */ public class OrientableFlowLayout extends FlowLayout { /** * The horizontal orientation constant. */ public static final int HORIZONTAL = 0; /** * The vertical orientation constant. */ public static final int VERTICAL = 1; /** * The top vertical alignment constant. */ public static final int TOP = 0; /** * The bottom vertical alignment constant. */ public static final int BOTTOM = 2; // CENTER == 1 int orientation; int vAlign; int vHGap; int vVGap; /** * Constructs a new flow layout with a horizontal orientation and * centered alignment. */ public OrientableFlowLayout() { this(HORIZONTAL, CENTER, CENTER, 5, 5, 5, 5); } /** * Constructs a new flow layout with the specified orientation and * a centered alignment. * * @param orientation the orientation, one of HORIZONTAL or VERTICAL. */ public OrientableFlowLayout(int orientation) { this(orientation, CENTER, CENTER, 5, 5, 5, 5); } /** * Constructs a new flow layout with the specified orientation and * alignment. * * @param orientation the orientation, one of HORIZONTAL or VERTICAL. * @param hAlign the horizontal alignment, one of LEFT, CENTER, or RIGHT. * @param vAlign the vertical alignment, one of TOP, CENTER, or BOTTOM. */ public OrientableFlowLayout(int orientation, int hAlign, int vAlign) { this(orientation, hAlign, vAlign, 5, 5, 5, 5); } /** * Constructs a new flow layout with the specified orientation, * alignment, and gap values. * * @param orientation the orientation, one of HORIZONTAL or VERTICAL. * @param hAlign the horizontal alignment, one of LEFT, CENTER, or RIGHT. * @param vAlign the vertical alignment, one of TOP, CENTER, or BOTTOM. * @param hHGap the horizontal gap between components in HORIZONTAL. * @param hVGap the vertical gap between components in HORIZONTAL. * @param vHGap the horizontal gap between components in VERTICAL. * @param vVGap the vertical gap between components in VERTICAL. */ public OrientableFlowLayout(int orientation, int hAlign, int vAlign, int hHGap, int hVGap, int vHGap, int vVGap) { super(hAlign, hHGap, hVGap); this.orientation = orientation; this.vAlign = vAlign; this.vHGap = vHGap; this.vVGap = vVGap; } /** * Set the layout's current orientation to horizontal. */ public synchronized void orientHorizontally() { orientation = HORIZONTAL; } /** * Set the layout's current orientation to vertical. */ public synchronized void orientVertically() { orientation = VERTICAL; } /** * Returns the preferred dimensions for this layout given the * components in the specified target container. * * @param target the component which needs to be laid out. * @see Container * @see FlowLayout * @see #minimumLayoutSize */ public Dimension preferredLayoutSize(Container target) { if (orientation == HORIZONTAL) { return super.preferredLayoutSize(target); } else { Dimension dim = new Dimension(0, 0); int n = target.countComponents(); for (int i = 0; i < n; i++) { Component c = target.getComponent(i); if (c.isVisible()) { Dimension cDim = c.preferredSize(); dim.width = Math.max(dim.width, cDim.width); if (i > 0) { dim.height += vVGap; } dim.height += cDim.height; } } Insets insets = target.insets();; dim.width += insets.left + insets.right + vHGap*2; dim.height += insets.top + insets.bottom + vVGap*2; return dim; } } /** * Returns the minimum dimensions needed to layout the components * contained in the specified target container. * * @param target the component which needs to be laid out. * @see #preferredLayoutSize. */ public Dimension minimumLayoutSize(Container target) { if (orientation == HORIZONTAL) { return super.minimumLayoutSize(target); } else { Dimension dim = new Dimension(0, 0); int n = target.countComponents(); for (int i = 0; i < n; i++) { Component c = target.getComponent(i); if (c.isVisible()) { Dimension cDim = c.minimumSize(); dim.width = Math.max(dim.width, cDim.width); if (i > 0) { dim.height += vVGap; } dim.height += cDim.height; } } Insets insets = target.insets(); dim.width += insets.left + insets.right + vHGap*2; dim.height += insets.top + insets.bottom + vVGap*2; return dim; } } /** * Lays out the container. This method will reshape the * components in the target to satisfy the constraints of the * layout. * * @param target the specified component being laid out. * @see Container. */ public void layoutContainer(Container target) { if (orientation == HORIZONTAL) { super.layoutContainer(target); } else { Insets insets = target.insets(); Dimension targetDim = target.size(); int maxHeight = targetDim.height - (insets.top + insets.bottom + vVGap*2); int x = insets.left + vHGap; int y = 0; int colWidth = 0; int start = 0; int n = target.countComponents(); for (int i = 0; i < n; i++) { Component c = target.getComponent(i); if (c.isVisible()) { Dimension cDim = c.preferredSize(); c.resize(cDim.width, cDim.height); if ((y == 0) || ((y + cDim.height) <= maxHeight)) { if (y > 0) { y += vVGap; } y += cDim.height; colWidth = Math.max(colWidth, cDim.width); } else { moveComponents(target, x, insets.top + vVGap, colWidth, maxHeight - y, start, i); x += vHGap + colWidth; y = cDim.width; colWidth = cDim.width; start = i; } } } moveComponents(target, x, insets.top + vVGap, colWidth, maxHeight - y, start, n); } } /** * Aligns the components vertically if there is any slack. * * @param target the container whose components need to be moved. * @param x the x coordinate. * @param y the y coordinate. * @param width the width available. * @param height the height available. * @param colStart the beginning of the column. * @param colEnd the end of the column. */ private void moveComponents(Container target, int x, int y, int width, int height, int colStart, int colEnd) { switch (vAlign) { case TOP: break; case CENTER: y += height/2; break; case BOTTOM: y += height; } for (int i = colStart; i < colEnd; i++) { Component c = target.getComponent(i); Dimension cDim = c.size(); if (c.isVisible()) { c.move(x + (width - cDim.width)/2, y); y += vVGap + cDim.height; } } } /** * Returns the String representation of this layout's values. */ public String toString() { String str = ""; switch (orientation) { case HORIZONTAL: str = "orientation=horizontal, "; break; case VERTICAL: str = "orientation=vertical, "; break; } return getClass().getName() + "[" + str + super.toString() + "]"; } }