Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/java/awt/CardLayout.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*/2425package java.awt;2627import java.util.Hashtable;28import java.util.Vector;29import java.util.Enumeration;3031import java.io.Serializable;32import java.io.ObjectInputStream;33import java.io.ObjectOutputStream;34import java.io.ObjectStreamField;35import java.io.IOException;3637/**38* A <code>CardLayout</code> object is a layout manager for a39* container. It treats each component in the container as a card.40* Only one card is visible at a time, and the container acts as41* a stack of cards. The first component added to a42* <code>CardLayout</code> object is the visible component when the43* container is first displayed.44* <p>45* The ordering of cards is determined by the container's own internal46* ordering of its component objects. <code>CardLayout</code>47* defines a set of methods that allow an application to flip48* through these cards sequentially, or to show a specified card.49* The {@link CardLayout#addLayoutComponent}50* method can be used to associate a string identifier with a given card51* for fast random access.52*53* @author Arthur van Hoff54* @see java.awt.Container55* @since JDK1.056*/5758public class CardLayout implements LayoutManager2,59Serializable {6061private static final long serialVersionUID = -4328196481005934313L;6263/*64* This creates a Vector to store associated65* pairs of components and their names.66* @see java.util.Vector67*/68Vector<Card> vector = new Vector<>();6970/*71* A pair of Component and String that represents its name.72*/73class Card implements Serializable {74static final long serialVersionUID = 6640330810709497518L;75public String name;76public Component comp;77public Card(String cardName, Component cardComponent) {78name = cardName;79comp = cardComponent;80}81}8283/*84* Index of Component currently displayed by CardLayout.85*/86int currentCard = 0;878889/*90* A cards horizontal Layout gap (inset). It specifies91* the space between the left and right edges of a92* container and the current component.93* This should be a non negative Integer.94* @see getHgap()95* @see setHgap()96*/97int hgap;9899/*100* A cards vertical Layout gap (inset). It specifies101* the space between the top and bottom edges of a102* container and the current component.103* This should be a non negative Integer.104* @see getVgap()105* @see setVgap()106*/107int vgap;108109/**110* @serialField tab Hashtable111* deprectated, for forward compatibility only112* @serialField hgap int113* @serialField vgap int114* @serialField vector Vector115* @serialField currentCard int116*/117private static final ObjectStreamField[] serialPersistentFields = {118new ObjectStreamField("tab", Hashtable.class),119new ObjectStreamField("hgap", Integer.TYPE),120new ObjectStreamField("vgap", Integer.TYPE),121new ObjectStreamField("vector", Vector.class),122new ObjectStreamField("currentCard", Integer.TYPE)123};124125/**126* Creates a new card layout with gaps of size zero.127*/128public CardLayout() {129this(0, 0);130}131132/**133* Creates a new card layout with the specified horizontal and134* vertical gaps. The horizontal gaps are placed at the left and135* right edges. The vertical gaps are placed at the top and bottom136* edges.137* @param hgap the horizontal gap.138* @param vgap the vertical gap.139*/140public CardLayout(int hgap, int vgap) {141this.hgap = hgap;142this.vgap = vgap;143}144145/**146* Gets the horizontal gap between components.147* @return the horizontal gap between components.148* @see java.awt.CardLayout#setHgap(int)149* @see java.awt.CardLayout#getVgap()150* @since JDK1.1151*/152public int getHgap() {153return hgap;154}155156/**157* Sets the horizontal gap between components.158* @param hgap the horizontal gap between components.159* @see java.awt.CardLayout#getHgap()160* @see java.awt.CardLayout#setVgap(int)161* @since JDK1.1162*/163public void setHgap(int hgap) {164this.hgap = hgap;165}166167/**168* Gets the vertical gap between components.169* @return the vertical gap between components.170* @see java.awt.CardLayout#setVgap(int)171* @see java.awt.CardLayout#getHgap()172*/173public int getVgap() {174return vgap;175}176177/**178* Sets the vertical gap between components.179* @param vgap the vertical gap between components.180* @see java.awt.CardLayout#getVgap()181* @see java.awt.CardLayout#setHgap(int)182* @since JDK1.1183*/184public void setVgap(int vgap) {185this.vgap = vgap;186}187188/**189* Adds the specified component to this card layout's internal190* table of names. The object specified by <code>constraints</code>191* must be a string. The card layout stores this string as a key-value192* pair that can be used for random access to a particular card.193* By calling the <code>show</code> method, an application can194* display the component with the specified name.195* @param comp the component to be added.196* @param constraints a tag that identifies a particular197* card in the layout.198* @see java.awt.CardLayout#show(java.awt.Container, java.lang.String)199* @exception IllegalArgumentException if the constraint is not a string.200*/201public void addLayoutComponent(Component comp, Object constraints) {202synchronized (comp.getTreeLock()) {203if (constraints == null){204constraints = "";205}206if (constraints instanceof String) {207addLayoutComponent((String)constraints, comp);208} else {209throw new IllegalArgumentException("cannot add to layout: constraint must be a string");210}211}212}213214/**215* @deprecated replaced by216* <code>addLayoutComponent(Component, Object)</code>.217*/218@Deprecated219public void addLayoutComponent(String name, Component comp) {220synchronized (comp.getTreeLock()) {221if (!vector.isEmpty()) {222comp.setVisible(false);223}224for (int i=0; i < vector.size(); i++) {225if (((Card)vector.get(i)).name.equals(name)) {226((Card)vector.get(i)).comp = comp;227return;228}229}230vector.add(new Card(name, comp));231}232}233234/**235* Removes the specified component from the layout.236* If the card was visible on top, the next card underneath it is shown.237* @param comp the component to be removed.238* @see java.awt.Container#remove(java.awt.Component)239* @see java.awt.Container#removeAll()240*/241public void removeLayoutComponent(Component comp) {242synchronized (comp.getTreeLock()) {243for (int i = 0; i < vector.size(); i++) {244if (((Card)vector.get(i)).comp == comp) {245// if we remove current component we should show next one246if (comp.isVisible() && (comp.getParent() != null)) {247next(comp.getParent());248}249250vector.remove(i);251252// correct currentCard if this is necessary253if (currentCard > i) {254currentCard--;255}256break;257}258}259}260}261262/**263* Determines the preferred size of the container argument using264* this card layout.265* @param parent the parent container in which to do the layout266* @return the preferred dimensions to lay out the subcomponents267* of the specified container268* @see java.awt.Container#getPreferredSize269* @see java.awt.CardLayout#minimumLayoutSize270*/271public Dimension preferredLayoutSize(Container parent) {272synchronized (parent.getTreeLock()) {273Insets insets = parent.getInsets();274int ncomponents = parent.getComponentCount();275int w = 0;276int h = 0;277278for (int i = 0 ; i < ncomponents ; i++) {279Component comp = parent.getComponent(i);280Dimension d = comp.getPreferredSize();281if (d.width > w) {282w = d.width;283}284if (d.height > h) {285h = d.height;286}287}288return new Dimension(insets.left + insets.right + w + hgap*2,289insets.top + insets.bottom + h + vgap*2);290}291}292293/**294* Calculates the minimum size for the specified panel.295* @param parent the parent container in which to do the layout296* @return the minimum dimensions required to lay out the297* subcomponents of the specified container298* @see java.awt.Container#doLayout299* @see java.awt.CardLayout#preferredLayoutSize300*/301public Dimension minimumLayoutSize(Container parent) {302synchronized (parent.getTreeLock()) {303Insets insets = parent.getInsets();304int ncomponents = parent.getComponentCount();305int w = 0;306int h = 0;307308for (int i = 0 ; i < ncomponents ; i++) {309Component comp = parent.getComponent(i);310Dimension d = comp.getMinimumSize();311if (d.width > w) {312w = d.width;313}314if (d.height > h) {315h = d.height;316}317}318return new Dimension(insets.left + insets.right + w + hgap*2,319insets.top + insets.bottom + h + vgap*2);320}321}322323/**324* Returns the maximum dimensions for this layout given the components325* in the specified target container.326* @param target the component which needs to be laid out327* @see Container328* @see #minimumLayoutSize329* @see #preferredLayoutSize330*/331public Dimension maximumLayoutSize(Container target) {332return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);333}334335/**336* Returns the alignment along the x axis. This specifies how337* the component would like to be aligned relative to other338* components. The value should be a number between 0 and 1339* where 0 represents alignment along the origin, 1 is aligned340* the furthest away from the origin, 0.5 is centered, etc.341*/342public float getLayoutAlignmentX(Container parent) {343return 0.5f;344}345346/**347* Returns the alignment along the y axis. This specifies how348* the component would like to be aligned relative to other349* components. The value should be a number between 0 and 1350* where 0 represents alignment along the origin, 1 is aligned351* the furthest away from the origin, 0.5 is centered, etc.352*/353public float getLayoutAlignmentY(Container parent) {354return 0.5f;355}356357/**358* Invalidates the layout, indicating that if the layout manager359* has cached information it should be discarded.360*/361public void invalidateLayout(Container target) {362}363364/**365* Lays out the specified container using this card layout.366* <p>367* Each component in the <code>parent</code> container is reshaped368* to be the size of the container, minus space for surrounding369* insets, horizontal gaps, and vertical gaps.370*371* @param parent the parent container in which to do the layout372* @see java.awt.Container#doLayout373*/374public void layoutContainer(Container parent) {375synchronized (parent.getTreeLock()) {376Insets insets = parent.getInsets();377int ncomponents = parent.getComponentCount();378Component comp = null;379boolean currentFound = false;380381for (int i = 0 ; i < ncomponents ; i++) {382comp = parent.getComponent(i);383comp.setBounds(hgap + insets.left, vgap + insets.top,384parent.width - (hgap*2 + insets.left + insets.right),385parent.height - (vgap*2 + insets.top + insets.bottom));386if (comp.isVisible()) {387currentFound = true;388}389}390391if (!currentFound && ncomponents > 0) {392parent.getComponent(0).setVisible(true);393}394}395}396397/**398* Make sure that the Container really has a CardLayout installed.399* Otherwise havoc can ensue!400*/401void checkLayout(Container parent) {402if (parent.getLayout() != this) {403throw new IllegalArgumentException("wrong parent for CardLayout");404}405}406407/**408* Flips to the first card of the container.409* @param parent the parent container in which to do the layout410* @see java.awt.CardLayout#last411*/412public void first(Container parent) {413synchronized (parent.getTreeLock()) {414checkLayout(parent);415int ncomponents = parent.getComponentCount();416for (int i = 0 ; i < ncomponents ; i++) {417Component comp = parent.getComponent(i);418if (comp.isVisible()) {419comp.setVisible(false);420break;421}422}423if (ncomponents > 0) {424currentCard = 0;425parent.getComponent(0).setVisible(true);426parent.validate();427}428}429}430431/**432* Flips to the next card of the specified container. If the433* currently visible card is the last one, this method flips to the434* first card in the layout.435* @param parent the parent container in which to do the layout436* @see java.awt.CardLayout#previous437*/438public void next(Container parent) {439synchronized (parent.getTreeLock()) {440checkLayout(parent);441int ncomponents = parent.getComponentCount();442for (int i = 0 ; i < ncomponents ; i++) {443Component comp = parent.getComponent(i);444if (comp.isVisible()) {445comp.setVisible(false);446currentCard = (i + 1) % ncomponents;447comp = parent.getComponent(currentCard);448comp.setVisible(true);449parent.validate();450return;451}452}453showDefaultComponent(parent);454}455}456457/**458* Flips to the previous card of the specified container. If the459* currently visible card is the first one, this method flips to the460* last card in the layout.461* @param parent the parent container in which to do the layout462* @see java.awt.CardLayout#next463*/464public void previous(Container parent) {465synchronized (parent.getTreeLock()) {466checkLayout(parent);467int ncomponents = parent.getComponentCount();468for (int i = 0 ; i < ncomponents ; i++) {469Component comp = parent.getComponent(i);470if (comp.isVisible()) {471comp.setVisible(false);472currentCard = ((i > 0) ? i-1 : ncomponents-1);473comp = parent.getComponent(currentCard);474comp.setVisible(true);475parent.validate();476return;477}478}479showDefaultComponent(parent);480}481}482483void showDefaultComponent(Container parent) {484if (parent.getComponentCount() > 0) {485currentCard = 0;486parent.getComponent(0).setVisible(true);487parent.validate();488}489}490491/**492* Flips to the last card of the container.493* @param parent the parent container in which to do the layout494* @see java.awt.CardLayout#first495*/496public void last(Container parent) {497synchronized (parent.getTreeLock()) {498checkLayout(parent);499int ncomponents = parent.getComponentCount();500for (int i = 0 ; i < ncomponents ; i++) {501Component comp = parent.getComponent(i);502if (comp.isVisible()) {503comp.setVisible(false);504break;505}506}507if (ncomponents > 0) {508currentCard = ncomponents - 1;509parent.getComponent(currentCard).setVisible(true);510parent.validate();511}512}513}514515/**516* Flips to the component that was added to this layout with the517* specified <code>name</code>, using <code>addLayoutComponent</code>.518* If no such component exists, then nothing happens.519* @param parent the parent container in which to do the layout520* @param name the component name521* @see java.awt.CardLayout#addLayoutComponent(java.awt.Component, java.lang.Object)522*/523public void show(Container parent, String name) {524synchronized (parent.getTreeLock()) {525checkLayout(parent);526Component next = null;527int ncomponents = vector.size();528for (int i = 0; i < ncomponents; i++) {529Card card = (Card)vector.get(i);530if (card.name.equals(name)) {531next = card.comp;532currentCard = i;533break;534}535}536if ((next != null) && !next.isVisible()) {537ncomponents = parent.getComponentCount();538for (int i = 0; i < ncomponents; i++) {539Component comp = parent.getComponent(i);540if (comp.isVisible()) {541comp.setVisible(false);542break;543}544}545next.setVisible(true);546parent.validate();547}548}549}550551/**552* Returns a string representation of the state of this card layout.553* @return a string representation of this card layout.554*/555public String toString() {556return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap + "]";557}558559/**560* Reads serializable fields from stream.561*/562private void readObject(ObjectInputStream s)563throws ClassNotFoundException, IOException564{565ObjectInputStream.GetField f = s.readFields();566567hgap = f.get("hgap", 0);568vgap = f.get("vgap", 0);569570if (f.defaulted("vector")) {571// pre-1.4 stream572Hashtable<String, Component> tab = (Hashtable)f.get("tab", null);573vector = new Vector<>();574if (tab != null && !tab.isEmpty()) {575for (Enumeration<String> e = tab.keys() ; e.hasMoreElements() ; ) {576String key = (String)e.nextElement();577Component comp = (Component)tab.get(key);578vector.add(new Card(key, comp));579if (comp.isVisible()) {580currentCard = vector.size() - 1;581}582}583}584} else {585vector = (Vector)f.get("vector", null);586currentCard = f.get("currentCard", 0);587}588}589590/**591* Writes serializable fields to stream.592*/593private void writeObject(ObjectOutputStream s)594throws IOException595{596Hashtable<String, Component> tab = new Hashtable<>();597int ncomponents = vector.size();598for (int i = 0; i < ncomponents; i++) {599Card card = (Card)vector.get(i);600tab.put(card.name, card.comp);601}602603ObjectOutputStream.PutField f = s.putFields();604f.put("hgap", hgap);605f.put("vgap", vgap);606f.put("vector", vector);607f.put("currentCard", currentCard);608f.put("tab", tab);609s.writeFields();610}611}612613614