| /* |
| * 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() + "]"; |
| } |
| } |