Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/awt/FlowLayout.java
38829 views
/*1* Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24package java.awt;2526import java.io.ObjectInputStream;27import java.io.IOException;2829/**30* A flow layout arranges components in a directional flow, much31* like lines of text in a paragraph. The flow direction is32* determined by the container's <code>componentOrientation</code>33* property and may be one of two values:34* <ul>35* <li><code>ComponentOrientation.LEFT_TO_RIGHT</code>36* <li><code>ComponentOrientation.RIGHT_TO_LEFT</code>37* </ul>38* Flow layouts are typically used39* to arrange buttons in a panel. It arranges buttons40* horizontally until no more buttons fit on the same line.41* The line alignment is determined by the <code>align</code>42* property. The possible values are:43* <ul>44* <li>{@link #LEFT LEFT}45* <li>{@link #RIGHT RIGHT}46* <li>{@link #CENTER CENTER}47* <li>{@link #LEADING LEADING}48* <li>{@link #TRAILING TRAILING}49* </ul>50* <p>51* For example, the following picture shows an applet using the flow52* layout manager (its default layout manager) to position three buttons:53* <p>54* <img src="doc-files/FlowLayout-1.gif"55* ALT="Graphic of Layout for Three Buttons"56* style="float:center; margin: 7px 10px;">57* <p>58* Here is the code for this applet:59*60* <hr><blockquote><pre>61* import java.awt.*;62* import java.applet.Applet;63*64* public class myButtons extends Applet {65* Button button1, button2, button3;66* public void init() {67* button1 = new Button("Ok");68* button2 = new Button("Open");69* button3 = new Button("Close");70* add(button1);71* add(button2);72* add(button3);73* }74* }75* </pre></blockquote><hr>76* <p>77* A flow layout lets each component assume its natural (preferred) size.78*79* @author Arthur van Hoff80* @author Sami Shaio81* @since JDK1.082* @see ComponentOrientation83*/84public class FlowLayout implements LayoutManager, java.io.Serializable {8586/**87* This value indicates that each row of components88* should be left-justified.89*/90public static final int LEFT = 0;9192/**93* This value indicates that each row of components94* should be centered.95*/96public static final int CENTER = 1;9798/**99* This value indicates that each row of components100* should be right-justified.101*/102public static final int RIGHT = 2;103104/**105* This value indicates that each row of components106* should be justified to the leading edge of the container's107* orientation, for example, to the left in left-to-right orientations.108*109* @see java.awt.Component#getComponentOrientation110* @see java.awt.ComponentOrientation111* @since 1.2112*/113public static final int LEADING = 3;114115/**116* This value indicates that each row of components117* should be justified to the trailing edge of the container's118* orientation, for example, to the right in left-to-right orientations.119*120* @see java.awt.Component#getComponentOrientation121* @see java.awt.ComponentOrientation122* @since 1.2123*/124public static final int TRAILING = 4;125126/**127* <code>align</code> is the property that determines128* how each row distributes empty space.129* It can be one of the following values:130* <ul>131* <li><code>LEFT</code>132* <li><code>RIGHT</code>133* <li><code>CENTER</code>134* </ul>135*136* @serial137* @see #getAlignment138* @see #setAlignment139*/140int align; // This is for 1.1 serialization compatibility141142/**143* <code>newAlign</code> is the property that determines144* how each row distributes empty space for the Java 2 platform,145* v1.2 and greater.146* It can be one of the following three values:147* <ul>148* <li><code>LEFT</code>149* <li><code>RIGHT</code>150* <li><code>CENTER</code>151* <li><code>LEADING</code>152* <li><code>TRAILING</code>153* </ul>154*155* @serial156* @since 1.2157* @see #getAlignment158* @see #setAlignment159*/160int newAlign; // This is the one we actually use161162/**163* The flow layout manager allows a seperation of164* components with gaps. The horizontal gap will165* specify the space between components and between166* the components and the borders of the167* <code>Container</code>.168*169* @serial170* @see #getHgap()171* @see #setHgap(int)172*/173int hgap;174175/**176* The flow layout manager allows a seperation of177* components with gaps. The vertical gap will178* specify the space between rows and between the179* the rows and the borders of the <code>Container</code>.180*181* @serial182* @see #getHgap()183* @see #setHgap(int)184*/185int vgap;186187/**188* If true, components will be aligned on their baseline.189*/190private boolean alignOnBaseline;191192/*193* JDK 1.1 serialVersionUID194*/195private static final long serialVersionUID = -7262534875583282631L;196197/**198* Constructs a new <code>FlowLayout</code> with a centered alignment and a199* default 5-unit horizontal and vertical gap.200*/201public FlowLayout() {202this(CENTER, 5, 5);203}204205/**206* Constructs a new <code>FlowLayout</code> with the specified207* alignment and a default 5-unit horizontal and vertical gap.208* The value of the alignment argument must be one of209* <code>FlowLayout.LEFT</code>, <code>FlowLayout.RIGHT</code>,210* <code>FlowLayout.CENTER</code>, <code>FlowLayout.LEADING</code>,211* or <code>FlowLayout.TRAILING</code>.212* @param align the alignment value213*/214public FlowLayout(int align) {215this(align, 5, 5);216}217218/**219* Creates a new flow layout manager with the indicated alignment220* and the indicated horizontal and vertical gaps.221* <p>222* The value of the alignment argument must be one of223* <code>FlowLayout.LEFT</code>, <code>FlowLayout.RIGHT</code>,224* <code>FlowLayout.CENTER</code>, <code>FlowLayout.LEADING</code>,225* or <code>FlowLayout.TRAILING</code>.226* @param align the alignment value227* @param hgap the horizontal gap between components228* and between the components and the229* borders of the <code>Container</code>230* @param vgap the vertical gap between components231* and between the components and the232* borders of the <code>Container</code>233*/234public FlowLayout(int align, int hgap, int vgap) {235this.hgap = hgap;236this.vgap = vgap;237setAlignment(align);238}239240/**241* Gets the alignment for this layout.242* Possible values are <code>FlowLayout.LEFT</code>,243* <code>FlowLayout.RIGHT</code>, <code>FlowLayout.CENTER</code>,244* <code>FlowLayout.LEADING</code>,245* or <code>FlowLayout.TRAILING</code>.246* @return the alignment value for this layout247* @see java.awt.FlowLayout#setAlignment248* @since JDK1.1249*/250public int getAlignment() {251return newAlign;252}253254/**255* Sets the alignment for this layout.256* Possible values are257* <ul>258* <li><code>FlowLayout.LEFT</code>259* <li><code>FlowLayout.RIGHT</code>260* <li><code>FlowLayout.CENTER</code>261* <li><code>FlowLayout.LEADING</code>262* <li><code>FlowLayout.TRAILING</code>263* </ul>264* @param align one of the alignment values shown above265* @see #getAlignment()266* @since JDK1.1267*/268public void setAlignment(int align) {269this.newAlign = align;270271// this.align is used only for serialization compatibility,272// so set it to a value compatible with the 1.1 version273// of the class274275switch (align) {276case LEADING:277this.align = LEFT;278break;279case TRAILING:280this.align = RIGHT;281break;282default:283this.align = align;284break;285}286}287288/**289* Gets the horizontal gap between components290* and between the components and the borders291* of the <code>Container</code>292*293* @return the horizontal gap between components294* and between the components and the borders295* of the <code>Container</code>296* @see java.awt.FlowLayout#setHgap297* @since JDK1.1298*/299public int getHgap() {300return hgap;301}302303/**304* Sets the horizontal gap between components and305* between the components and the borders of the306* <code>Container</code>.307*308* @param hgap the horizontal gap between components309* and between the components and the borders310* of the <code>Container</code>311* @see java.awt.FlowLayout#getHgap312* @since JDK1.1313*/314public void setHgap(int hgap) {315this.hgap = hgap;316}317318/**319* Gets the vertical gap between components and320* between the components and the borders of the321* <code>Container</code>.322*323* @return the vertical gap between components324* and between the components and the borders325* of the <code>Container</code>326* @see java.awt.FlowLayout#setVgap327* @since JDK1.1328*/329public int getVgap() {330return vgap;331}332333/**334* Sets the vertical gap between components and between335* the components and the borders of the <code>Container</code>.336*337* @param vgap the vertical gap between components338* and between the components and the borders339* of the <code>Container</code>340* @see java.awt.FlowLayout#getVgap341* @since JDK1.1342*/343public void setVgap(int vgap) {344this.vgap = vgap;345}346347/**348* Sets whether or not components should be vertically aligned along their349* baseline. Components that do not have a baseline will be centered.350* The default is false.351*352* @param alignOnBaseline whether or not components should be353* vertically aligned on their baseline354* @since 1.6355*/356public void setAlignOnBaseline(boolean alignOnBaseline) {357this.alignOnBaseline = alignOnBaseline;358}359360/**361* Returns true if components are to be vertically aligned along362* their baseline. The default is false.363*364* @return true if components are to be vertically aligned along365* their baseline366* @since 1.6367*/368public boolean getAlignOnBaseline() {369return alignOnBaseline;370}371372/**373* Adds the specified component to the layout.374* Not used by this class.375* @param name the name of the component376* @param comp the component to be added377*/378public void addLayoutComponent(String name, Component comp) {379}380381/**382* Removes the specified component from the layout.383* Not used by this class.384* @param comp the component to remove385* @see java.awt.Container#removeAll386*/387public void removeLayoutComponent(Component comp) {388}389390/**391* Returns the preferred dimensions for this layout given the392* <i>visible</i> components in the specified target container.393*394* @param target the container that needs to be laid out395* @return the preferred dimensions to lay out the396* subcomponents of the specified container397* @see Container398* @see #minimumLayoutSize399* @see java.awt.Container#getPreferredSize400*/401public Dimension preferredLayoutSize(Container target) {402synchronized (target.getTreeLock()) {403Dimension dim = new Dimension(0, 0);404int nmembers = target.getComponentCount();405boolean firstVisibleComponent = true;406boolean useBaseline = getAlignOnBaseline();407int maxAscent = 0;408int maxDescent = 0;409410for (int i = 0 ; i < nmembers ; i++) {411Component m = target.getComponent(i);412if (m.isVisible()) {413Dimension d = m.getPreferredSize();414dim.height = Math.max(dim.height, d.height);415if (firstVisibleComponent) {416firstVisibleComponent = false;417} else {418dim.width += hgap;419}420dim.width += d.width;421if (useBaseline) {422int baseline = m.getBaseline(d.width, d.height);423if (baseline >= 0) {424maxAscent = Math.max(maxAscent, baseline);425maxDescent = Math.max(maxDescent, d.height - baseline);426}427}428}429}430if (useBaseline) {431dim.height = Math.max(maxAscent + maxDescent, dim.height);432}433Insets insets = target.getInsets();434dim.width += insets.left + insets.right + hgap*2;435dim.height += insets.top + insets.bottom + vgap*2;436return dim;437}438}439440/**441* Returns the minimum dimensions needed to layout the <i>visible</i>442* components contained in the specified target container.443* @param target the container that needs to be laid out444* @return the minimum dimensions to lay out the445* subcomponents of the specified container446* @see #preferredLayoutSize447* @see java.awt.Container448* @see java.awt.Container#doLayout449*/450public Dimension minimumLayoutSize(Container target) {451synchronized (target.getTreeLock()) {452boolean useBaseline = getAlignOnBaseline();453Dimension dim = new Dimension(0, 0);454int nmembers = target.getComponentCount();455int maxAscent = 0;456int maxDescent = 0;457boolean firstVisibleComponent = true;458459for (int i = 0 ; i < nmembers ; i++) {460Component m = target.getComponent(i);461if (m.visible) {462Dimension d = m.getMinimumSize();463dim.height = Math.max(dim.height, d.height);464if (firstVisibleComponent) {465firstVisibleComponent = false;466} else {467dim.width += hgap;468}469dim.width += d.width;470if (useBaseline) {471int baseline = m.getBaseline(d.width, d.height);472if (baseline >= 0) {473maxAscent = Math.max(maxAscent, baseline);474maxDescent = Math.max(maxDescent,475dim.height - baseline);476}477}478}479}480481if (useBaseline) {482dim.height = Math.max(maxAscent + maxDescent, dim.height);483}484485Insets insets = target.getInsets();486dim.width += insets.left + insets.right + hgap*2;487dim.height += insets.top + insets.bottom + vgap*2;488return dim;489490491492493494}495}496497/**498* Centers the elements in the specified row, if there is any slack.499* @param target the component which needs to be moved500* @param x the x coordinate501* @param y the y coordinate502* @param width the width dimensions503* @param height the height dimensions504* @param rowStart the beginning of the row505* @param rowEnd the the ending of the row506* @param useBaseline Whether or not to align on baseline.507* @param ascent Ascent for the components. This is only valid if508* useBaseline is true.509* @param descent Ascent for the components. This is only valid if510* useBaseline is true.511* @return actual row height512*/513private int moveComponents(Container target, int x, int y, int width, int height,514int rowStart, int rowEnd, boolean ltr,515boolean useBaseline, int[] ascent,516int[] descent) {517switch (newAlign) {518case LEFT:519x += ltr ? 0 : width;520break;521case CENTER:522x += width / 2;523break;524case RIGHT:525x += ltr ? width : 0;526break;527case LEADING:528break;529case TRAILING:530x += width;531break;532}533int maxAscent = 0;534int nonbaselineHeight = 0;535int baselineOffset = 0;536if (useBaseline) {537int maxDescent = 0;538for (int i = rowStart ; i < rowEnd ; i++) {539Component m = target.getComponent(i);540if (m.visible) {541if (ascent[i] >= 0) {542maxAscent = Math.max(maxAscent, ascent[i]);543maxDescent = Math.max(maxDescent, descent[i]);544}545else {546nonbaselineHeight = Math.max(m.getHeight(),547nonbaselineHeight);548}549}550}551height = Math.max(maxAscent + maxDescent, nonbaselineHeight);552baselineOffset = (height - maxAscent - maxDescent) / 2;553}554for (int i = rowStart ; i < rowEnd ; i++) {555Component m = target.getComponent(i);556if (m.isVisible()) {557int cy;558if (useBaseline && ascent[i] >= 0) {559cy = y + baselineOffset + maxAscent - ascent[i];560}561else {562cy = y + (height - m.height) / 2;563}564if (ltr) {565m.setLocation(x, cy);566} else {567m.setLocation(target.width - x - m.width, cy);568}569x += m.width + hgap;570}571}572return height;573}574575/**576* Lays out the container. This method lets each577* <i>visible</i> component take578* its preferred size by reshaping the components in the579* target container in order to satisfy the alignment of580* this <code>FlowLayout</code> object.581*582* @param target the specified component being laid out583* @see Container584* @see java.awt.Container#doLayout585*/586public void layoutContainer(Container target) {587synchronized (target.getTreeLock()) {588Insets insets = target.getInsets();589int maxwidth = target.width - (insets.left + insets.right + hgap*2);590int nmembers = target.getComponentCount();591int x = 0, y = insets.top + vgap;592int rowh = 0, start = 0;593594boolean ltr = target.getComponentOrientation().isLeftToRight();595596boolean useBaseline = getAlignOnBaseline();597int[] ascent = null;598int[] descent = null;599600if (useBaseline) {601ascent = new int[nmembers];602descent = new int[nmembers];603}604605for (int i = 0 ; i < nmembers ; i++) {606Component m = target.getComponent(i);607if (m.isVisible()) {608Dimension d = m.getPreferredSize();609m.setSize(d.width, d.height);610611if (useBaseline) {612int baseline = m.getBaseline(d.width, d.height);613if (baseline >= 0) {614ascent[i] = baseline;615descent[i] = d.height - baseline;616}617else {618ascent[i] = -1;619}620}621if ((x == 0) || ((x + d.width) <= maxwidth)) {622if (x > 0) {623x += hgap;624}625x += d.width;626rowh = Math.max(rowh, d.height);627} else {628rowh = moveComponents(target, insets.left + hgap, y,629maxwidth - x, rowh, start, i, ltr,630useBaseline, ascent, descent);631x = d.width;632y += vgap + rowh;633rowh = d.height;634start = i;635}636}637}638moveComponents(target, insets.left + hgap, y, maxwidth - x, rowh,639start, nmembers, ltr, useBaseline, ascent, descent);640}641}642643//644// the internal serial version which says which version was written645// - 0 (default) for versions before the Java 2 platform, v1.2646// - 1 for version >= Java 2 platform v1.2, which includes "newAlign" field647//648private static final int currentSerialVersion = 1;649/**650* This represent the <code>currentSerialVersion</code>651* which is bein used. It will be one of two values :652* <code>0</code> versions before Java 2 platform v1.2..653* <code>1</code> versions after Java 2 platform v1.2..654*655* @serial656* @since 1.2657*/658private int serialVersionOnStream = currentSerialVersion;659660/**661* Reads this object out of a serialization stream, handling662* objects written by older versions of the class that didn't contain all663* of the fields we use now..664*/665private void readObject(ObjectInputStream stream)666throws IOException, ClassNotFoundException667{668stream.defaultReadObject();669670if (serialVersionOnStream < 1) {671// "newAlign" field wasn't present, so use the old "align" field.672setAlignment(this.align);673}674serialVersionOnStream = currentSerialVersion;675}676677/**678* Returns a string representation of this <code>FlowLayout</code>679* object and its values.680* @return a string representation of this layout681*/682public String toString() {683String str = "";684switch (align) {685case LEFT: str = ",align=left"; break;686case CENTER: str = ",align=center"; break;687case RIGHT: str = ",align=right"; break;688case LEADING: str = ",align=leading"; break;689case TRAILING: str = ",align=trailing"; break;690}691return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap + str + "]";692}693694695}696697698