0N/A/*
2362N/A * Copyright (c) 1995, 2006, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage java.awt;
0N/A
0N/Aimport java.util.Hashtable;
0N/Aimport java.util.Vector;
0N/Aimport java.util.Enumeration;
0N/A
0N/Aimport java.io.Serializable;
0N/Aimport java.io.ObjectInputStream;
0N/Aimport java.io.ObjectOutputStream;
0N/Aimport java.io.ObjectStreamField;
0N/Aimport java.io.IOException;
0N/A
0N/A/**
0N/A * A <code>CardLayout</code> object is a layout manager for a
0N/A * container. It treats each component in the container as a card.
0N/A * Only one card is visible at a time, and the container acts as
0N/A * a stack of cards. The first component added to a
0N/A * <code>CardLayout</code> object is the visible component when the
0N/A * container is first displayed.
0N/A * <p>
0N/A * The ordering of cards is determined by the container's own internal
0N/A * ordering of its component objects. <code>CardLayout</code>
0N/A * defines a set of methods that allow an application to flip
0N/A * through these cards sequentially, or to show a specified card.
0N/A * The {@link CardLayout#addLayoutComponent}
0N/A * method can be used to associate a string identifier with a given card
0N/A * for fast random access.
0N/A *
0N/A * @author Arthur van Hoff
0N/A * @see java.awt.Container
0N/A * @since JDK1.0
0N/A */
0N/A
0N/Apublic class CardLayout implements LayoutManager2,
0N/A Serializable {
0N/A
0N/A private static final long serialVersionUID = -4328196481005934313L;
0N/A
0N/A /*
0N/A * This creates a Vector to store associated
0N/A * pairs of components and their names.
0N/A * @see java.util.Vector
0N/A */
0N/A Vector vector = new Vector();
0N/A
0N/A /*
0N/A * A pair of Component and String that represents its name.
0N/A */
0N/A class Card implements Serializable {
0N/A static final long serialVersionUID = 6640330810709497518L;
0N/A public String name;
0N/A public Component comp;
0N/A public Card(String cardName, Component cardComponent) {
0N/A name = cardName;
0N/A comp = cardComponent;
0N/A }
0N/A }
0N/A
0N/A /*
0N/A * Index of Component currently displayed by CardLayout.
0N/A */
0N/A int currentCard = 0;
0N/A
0N/A
0N/A /*
0N/A * A cards horizontal Layout gap (inset). It specifies
0N/A * the space between the left and right edges of a
0N/A * container and the current component.
0N/A * This should be a non negative Integer.
0N/A * @see getHgap()
0N/A * @see setHgap()
0N/A */
0N/A int hgap;
0N/A
0N/A /*
0N/A * A cards vertical Layout gap (inset). It specifies
0N/A * the space between the top and bottom edges of a
0N/A * container and the current component.
0N/A * This should be a non negative Integer.
0N/A * @see getVgap()
0N/A * @see setVgap()
0N/A */
0N/A int vgap;
0N/A
0N/A /**
0N/A * @serialField tab Hashtable
0N/A * deprectated, for forward compatibility only
0N/A * @serialField hgap int
0N/A * @serialField vgap int
0N/A * @serialField vector Vector
0N/A * @serialField currentCard int
0N/A */
0N/A private static final ObjectStreamField[] serialPersistentFields = {
0N/A new ObjectStreamField("tab", Hashtable.class),
0N/A new ObjectStreamField("hgap", Integer.TYPE),
0N/A new ObjectStreamField("vgap", Integer.TYPE),
0N/A new ObjectStreamField("vector", Vector.class),
0N/A new ObjectStreamField("currentCard", Integer.TYPE)
0N/A };
0N/A
0N/A /**
0N/A * Creates a new card layout with gaps of size zero.
0N/A */
0N/A public CardLayout() {
0N/A this(0, 0);
0N/A }
0N/A
0N/A /**
0N/A * Creates a new card layout with the specified horizontal and
0N/A * vertical gaps. The horizontal gaps are placed at the left and
0N/A * right edges. The vertical gaps are placed at the top and bottom
0N/A * edges.
0N/A * @param hgap the horizontal gap.
0N/A * @param vgap the vertical gap.
0N/A */
0N/A public CardLayout(int hgap, int vgap) {
0N/A this.hgap = hgap;
0N/A this.vgap = vgap;
0N/A }
0N/A
0N/A /**
0N/A * Gets the horizontal gap between components.
0N/A * @return the horizontal gap between components.
0N/A * @see java.awt.CardLayout#setHgap(int)
0N/A * @see java.awt.CardLayout#getVgap()
0N/A * @since JDK1.1
0N/A */
0N/A public int getHgap() {
0N/A return hgap;
0N/A }
0N/A
0N/A /**
0N/A * Sets the horizontal gap between components.
0N/A * @param hgap the horizontal gap between components.
0N/A * @see java.awt.CardLayout#getHgap()
0N/A * @see java.awt.CardLayout#setVgap(int)
0N/A * @since JDK1.1
0N/A */
0N/A public void setHgap(int hgap) {
0N/A this.hgap = hgap;
0N/A }
0N/A
0N/A /**
0N/A * Gets the vertical gap between components.
0N/A * @return the vertical gap between components.
0N/A * @see java.awt.CardLayout#setVgap(int)
0N/A * @see java.awt.CardLayout#getHgap()
0N/A */
0N/A public int getVgap() {
0N/A return vgap;
0N/A }
0N/A
0N/A /**
0N/A * Sets the vertical gap between components.
0N/A * @param vgap the vertical gap between components.
0N/A * @see java.awt.CardLayout#getVgap()
0N/A * @see java.awt.CardLayout#setHgap(int)
0N/A * @since JDK1.1
0N/A */
0N/A public void setVgap(int vgap) {
0N/A this.vgap = vgap;
0N/A }
0N/A
0N/A /**
0N/A * Adds the specified component to this card layout's internal
0N/A * table of names. The object specified by <code>constraints</code>
0N/A * must be a string. The card layout stores this string as a key-value
0N/A * pair that can be used for random access to a particular card.
0N/A * By calling the <code>show</code> method, an application can
0N/A * display the component with the specified name.
0N/A * @param comp the component to be added.
0N/A * @param constraints a tag that identifies a particular
0N/A * card in the layout.
0N/A * @see java.awt.CardLayout#show(java.awt.Container, java.lang.String)
0N/A * @exception IllegalArgumentException if the constraint is not a string.
0N/A */
0N/A public void addLayoutComponent(Component comp, Object constraints) {
0N/A synchronized (comp.getTreeLock()) {
0N/A if (constraints == null){
0N/A constraints = "";
0N/A }
0N/A if (constraints instanceof String) {
0N/A addLayoutComponent((String)constraints, comp);
0N/A } else {
0N/A throw new IllegalArgumentException("cannot add to layout: constraint must be a string");
0N/A }
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * @deprecated replaced by
0N/A * <code>addLayoutComponent(Component, Object)</code>.
0N/A */
0N/A @Deprecated
0N/A public void addLayoutComponent(String name, Component comp) {
0N/A synchronized (comp.getTreeLock()) {
0N/A if (!vector.isEmpty()) {
0N/A comp.setVisible(false);
0N/A }
0N/A for (int i=0; i < vector.size(); i++) {
0N/A if (((Card)vector.get(i)).name.equals(name)) {
0N/A ((Card)vector.get(i)).comp = comp;
0N/A return;
0N/A }
0N/A }
0N/A vector.add(new Card(name, comp));
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Removes the specified component from the layout.
0N/A * If the card was visible on top, the next card underneath it is shown.
0N/A * @param comp the component to be removed.
0N/A * @see java.awt.Container#remove(java.awt.Component)
0N/A * @see java.awt.Container#removeAll()
0N/A */
0N/A public void removeLayoutComponent(Component comp) {
0N/A synchronized (comp.getTreeLock()) {
0N/A for (int i = 0; i < vector.size(); i++) {
0N/A if (((Card)vector.get(i)).comp == comp) {
0N/A // if we remove current component we should show next one
0N/A if (comp.isVisible() && (comp.getParent() != null)) {
0N/A next(comp.getParent());
0N/A }
0N/A
0N/A vector.remove(i);
0N/A
0N/A // correct currentCard if this is necessary
0N/A if (currentCard > i) {
0N/A currentCard--;
0N/A }
0N/A break;
0N/A }
0N/A }
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Determines the preferred size of the container argument using
0N/A * this card layout.
0N/A * @param parent the parent container in which to do the layout
0N/A * @return the preferred dimensions to lay out the subcomponents
0N/A * of the specified container
0N/A * @see java.awt.Container#getPreferredSize
0N/A * @see java.awt.CardLayout#minimumLayoutSize
0N/A */
0N/A public Dimension preferredLayoutSize(Container parent) {
0N/A synchronized (parent.getTreeLock()) {
0N/A Insets insets = parent.getInsets();
0N/A int ncomponents = parent.getComponentCount();
0N/A int w = 0;
0N/A int h = 0;
0N/A
0N/A for (int i = 0 ; i < ncomponents ; i++) {
0N/A Component comp = parent.getComponent(i);
0N/A Dimension d = comp.getPreferredSize();
0N/A if (d.width > w) {
0N/A w = d.width;
0N/A }
0N/A if (d.height > h) {
0N/A h = d.height;
0N/A }
0N/A }
0N/A return new Dimension(insets.left + insets.right + w + hgap*2,
0N/A insets.top + insets.bottom + h + vgap*2);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Calculates the minimum size for the specified panel.
0N/A * @param parent the parent container in which to do the layout
0N/A * @return the minimum dimensions required to lay out the
0N/A * subcomponents of the specified container
0N/A * @see java.awt.Container#doLayout
0N/A * @see java.awt.CardLayout#preferredLayoutSize
0N/A */
0N/A public Dimension minimumLayoutSize(Container parent) {
0N/A synchronized (parent.getTreeLock()) {
0N/A Insets insets = parent.getInsets();
0N/A int ncomponents = parent.getComponentCount();
0N/A int w = 0;
0N/A int h = 0;
0N/A
0N/A for (int i = 0 ; i < ncomponents ; i++) {
0N/A Component comp = parent.getComponent(i);
0N/A Dimension d = comp.getMinimumSize();
0N/A if (d.width > w) {
0N/A w = d.width;
0N/A }
0N/A if (d.height > h) {
0N/A h = d.height;
0N/A }
0N/A }
0N/A return new Dimension(insets.left + insets.right + w + hgap*2,
0N/A insets.top + insets.bottom + h + vgap*2);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Returns the maximum dimensions for this layout given the components
0N/A * in the specified target container.
0N/A * @param target the component which needs to be laid out
0N/A * @see Container
0N/A * @see #minimumLayoutSize
0N/A * @see #preferredLayoutSize
0N/A */
0N/A public Dimension maximumLayoutSize(Container target) {
0N/A return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
0N/A }
0N/A
0N/A /**
0N/A * Returns the alignment along the x axis. This specifies how
0N/A * the component would like to be aligned relative to other
0N/A * components. The value should be a number between 0 and 1
0N/A * where 0 represents alignment along the origin, 1 is aligned
0N/A * the furthest away from the origin, 0.5 is centered, etc.
0N/A */
0N/A public float getLayoutAlignmentX(Container parent) {
0N/A return 0.5f;
0N/A }
0N/A
0N/A /**
0N/A * Returns the alignment along the y axis. This specifies how
0N/A * the component would like to be aligned relative to other
0N/A * components. The value should be a number between 0 and 1
0N/A * where 0 represents alignment along the origin, 1 is aligned
0N/A * the furthest away from the origin, 0.5 is centered, etc.
0N/A */
0N/A public float getLayoutAlignmentY(Container parent) {
0N/A return 0.5f;
0N/A }
0N/A
0N/A /**
0N/A * Invalidates the layout, indicating that if the layout manager
0N/A * has cached information it should be discarded.
0N/A */
0N/A public void invalidateLayout(Container target) {
0N/A }
0N/A
0N/A /**
0N/A * Lays out the specified container using this card layout.
0N/A * <p>
0N/A * Each component in the <code>parent</code> container is reshaped
0N/A * to be the size of the container, minus space for surrounding
0N/A * insets, horizontal gaps, and vertical gaps.
0N/A *
0N/A * @param parent the parent container in which to do the layout
0N/A * @see java.awt.Container#doLayout
0N/A */
0N/A public void layoutContainer(Container parent) {
0N/A synchronized (parent.getTreeLock()) {
0N/A Insets insets = parent.getInsets();
0N/A int ncomponents = parent.getComponentCount();
0N/A Component comp = null;
0N/A boolean currentFound = false;
0N/A
0N/A for (int i = 0 ; i < ncomponents ; i++) {
0N/A comp = parent.getComponent(i);
0N/A comp.setBounds(hgap + insets.left, vgap + insets.top,
0N/A parent.width - (hgap*2 + insets.left + insets.right),
0N/A parent.height - (vgap*2 + insets.top + insets.bottom));
0N/A if (comp.isVisible()) {
0N/A currentFound = true;
0N/A }
0N/A }
0N/A
0N/A if (!currentFound && ncomponents > 0) {
0N/A parent.getComponent(0).setVisible(true);
0N/A }
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Make sure that the Container really has a CardLayout installed.
0N/A * Otherwise havoc can ensue!
0N/A */
0N/A void checkLayout(Container parent) {
0N/A if (parent.getLayout() != this) {
0N/A throw new IllegalArgumentException("wrong parent for CardLayout");
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Flips to the first card of the container.
0N/A * @param parent the parent container in which to do the layout
0N/A * @see java.awt.CardLayout#last
0N/A */
0N/A public void first(Container parent) {
0N/A synchronized (parent.getTreeLock()) {
0N/A checkLayout(parent);
0N/A int ncomponents = parent.getComponentCount();
0N/A for (int i = 0 ; i < ncomponents ; i++) {
0N/A Component comp = parent.getComponent(i);
0N/A if (comp.isVisible()) {
0N/A comp.setVisible(false);
0N/A break;
0N/A }
0N/A }
0N/A if (ncomponents > 0) {
0N/A currentCard = 0;
0N/A parent.getComponent(0).setVisible(true);
0N/A parent.validate();
0N/A }
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Flips to the next card of the specified container. If the
0N/A * currently visible card is the last one, this method flips to the
0N/A * first card in the layout.
0N/A * @param parent the parent container in which to do the layout
0N/A * @see java.awt.CardLayout#previous
0N/A */
0N/A public void next(Container parent) {
0N/A synchronized (parent.getTreeLock()) {
0N/A checkLayout(parent);
0N/A int ncomponents = parent.getComponentCount();
0N/A for (int i = 0 ; i < ncomponents ; i++) {
0N/A Component comp = parent.getComponent(i);
0N/A if (comp.isVisible()) {
0N/A comp.setVisible(false);
0N/A currentCard = (i + 1) % ncomponents;
0N/A comp = parent.getComponent(currentCard);
0N/A comp.setVisible(true);
0N/A parent.validate();
0N/A return;
0N/A }
0N/A }
0N/A showDefaultComponent(parent);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Flips to the previous card of the specified container. If the
0N/A * currently visible card is the first one, this method flips to the
0N/A * last card in the layout.
0N/A * @param parent the parent container in which to do the layout
0N/A * @see java.awt.CardLayout#next
0N/A */
0N/A public void previous(Container parent) {
0N/A synchronized (parent.getTreeLock()) {
0N/A checkLayout(parent);
0N/A int ncomponents = parent.getComponentCount();
0N/A for (int i = 0 ; i < ncomponents ; i++) {
0N/A Component comp = parent.getComponent(i);
0N/A if (comp.isVisible()) {
0N/A comp.setVisible(false);
0N/A currentCard = ((i > 0) ? i-1 : ncomponents-1);
0N/A comp = parent.getComponent(currentCard);
0N/A comp.setVisible(true);
0N/A parent.validate();
0N/A return;
0N/A }
0N/A }
0N/A showDefaultComponent(parent);
0N/A }
0N/A }
0N/A
0N/A void showDefaultComponent(Container parent) {
0N/A if (parent.getComponentCount() > 0) {
0N/A currentCard = 0;
0N/A parent.getComponent(0).setVisible(true);
0N/A parent.validate();
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Flips to the last card of the container.
0N/A * @param parent the parent container in which to do the layout
0N/A * @see java.awt.CardLayout#first
0N/A */
0N/A public void last(Container parent) {
0N/A synchronized (parent.getTreeLock()) {
0N/A checkLayout(parent);
0N/A int ncomponents = parent.getComponentCount();
0N/A for (int i = 0 ; i < ncomponents ; i++) {
0N/A Component comp = parent.getComponent(i);
0N/A if (comp.isVisible()) {
0N/A comp.setVisible(false);
0N/A break;
0N/A }
0N/A }
0N/A if (ncomponents > 0) {
0N/A currentCard = ncomponents - 1;
0N/A parent.getComponent(currentCard).setVisible(true);
0N/A parent.validate();
0N/A }
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Flips to the component that was added to this layout with the
0N/A * specified <code>name</code>, using <code>addLayoutComponent</code>.
0N/A * If no such component exists, then nothing happens.
0N/A * @param parent the parent container in which to do the layout
0N/A * @param name the component name
0N/A * @see java.awt.CardLayout#addLayoutComponent(java.awt.Component, java.lang.Object)
0N/A */
0N/A public void show(Container parent, String name) {
0N/A synchronized (parent.getTreeLock()) {
0N/A checkLayout(parent);
0N/A Component next = null;
0N/A int ncomponents = vector.size();
0N/A for (int i = 0; i < ncomponents; i++) {
0N/A Card card = (Card)vector.get(i);
0N/A if (card.name.equals(name)) {
0N/A next = card.comp;
0N/A currentCard = i;
0N/A break;
0N/A }
0N/A }
0N/A if ((next != null) && !next.isVisible()) {
0N/A ncomponents = parent.getComponentCount();
0N/A for (int i = 0; i < ncomponents; i++) {
0N/A Component comp = parent.getComponent(i);
0N/A if (comp.isVisible()) {
0N/A comp.setVisible(false);
0N/A break;
0N/A }
0N/A }
0N/A next.setVisible(true);
0N/A parent.validate();
0N/A }
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Returns a string representation of the state of this card layout.
0N/A * @return a string representation of this card layout.
0N/A */
0N/A public String toString() {
0N/A return getClass().getName() + "[hgap=" + hgap + ",vgap=" + vgap + "]";
0N/A }
0N/A
0N/A /**
0N/A * Reads serializable fields from stream.
0N/A */
0N/A private void readObject(ObjectInputStream s)
0N/A throws ClassNotFoundException, IOException
0N/A {
0N/A ObjectInputStream.GetField f = s.readFields();
0N/A
0N/A hgap = f.get("hgap", 0);
0N/A vgap = f.get("vgap", 0);
0N/A
0N/A if (f.defaulted("vector")) {
0N/A // pre-1.4 stream
0N/A Hashtable tab = (Hashtable)f.get("tab", null);
0N/A vector = new Vector();
0N/A if (tab != null && !tab.isEmpty()) {
0N/A for (Enumeration e = tab.keys() ; e.hasMoreElements() ; ) {
0N/A String key = (String)e.nextElement();
0N/A Component comp = (Component)tab.get(key);
0N/A vector.add(new Card(key, comp));
0N/A if (comp.isVisible()) {
0N/A currentCard = vector.size() - 1;
0N/A }
0N/A }
0N/A }
0N/A } else {
0N/A vector = (Vector)f.get("vector", null);
0N/A currentCard = f.get("currentCard", 0);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Writes serializable fields to stream.
0N/A */
0N/A private void writeObject(ObjectOutputStream s)
0N/A throws IOException
0N/A {
0N/A Hashtable tab = new Hashtable();
0N/A int ncomponents = vector.size();
0N/A for (int i = 0; i < ncomponents; i++) {
0N/A Card card = (Card)vector.get(i);
0N/A tab.put(card.name, card.comp);
0N/A }
0N/A
0N/A ObjectOutputStream.PutField f = s.putFields();
0N/A f.put("hgap", hgap);
0N/A f.put("vgap", vgap);
0N/A f.put("vector", vector);
0N/A f.put("currentCard", currentCard);
0N/A f.put("tab", tab);
0N/A s.writeFields();
0N/A }
0N/A}