jdk/src/share/classes/sun/awt/OrientableFlowLayout.java
changeset 11324 0d73629f3a8d
parent 11323 8e546b2b9dd0
parent 11311 4435192939b8
child 11325 0ff7113a0882
equal deleted inserted replaced
11323:8e546b2b9dd0 11324:0d73629f3a8d
     1 /*
       
     2  * Copyright (c) 1996, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 package sun.awt;
       
    26 
       
    27 import java.awt.*;
       
    28 
       
    29 /**
       
    30  * Extends the FlowLayout class to support both vertical and horizontal
       
    31  * layout of components.  Orientation can be changed dynamically after
       
    32  * creation by calling either of the methods @method orientHorizontally or
       
    33  * @method orientVertically.  Separate values for alignment, vertical gap,
       
    34  * and horizontal gap can be specified for horizontal and vertical
       
    35  * orientation.
       
    36  *
       
    37  * @author Terry Cline
       
    38  */
       
    39 public class OrientableFlowLayout extends FlowLayout {
       
    40     /**
       
    41      * The horizontal orientation constant.
       
    42      */
       
    43     public static final int HORIZONTAL = 0;
       
    44 
       
    45     /**
       
    46      * The vertical orientation constant.
       
    47      */
       
    48     public static final int VERTICAL   = 1;
       
    49 
       
    50     /**
       
    51      * The top vertical alignment constant.
       
    52      */
       
    53     public static final int TOP        = 0;
       
    54 
       
    55     /**
       
    56      * The bottom vertical alignment constant.
       
    57      */
       
    58     public static final int BOTTOM     = 2; // CENTER == 1
       
    59 
       
    60     int orientation;
       
    61     int vAlign;
       
    62     int vHGap;
       
    63     int vVGap;
       
    64 
       
    65     /**
       
    66      * Constructs a new flow layout with a horizontal orientation and
       
    67      * centered alignment.
       
    68      */
       
    69     public OrientableFlowLayout() {
       
    70         this(HORIZONTAL, CENTER, CENTER, 5, 5, 5, 5);
       
    71     }
       
    72 
       
    73     /**
       
    74      * Constructs a new flow layout with the specified orientation and
       
    75      * a centered alignment.
       
    76      *
       
    77      * @param orientation the orientation, one of HORIZONTAL or VERTICAL.
       
    78      */
       
    79     public OrientableFlowLayout(int orientation) {
       
    80         this(orientation, CENTER, CENTER, 5, 5, 5, 5);
       
    81     }
       
    82 
       
    83     /**
       
    84      * Constructs a new flow layout with the specified orientation and
       
    85      * alignment.
       
    86      *
       
    87      * @param orientation the orientation, one of HORIZONTAL or VERTICAL.
       
    88      * @param hAlign the horizontal alignment, one of LEFT, CENTER, or RIGHT.
       
    89      * @param vAlign the vertical alignment, one of TOP, CENTER, or BOTTOM.
       
    90      */
       
    91     public OrientableFlowLayout(int orientation, int hAlign, int vAlign) {
       
    92         this(orientation, hAlign, vAlign, 5, 5, 5, 5);
       
    93     }
       
    94 
       
    95     /**
       
    96      * Constructs a new flow layout with the specified orientation,
       
    97      * alignment, and gap values.
       
    98      *
       
    99      * @param orientation the orientation, one of HORIZONTAL or VERTICAL.
       
   100      * @param hAlign the horizontal alignment, one of LEFT, CENTER, or RIGHT.
       
   101      * @param vAlign the vertical alignment, one of TOP, CENTER, or BOTTOM.
       
   102      * @param hHGap the horizontal gap between components in HORIZONTAL.
       
   103      * @param hVGap the vertical gap between components in HORIZONTAL.
       
   104      * @param vHGap the horizontal gap between components in VERTICAL.
       
   105      * @param vVGap the vertical gap between components in VERTICAL.
       
   106      */
       
   107     public OrientableFlowLayout(int orientation, int hAlign, int vAlign, int hHGap, int hVGap, int vHGap, int vVGap) {
       
   108         super(hAlign, hHGap, hVGap);
       
   109         this.orientation = orientation;
       
   110         this.vAlign      = vAlign;
       
   111         this.vHGap       = vHGap;
       
   112         this.vVGap       = vVGap;
       
   113     }
       
   114 
       
   115     /**
       
   116      * Set the layout's current orientation to horizontal.
       
   117      */
       
   118     public synchronized void orientHorizontally() {
       
   119         orientation = HORIZONTAL;
       
   120     }
       
   121 
       
   122     /**
       
   123      * Set the layout's current orientation to vertical.
       
   124      */
       
   125     public synchronized void orientVertically() {
       
   126         orientation = VERTICAL;
       
   127     }
       
   128 
       
   129     /**
       
   130      * Returns the preferred dimensions for this layout given the
       
   131      * components in the specified target container.
       
   132      *
       
   133      * @param target the component which needs to be laid out.
       
   134      * @see Container
       
   135      * @see FlowLayout
       
   136      * @see #minimumLayoutSize
       
   137      */
       
   138     public Dimension preferredLayoutSize(Container target) {
       
   139         if (orientation == HORIZONTAL) {
       
   140             return super.preferredLayoutSize(target);
       
   141         }
       
   142         else {
       
   143             Dimension dim = new Dimension(0, 0);
       
   144 
       
   145             int n = target.countComponents();
       
   146             for (int i = 0; i < n; i++) {
       
   147                 Component c = target.getComponent(i);
       
   148                 if (c.isVisible()) {
       
   149                     Dimension cDim = c.preferredSize();
       
   150                     dim.width = Math.max(dim.width, cDim.width);
       
   151                     if (i > 0) {
       
   152                         dim.height += vVGap;
       
   153                     }
       
   154                     dim.height += cDim.height;
       
   155                 }
       
   156             }
       
   157 
       
   158             Insets insets = target.insets();;
       
   159             dim.width  += insets.left + insets.right  + vHGap*2;
       
   160             dim.height += insets.top  + insets.bottom + vVGap*2;
       
   161 
       
   162             return dim;
       
   163         }
       
   164     }
       
   165 
       
   166     /**
       
   167      * Returns the minimum dimensions needed to layout the components
       
   168      * contained in the specified target container.
       
   169      *
       
   170      * @param target the component which needs to be laid out.
       
   171      * @see #preferredLayoutSize.
       
   172      */
       
   173     public Dimension minimumLayoutSize(Container target) {
       
   174         if (orientation == HORIZONTAL) {
       
   175             return super.minimumLayoutSize(target);
       
   176         }
       
   177         else {
       
   178             Dimension dim = new Dimension(0, 0);
       
   179 
       
   180             int n = target.countComponents();
       
   181             for (int i = 0; i < n; i++) {
       
   182                 Component c = target.getComponent(i);
       
   183                 if (c.isVisible()) {
       
   184                     Dimension cDim = c.minimumSize();
       
   185                     dim.width = Math.max(dim.width, cDim.width);
       
   186                     if (i > 0) {
       
   187                         dim.height += vVGap;
       
   188                     }
       
   189                     dim.height += cDim.height;
       
   190                 }
       
   191             }
       
   192 
       
   193             Insets insets = target.insets();
       
   194             dim.width  += insets.left + insets.right  + vHGap*2;
       
   195             dim.height += insets.top  + insets.bottom + vVGap*2;
       
   196 
       
   197             return dim;
       
   198         }
       
   199     }
       
   200 
       
   201     /**
       
   202      * Lays out the container.  This method will reshape the
       
   203      * components in the target to satisfy the constraints of the
       
   204      * layout.
       
   205      *
       
   206      * @param target the specified component being laid out.
       
   207      * @see Container.
       
   208      */
       
   209     public void layoutContainer(Container target) {
       
   210         if (orientation == HORIZONTAL) {
       
   211             super.layoutContainer(target);
       
   212         }
       
   213         else {
       
   214             Insets insets = target.insets();
       
   215             Dimension targetDim = target.size();
       
   216             int maxHeight = targetDim.height - (insets.top + insets.bottom + vVGap*2);
       
   217             int x = insets.left + vHGap;
       
   218             int y = 0;
       
   219             int colWidth = 0;
       
   220             int start = 0;
       
   221 
       
   222             int n = target.countComponents();
       
   223             for (int i = 0; i < n; i++) {
       
   224                 Component c = target.getComponent(i);
       
   225                 if (c.isVisible()) {
       
   226                     Dimension cDim = c.preferredSize();
       
   227                     c.resize(cDim.width, cDim.height);
       
   228 
       
   229                     if ((y == 0) || ((y + cDim.height) <= maxHeight)) {
       
   230                         if (y > 0) {
       
   231                             y += vVGap;
       
   232                         }
       
   233                         y += cDim.height;
       
   234                         colWidth = Math.max(colWidth, cDim.width);
       
   235                     }
       
   236                     else {
       
   237                         moveComponents(target,
       
   238                                        x,
       
   239                                        insets.top + vVGap,
       
   240                                        colWidth,
       
   241                                        maxHeight - y,
       
   242                                        start,
       
   243                                        i);
       
   244                         x += vHGap + colWidth;
       
   245                         y = cDim.width;
       
   246                         colWidth = cDim.width;
       
   247                         start = i;
       
   248                     }
       
   249                 }
       
   250             }
       
   251 
       
   252             moveComponents(target,
       
   253                            x,
       
   254                            insets.top + vVGap,
       
   255                            colWidth,
       
   256                            maxHeight - y,
       
   257                            start,
       
   258                            n);
       
   259         }
       
   260     }
       
   261 
       
   262     /**
       
   263      * Aligns the components vertically if there is any slack.
       
   264      *
       
   265      * @param target the container whose components need to be moved.
       
   266      * @param x the x coordinate.
       
   267      * @param y the y coordinate.
       
   268      * @param width the width available.
       
   269      * @param height the height available.
       
   270      * @param colStart the beginning of the column.
       
   271      * @param colEnd the end of the column.
       
   272      */
       
   273     private void moveComponents(Container target, int x, int y, int width, int height, int colStart, int colEnd) {
       
   274         switch (vAlign) {
       
   275         case TOP:
       
   276             break;
       
   277         case CENTER:
       
   278             y += height/2;
       
   279             break;
       
   280         case BOTTOM:
       
   281             y += height;
       
   282         }
       
   283 
       
   284         for (int i = colStart; i < colEnd; i++) {
       
   285             Component c = target.getComponent(i);
       
   286             Dimension cDim = c.size();
       
   287             if (c.isVisible()) {
       
   288                 c.move(x + (width - cDim.width)/2, y);
       
   289                 y += vVGap + cDim.height;
       
   290             }
       
   291         }
       
   292     }
       
   293 
       
   294     /**
       
   295      * Returns the String representation of this layout's values.
       
   296      */
       
   297     public String toString() {
       
   298         String str = "";
       
   299         switch (orientation) {
       
   300         case HORIZONTAL:
       
   301             str = "orientation=horizontal, ";
       
   302             break;
       
   303         case VERTICAL:
       
   304             str = "orientation=vertical, ";
       
   305             break;
       
   306         }
       
   307 
       
   308         return getClass().getName() + "[" + str + super.toString() + "]";
       
   309     }
       
   310 }