diff options
author | Tom Tromey <tromey@gcc.gnu.org> | 2005-07-16 00:30:23 +0000 |
---|---|---|
committer | Tom Tromey <tromey@gcc.gnu.org> | 2005-07-16 00:30:23 +0000 |
commit | f911ba985aa7fe0096c386c5be385ac5825ea527 (patch) | |
tree | a0b991cf5866ae1d616639b906ac001811d74508 /libjava/classpath/javax/swing/plaf | |
parent | 6f4434b39b261de5317dc81ddfdd94d2e1d62b11 (diff) | |
download | gcc-f911ba985aa7fe0096c386c5be385ac5825ea527.zip gcc-f911ba985aa7fe0096c386c5be385ac5825ea527.tar.gz gcc-f911ba985aa7fe0096c386c5be385ac5825ea527.tar.bz2 |
Initial revision
From-SVN: r102074
Diffstat (limited to 'libjava/classpath/javax/swing/plaf')
153 files changed, 46795 insertions, 0 deletions
diff --git a/libjava/classpath/javax/swing/plaf/ActionMapUIResource.java b/libjava/classpath/javax/swing/plaf/ActionMapUIResource.java new file mode 100644 index 0000000..f6af088 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/ActionMapUIResource.java @@ -0,0 +1,64 @@ +/* ActionMapUIResource.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + +import javax.swing.ActionMap; + + +/** + * An <code>ActionMap</code> that implements the {@link UIResource} + * interface to indicate that it belongs to a pluggable + * LookAndFeel. + * + * @see javax.swing.ActionMap + * + * @author Andrew Selkirk + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class ActionMapUIResource + extends ActionMap + implements UIResource +{ + /** + * Constructs a new ActionMapUIResource. + */ + public ActionMapUIResource() + { + /* The constructor does nothing. */ + } +} diff --git a/libjava/classpath/javax/swing/plaf/BorderUIResource.java b/libjava/classpath/javax/swing/plaf/BorderUIResource.java new file mode 100644 index 0000000..1bf8540 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/BorderUIResource.java @@ -0,0 +1,933 @@ +/* BorderUIResource.java + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Insets; +import java.io.Serializable; + +import javax.swing.Icon; +import javax.swing.border.BevelBorder; +import javax.swing.border.Border; +import javax.swing.border.CompoundBorder; +import javax.swing.border.EmptyBorder; +import javax.swing.border.EtchedBorder; +import javax.swing.border.LineBorder; +import javax.swing.border.MatteBorder; +import javax.swing.border.TitledBorder; + +/** + * A wrapper for {@link javax.swing.border.Border} that also + * implements the {@link UIResource} marker interface. This is useful + * for implementing pluggable look-and-feels: When switching the + * current LookAndFeel, only those borders are replaced that are + * marked as {@link UIResource}. For this reason, a look-and-feel + * should always install borders that implement + * <code>UIResource</code>, such as the borders provided by this + * class. + * + * @serial + * @serialField delegate Border the <code>Border</code> wrapped + * + * @author Brian Jones (cbj@gnu.org) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class BorderUIResource + extends Object + implements Border, UIResource, Serializable +{ + /** + * Verified using the <code>serialver</code> tool + * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5. + */ + static final long serialVersionUID = -3440553684010079691L; + + + /** + * A shared instance of an {@link EtchedBorderUIResource}, or + * <code>null</code> if the {@link #getEtchedBorderUIResource()} + * method has not yet been called. + */ + private static Border etchedBorderUIResource; + + + /** + * A shared instance of a {@link BevelBorderUIResource} whose + * <code>bevelType</code> is {@link + * javax.swing.border.BevelBorder#LOWERED}, or <code>null</code> if + * the {@link #getLoweredBevelBorderUIResource()} has not yet been + * called. + */ + private static Border loweredBevelBorderUIResource; + + + /** + * A shared instance of a {@link BevelBorderUIResource} whose + * <code>bevelType</code> is {@link + * javax.swing.border.BevelBorder#RAISED}, or <code>null</code> if + * the {@link #getRaisedBevelBorderUIResource()} has not yet been + * called. + */ + private static Border raisedBevelBorderUIResource; + + + /** + * A shared instance of a {@link LineBorderUIResource} for + * a one-pixel thick black line, or <code>null</code> if + * the {@link #getBlackLineBorderUIResource()} has not yet been + * called. + */ + private static Border blackLineBorderUIResource; + + + /** + * Returns a shared instance of an etched border which also + * is marked as an {@link UIResource}. + * + * @see javax.swing.border.EtchedBorder + */ + public static Border getEtchedBorderUIResource() + { + /* Swing is not designed to be thread-safe, so there is no + * need to synchronize the access to the global variable. + */ + if (etchedBorderUIResource == null) + etchedBorderUIResource = new EtchedBorderUIResource(); + return etchedBorderUIResource; + } + + + /** + * Returns a shared instance of {@link BevelBorderUIResource} whose + * <code>bevelType</code> is {@link + * javax.swing.border.BevelBorder#LOWERED}. + * + * @see javax.swing.border.BevelBorder + */ + public static Border getLoweredBevelBorderUIResource() + { + /* Swing is not designed to be thread-safe, so there is no + * need to synchronize the access to the global variable. + */ + if (loweredBevelBorderUIResource == null) + loweredBevelBorderUIResource = new BevelBorderUIResource( + BevelBorder.LOWERED); + return loweredBevelBorderUIResource; + } + + + /** + * Returns a shared instance of {@link BevelBorderUIResource} whose + * <code>bevelType</code> is {@link + * javax.swing.border.BevelBorder#RAISED}. + * + * @see javax.swing.border.BevelBorder + */ + public static Border getRaisedBevelBorderUIResource() + { + /* Swing is not designed to be thread-safe, so there is no + * need to synchronize the access to the global variable. + */ + if (raisedBevelBorderUIResource == null) + raisedBevelBorderUIResource = new BevelBorderUIResource( + BevelBorder.RAISED); + return raisedBevelBorderUIResource; + } + + + /** + * Returns a shared instance of {@link LineBorderUIResource} for + * a black, one-pixel width border. + * + * @see javax.swing.border.LineBorder + */ + public static Border getBlackLineBorderUIResource() + { + /* Swing is not designed to be thread-safe, so there is no + * need to synchronize the access to the global variable. + */ + if (blackLineBorderUIResource == null) + blackLineBorderUIResource = new LineBorderUIResource(Color.black); + return blackLineBorderUIResource; + } + + + /** + * The wrapped border. + */ + private Border delegate; + + + /** + * Constructs a <code>BorderUIResource</code> for wrapping + * a <code>Border</code> object. + * + * @param delegate the border to be wrapped. + */ + public BorderUIResource(Border delegate) + { + if (delegate == null) + throw new IllegalArgumentException(); + + this.delegate = delegate; + } + + + /** + * Paints the border around an enclosed component by calling + * the <code>paintBorder</code> method of the wrapped delegate. + * + * @param c the component whose border is to be painted. + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the border. + * @param width the width of the available area for painting the border. + * @param height the height of the available area for painting the border. + */ + public void paintBorder(Component c, Graphics g, + int x, int y, int width, int height) + { + delegate.paintBorder(c, g, x, y, width, height); + } + + + /** + * Measures the width of this border by calling the + * <code>getBorderInsets</code> method of the wrapped + * delegate. + * + * @param c the component whose border is to be measured. + * + * @return an Insets object whose <code>left</code>, <code>right</code>, + * <code>top</code> and <code>bottom</code> fields indicate the + * width of the border at the respective edge. + */ + public Insets getBorderInsets(Component c) + { + return delegate.getBorderInsets(c); + } + + + /** + * Determines whether this border fills every pixel in its area + * when painting by calling the <code>isBorderOpaque</code> + * method of the wrapped delegate. + * + * @return <code>true</code> if the border is fully opaque, or + * <code>false</code> if some pixels of the background + * can shine through the border. + */ + public boolean isBorderOpaque() + { + return delegate.isBorderOpaque(); + } + + + /** + * A {@link javax.swing.border.BevelBorder} that also implements the + * {@link UIResource} marker interface. This is useful for + * implementing pluggable look-and-feels: When switching the current + * LookAndFeel, only those borders are replaced that are marked as + * {@link UIResource}. For this reason, a look-and-feel should + * always install borders that implement <code>UIResource</code>, + * such as the borders provided by this class. + * + * @author Brian Jones (cbj@gnu.org) + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class BevelBorderUIResource + extends BevelBorder + implements UIResource, Serializable + { + private static final long serialVersionUID = -1275542891108351642L; + + /** + * Constructs a BevelBorderUIResource whose colors will be derived + * from the background of the enclosed component. The background + * color is retrieved each time the border is painted, so a border + * constructed by this method will automatically reflect a change + * to the component’s background color. + * + * <p><img src="../border/doc-files/BevelBorder-1.png" + * width="500" height="150" + * alt="[An illustration showing raised and lowered BevelBorders]" /></p> + * + * @param bevelType the desired appearance of the border. The value + * must be either {@link javax.swing.border.BevelBorder#RAISED} + * or {@link javax.swing.border.BevelBorder#LOWERED}. + * + * @throws IllegalArgumentException if <code>bevelType</code> has + * an unsupported value. + */ + public BevelBorderUIResource(int bevelType) + { + super(bevelType); + } + + + /** + * Constructs a BevelBorderUIResource given its appearance type + * and two colors for its highlight and shadow. + * + * <p><img src="../border/doc-files/BevelBorder-2.png" width="500" + * height="150" alt="[An illustration showing BevelBorders that were + * constructed with this method]" /></p> + * + * @param bevelType the desired appearance of the border. The value + * must be either {@link javax.swing.border.BevelBorder#RAISED} + * or {@link javax.swing.border.BevelBorder#LOWERED}. + * + * @param highlight the color that will be used for the inner side + * of the highlighted edges (top and left if if + * <code>bevelType</code> is {@link + * javax.swing.border.BevelBorder#RAISED}; bottom and right + * otherwise). The color for the outer side is a brightened + * version of this color. + * + * @param shadow the color that will be used for the outer side of + * the shadowed edges (bottom and right if + * <code>bevelType</code> is {@link + * javax.swing.border.BevelBorder#RAISED}; top and left + * otherwise). The color for the inner side is a brightened + * version of this color. + * + * @throws IllegalArgumentException if <code>bevelType</code> has + * an unsupported value. + * + * @throws NullPointerException if <code>highlight</code> or + * <code>shadow</code> is <code>null</code>. + */ + public BevelBorderUIResource(int bevelType, + Color highlight, + Color shadow) + { + super(bevelType, highlight, shadow); + } + + + /** + * Constructs a BevelBorderUIResource given its appearance type + * and all its colors. + * + * <p><img src="../border/doc-files/BevelBorder-3.png" width="500" + * height="150" alt="[An illustration showing BevelBorders that + * were constructed with this method]" /></p> + * + * @param bevelType the desired appearance of the border. The value + * must be either {@link javax.swing.border.BevelBorder#RAISED} + * or {@link javax.swing.border.BevelBorder#LOWERED}. + * + * @param highlightOuter the color that will be used for the outer + * side of the highlighted edges (top and left if + * <code>bevelType</code> is {@link + * javax.swing.border.BevelBorder#RAISED}; bottom and right + * otherwise). + * + * @param highlightInner the color that will be used for the inner + * side of the highlighted edges. + * + * @param shadowOuter the color that will be used for the outer + * side of the shadowed edges (bottom and right if + * <code>bevelType</code> is {@link + * javax.swing.border.BevelBorder#RAISED}; top and left + * otherwise). + * + * @param shadowInner the color that will be used for the inner + * side of the shadowed edges. + * + * @throws IllegalArgumentException if <code>bevelType</code> has + * an unsupported value. + * + * @throws NullPointerException if one of the passed colors + * is <code>null</code>. + */ + public BevelBorderUIResource(int bevelType, + Color highlightOuter, + Color highlightInner, + Color shadowOuter, + Color shadowInner) + { + super(bevelType, + highlightOuter, highlightInner, + shadowOuter, shadowInner); + } + } + + + /** + * A {@link javax.swing.border.CompoundBorder} that also implements the + * {@link UIResource} marker interface. This is useful for + * implementing pluggable look-and-feels: When switching the current + * LookAndFeel, only those borders are replaced that are marked as + * {@link UIResource}. For this reason, a look-and-feel should + * always install borders that implement <code>UIResource</code>, + * such as the borders provided by this class. + * + * @author Brian Jones (cbj@gnu.org) + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class CompoundBorderUIResource + extends CompoundBorder + implements UIResource, Serializable + { + private static final long serialVersionUID = 7550017084975167341L; + + /** + * Constructs a CompoundBorderUIResource with the specified inside + * and outside borders. + * + * @param outsideBorder the outside border, which is painted to the + * outside of both <code>insideBorder</code> and the enclosed + * component. It is acceptable to pass <code>null</code>, in + * which case no outside border is painted. + * + * @param insideBorder the inside border, which is painted to + * between <code>outsideBorder</code> and the enclosed + * component. It is acceptable to pass <code>null</code>, in + * which case no inside border is painted. + */ + public CompoundBorderUIResource(Border outsideBorder, + Border insideBorder) + { + super(outsideBorder, insideBorder); + } + } + + + /** + * An {@link javax.swing.border.EmptyBorder} that also implements the + * {@link UIResource} marker interface. This is useful for + * implementing pluggable look-and-feels: When switching the current + * LookAndFeel, only those borders are replaced that are marked as + * {@link UIResource}. For this reason, a look-and-feel should + * always install borders that implement <code>UIResource</code>, + * such as the borders provided by this class. + * + * <p><img src="../border/doc-files/EmptyBorder-1.png" + * width="290" height="200" + * alt="[An illustration of EmptyBorder]" /></p> + * + * @author Brian Jones (cbj@gnu.org) + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class EmptyBorderUIResource + extends EmptyBorder + implements UIResource, Serializable + { + private static final long serialVersionUID = -4914187529340071708L; + + /** + * Constructs an empty border given the number of pixels required + * on each side. + * + * @param top the number of pixels that the border will need + * for its top edge. + * + * @param left the number of pixels that the border will need + * for its left edge. + * + * @param bottom the number of pixels that the border will need + * for its bottom edge. + * + * @param right the number of pixels that the border will need + * for its right edge. + */ + public EmptyBorderUIResource(int top, int left, int bottom, int right) + { + super(top, left, bottom, right); + } + + + /** + * Constructs an empty border given the number of pixels required + * on each side, passed in an Insets object. + * + * @param insets the Insets for the new border. + */ + public EmptyBorderUIResource(Insets insets) + { + super(insets); + } + } + + + /** + * An {@link javax.swing.border.EtchedBorder} that also implements the + * {@link UIResource} marker interface. This is useful for + * implementing pluggable look-and-feels: When switching the current + * LookAndFeel, only those borders are replaced that are marked as + * {@link UIResource}. For this reason, a look-and-feel should + * always install borders that implement <code>UIResource</code>, + * such as the borders provided by this class. + * + * <p><img src="../border/doc-files/EtchedBorder-1.png" width="500" + * height="200" alt="[An illustration of the two EtchedBorder + * variants]" /></p> + * + * @author Brian Jones (cbj@gnu.org) + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class EtchedBorderUIResource + extends EtchedBorder + implements UIResource, Serializable + { + private static final long serialVersionUID = -8186391754165296656L; + + /** + * Constructs an EtchedBorderUIResource that appears lowered into + * the surface. The colors will be derived from the background + * color of the enclosed Component when the border gets painted. + */ + public EtchedBorderUIResource() + { + super(); + } + + + /** + * Constructs an EtchedBorderUIResource with the specified + * appearance. The colors will be derived from the background + * color of the enclosed Component when the border gets painted. + * + * <p><img src="../border/doc-files/EtchedBorder-1.png" + * width="500" height="200" alt="[An illustration of the two + * EtchedBorder variants]" /></p> + * + * @param etchType the desired appearance of the border. The value + * must be either {@link javax.swing.border.EtchedBorder#RAISED} + * or {@link javax.swing.border.EtchedBorder#LOWERED}. + * + * @throws IllegalArgumentException if <code>etchType</code> has + * an unsupported value. + */ + public EtchedBorderUIResource(int etchType) + { + super(etchType); + } + + + /** + * Constructs a lowered EtchedBorderUIResource, explicitly + * selecting the colors that will be used for highlight and + * shadow. + * + * @param highlight the color that will be used for painting + * the highlight part of the border. + * + * @param shadow the color that will be used for painting + * the shadow part of the border. + * + * @see #EtchedBorderUIResource(int, Color, Color) + */ + public EtchedBorderUIResource(Color highlight, Color shadow) + { + super(highlight, shadow); + } + + + /** + * Constructs an EtchedBorderUIResource with the specified + * appearance, explicitly selecting the colors that will be used + * for highlight and shadow. + * + * <p><img src="../border/doc-files/EtchedBorder-2.png" width="500" + * height="200" alt="[An illustration that shows which pixels get + * painted in what color]" /></p> + * + * @param etchType the desired appearance of the border. The value + * must be either {@link javax.swing.border.EtchedBorder#RAISED} + * or {@link javax.swing.border.EtchedBorder#LOWERED}. + * + * @param highlight the color that will be used for painting + * the highlight part of the border. + * + * @param shadow the color that will be used for painting + * the shadow part of the border. + * + * @throws IllegalArgumentException if <code>etchType</code> has + * an unsupported value. + */ + public EtchedBorderUIResource(int etchType, + Color highlight, Color shadow) + { + super(etchType, highlight, shadow); + } + } + + + /** + * A {@link javax.swing.border.LineBorder} that also implements the + * {@link UIResource} marker interface. This is useful for + * implementing pluggable look-and-feels: When switching the current + * LookAndFeel, only those borders are replaced that are marked as + * {@link UIResource}. For this reason, a look-and-feel should + * always install borders that implement <code>UIResource</code>, + * such as the borders provided by this class. + * + * <p><img src="../border/doc-files/LineBorder-1.png" width="500" + * height="200" alt="[An illustration of two LineBorders]" /></p> + * + * @author Brian Jones (cbj@gnu.org) + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class LineBorderUIResource + extends LineBorder + implements UIResource, Serializable + { + private static final long serialVersionUID = -6171232338180172310L; + + /** + * Constructs a LineBorderUIResource given its color. The border + * will be one pixel thick and have plain corners. + * + * @param color the color for drawing the border. + */ + public LineBorderUIResource(Color color) + { + super(color); + } + + + /** + * Constructs a LineBorder given its color and thickness. The + * border will have plain corners. + * + * @param color the color for drawing the border. + * @param thickness the width of the line in pixels. + */ + public LineBorderUIResource(Color color, int thickness) + { + super(color, thickness); + } + + + /* Note: Since JDK1.3, javax.swing.border.LineBorder also has a + * constructor which accepts a value for the roundedCorners + * property. However, as of JDK1.4.1, the LineBorderUIResource + * subclass does not have a corresponding constructor. + * + * A request for enhancing the Swing API has been filed with Sun: + * http://developer.java.sun.com/developer/bugParade/bugs/4879999.html + */ + } + + + /** + * A {@link javax.swing.border.MatteBorder} that also implements the + * {@link UIResource} marker interface. This is useful for + * implementing pluggable look-and-feels: When switching the current + * LookAndFeel, only those borders are replaced that are marked as + * {@link UIResource}. For this reason, a look-and-feel should + * always install borders that implement <code>UIResource</code>, + * such as the borders provided by this class. + * + * <p><img src="../border/doc-files/MatteBorder-1.png" width="500" + * height="150" alt="[An illustration of two MatteBorders]" /></p> + * + * @author Brian Jones (cbj@gnu.org) + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class MatteBorderUIResource + extends MatteBorder + implements UIResource, Serializable + { + private static final long serialVersionUID = -8107923147541851122L; + + /** + * Constructs a MatteBorderUIResource given the width on each side + * and a fill color. + * + * <p><img src="../border/doc-files/MatteBorder-2.png" width="500" + * height="150" alt="[A picture of a MatteBorder made by this + * constructor]" /></p> + * + * @param top the width of the border at its top edge. + * @param left the width of the border at its left edge. + * @param bottom the width of the border at its bottom edge. + * @param right the width of the border at its right edge. + * @param matteColor the color for filling the border. + */ + public MatteBorderUIResource(int top, int left, + int bottom, int right, + Color color) + { + super(top, left, bottom, right, color); + } + + + /** + * Constructs a MatteBorderUIResource given the width on each side + * and an icon for tiling the border area. + * + * <p><img src="../border/doc-files/MatteBorder-4.png" width="500" + * height="150" alt="[A picture of a MatteBorder made by this + * constructor]" /></p> + * + * @param top the width of the border at its top edge. + * @param left the width of the border at its left edge. + * @param bottom the width of the border at its bottom edge. + * @param right the width of the border at its right edge. + * @param tileIcon an icon for tiling the border area. + */ + public MatteBorderUIResource(int top, int left, + int bottom, int right, + Icon tileIcon) + { + super(top, left, bottom, right, tileIcon); + } + + + /** + * Constructs a MatteBorderUIResource given an icon for tiling the + * border area. The icon width is used for the border insets at + * the left and right edge, the icon height for the top and bottom + * edge. + * + * <p><img src="../border/doc-files/MatteBorder-6.png" width="500" + * height="150" alt="[A picture of a MatteBorder made by this + * constructor]" /></p> + * + * @param tileIcon an icon for tiling the border area. + */ + public MatteBorderUIResource(Icon tileIcon) + { + super(tileIcon); + } + } + + + /** + * A {@link javax.swing.border.TitledBorder} that also implements the + * {@link UIResource} marker interface. This is useful for + * implementing pluggable look-and-feels: When switching the current + * LookAndFeel, only those borders are replaced that are marked as + * {@link UIResource}. For this reason, a look-and-feel should + * always install borders that implement <code>UIResource</code>, + * such as the borders provided by this class. + * + * @author Brian Jones (cbj@gnu.org) + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class TitledBorderUIResource + extends TitledBorder + implements UIResource, Serializable + { + private static final long serialVersionUID = 7667113547406407427L; + + /** + * Constructs a TitledBorderUIResource given the text of its title. + * + * @param title the title text, or <code>null</code> to use no + * title text. + */ + public TitledBorderUIResource(String title) + { + super(title); + } + + + /** + * Constructs an initially untitled TitledBorderUIResource + * given another border. + * + * @param border the border underneath the title, or + * <code>null</code> to use a default from + * the current look and feel. + */ + public TitledBorderUIResource(Border border) + { + super(border); + } + + + /** + * Constructs a TitledBorder given its border and title text. + * + * @param border the border underneath the title, or + * <code>null</code> to use a default from + * the current look and feel. + * + * @param title the title text, or <code>null</code> + * to use no title text. + */ + public TitledBorderUIResource(Border border, String title) + { + super(border, title); + } + + + /** + * Constructs a TitledBorderUIResource given its border, title + * text, horizontal alignment, and vertical position. + * + * @param border the border underneath the title, or + * <code>null</code> to use a default + * from the current look and feel. + * + * @param title the title text, or <code>null</code> + * to use no title text. + * + * @param titleJustification the horizontal alignment of the title + * text in relation to the border. The value must be one of + * {@link javax.swing.border.TitledBorder#LEFT}, + * {@link javax.swing.border.TitledBorder#CENTER}, + * {@link javax.swing.border.TitledBorder#RIGHT}, + * {@link javax.swing.border.TitledBorder#LEADING}, + * {@link javax.swing.border.TitledBorder#TRAILING}, or + * {@link javax.swing.border.TitledBorder#DEFAULT_JUSTIFICATION}. + * + * @param titlePosition the vertical position of the title text + * in relation to the border. The value must be one of + * {@link javax.swing.border.TitledBorder#ABOVE_TOP}, + * {@link javax.swing.border.TitledBorder#TOP}, + * {@link javax.swing.border.TitledBorder#BELOW_TOP}, + * {@link javax.swing.border.TitledBorder#ABOVE_BOTTOM}, + * {@link javax.swing.border.TitledBorder#BOTTOM}, + * {@link javax.swing.border.TitledBorder#BELOW_BOTTOM}, + * or {@link javax.swing.border.TitledBorder#DEFAULT_POSITION}. + * + * @throws IllegalArgumentException if <code>titleJustification</code> + * or <code>titlePosition</code> have an unsupported value. + */ + public TitledBorderUIResource(Border border, String title, + int titleJustification, + int titlePosition) + { + super(border, title, titleJustification, titlePosition); + } + + + /** + * Constructs a TitledBorder given its border, title text, + * horizontal alignment, vertical position, and font. + * + * @param border the border underneath the title, or + * <code>null</code> to use a default + * from the current look and feel. + * + * @param title the title text, or <code>null</code> + * to use no title text. + * + * @param titleJustification the horizontal alignment of the title + * text in relation to the border. The value must be one of + * {@link javax.swing.border.TitledBorder#LEFT}, + * {@link javax.swing.border.TitledBorder#CENTER}, + * {@link javax.swing.border.TitledBorder#RIGHT}, + * {@link javax.swing.border.TitledBorder#LEADING}, + * {@link javax.swing.border.TitledBorder#TRAILING}, or + * {@link javax.swing.border.TitledBorder#DEFAULT_JUSTIFICATION}. + * + * @param titlePosition the vertical position of the title text + * in relation to the border. The value must be one of + * {@link javax.swing.border.TitledBorder#ABOVE_TOP}, + * {@link javax.swing.border.TitledBorder#TOP}, + * {@link javax.swing.border.TitledBorder#BELOW_TOP}, + * {@link javax.swing.border.TitledBorder#ABOVE_BOTTOM}, + * {@link javax.swing.border.TitledBorder#BOTTOM}, + * {@link javax.swing.border.TitledBorder#BELOW_BOTTOM}, + * or {@link javax.swing.border.TitledBorder#DEFAULT_POSITION}. + * + * @param titleFont the font for the title text, or <code>null</code> + * to use a default from the current look and feel. + * + * @throws IllegalArgumentException if <code>titleJustification</code> + * or <code>titlePosition</code> have an unsupported value. + */ + public TitledBorderUIResource(Border border, String title, + int titleJustification, + int titlePosition, + Font titleFont) + { + super(border, title, titleJustification, titlePosition, + titleFont); + } + + + /** + * Constructs a TitledBorder given its border, title text, + * horizontal alignment, vertical position, font, and color. + * + * @param border the border underneath the title, or + * <code>null</code> to use a default + * from the current look and feel. + * + * @param title the title text, or <code>null</code> + * to use no title text. + * + * @param titleJustification the horizontal alignment of the title + * text in relation to the border. The value must be one of + * {@link javax.swing.border.TitledBorder#LEFT}, + * {@link javax.swing.border.TitledBorder#CENTER}, + * {@link javax.swing.border.TitledBorder#RIGHT}, + * {@link javax.swing.border.TitledBorder#LEADING}, + * {@link javax.swing.border.TitledBorder#TRAILING}, or + * {@link javax.swing.border.TitledBorder#DEFAULT_JUSTIFICATION}. + * + * @param titlePosition the vertical position of the title text + * in relation to the border. The value must be one of + * {@link javax.swing.border.TitledBorder#ABOVE_TOP}, + * {@link javax.swing.border.TitledBorder#TOP}, + * {@link javax.swing.border.TitledBorder#BELOW_TOP}, + * {@link javax.swing.border.TitledBorder#ABOVE_BOTTOM}, + * {@link javax.swing.border.TitledBorder#BOTTOM}, + * {@link javax.swing.border.TitledBorder#BELOW_BOTTOM}, + * or {@link javax.swing.border.TitledBorder#DEFAULT_POSITION}. + * + * @param titleFont the font for the title text, or <code>null</code> + * to use a default from the current look and feel. + * + * @param titleColor the color for the title text, or <code>null</code> + * to use a default from the current look and feel. + * + * @throws IllegalArgumentException if <code>titleJustification</code> + * or <code>titlePosition</code> have an unsupported value. + */ + public TitledBorderUIResource(Border border, String title, + int titleJustification, int titlePosition, + Font titleFont, Color titleColor) + { + super(border, title, titleJustification, titlePosition, + titleFont, titleColor); + } + } +} + diff --git a/libjava/classpath/javax/swing/plaf/ButtonUI.java b/libjava/classpath/javax/swing/plaf/ButtonUI.java new file mode 100644 index 0000000..197299e --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/ButtonUI.java @@ -0,0 +1,52 @@ +/* ButtonUI.java + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a <code>JButton</code>. + * + * @see javax.swing.JButton + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class ButtonUI + extends ComponentUI +{ +} diff --git a/libjava/classpath/javax/swing/plaf/ColorChooserUI.java b/libjava/classpath/javax/swing/plaf/ColorChooserUI.java new file mode 100644 index 0000000..68ffd91 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/ColorChooserUI.java @@ -0,0 +1,60 @@ +/* ColorChooserUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a <code>JColorChooser</code>. + * + * @see javax.swing.JColorChooser + * + * @author Andrew Selkirk + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class ColorChooserUI + extends ComponentUI +{ + /** + * Constructs a ColorChooserUI. + */ + public ColorChooserUI() + { + /* The constructor does not do anything. */ + } +} + diff --git a/libjava/classpath/javax/swing/plaf/ColorUIResource.java b/libjava/classpath/javax/swing/plaf/ColorUIResource.java new file mode 100644 index 0000000..33b1676 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/ColorUIResource.java @@ -0,0 +1,123 @@ +/* ColorUIResource.java + Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +import java.awt.Color; + + +/** + * A Color that is marked as <code>UIResource</code>, which indicates that + * the color has been installed by a pluggable LookAndFeel. Such colors + * are replaced when the LookAndFeel changes. + * + * @see java.awt.Color + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class ColorUIResource + extends Color + implements UIResource +{ + /** + * Constructs a <code>ColorUIResource</code> using the specified + * red, green, and blue values, which must be given as integers in + * the range of 0-255. The alpha channel value will default to 255, + * meaning that the color is fully opaque. + * + * @param r the red intensity, which must be in the range [0 .. 255]. + * @param g the green intensity, which must be in the range [0 .. 255]. + * @param b the blue intensity, which must be in the range [0 .. 255]. + * + * @throws IllegalArgumentException if any of the values is outside the + * specified range. + */ + public ColorUIResource(int r, int g, int b) + { + super(r, g, b); + } + + + /** + * Constructs a <code>ColorUIResource</code> using the specified + * RGB value. The blue value is in bits 0-7, green in bits 8-15, and + * red in bits 16-23. The other bits are ignored. The alpha value is set + * to 255, meaning that the color is fully opaque. + * + * @param rgb the rgb value, as discussed above. + */ + public ColorUIResource(int rgb) + { + super(rgb); + } + + + /** + * Constructs a <code>ColorUIResource</code> using the specified + * red, green, and blue intensities, which must be given as floats in + * the range of 0-1. The alpha channel value will default to 1.0f, + * meaning that the color is fully opaque. + * + * @param r the red intensity, which must be in the range [0.0 .. 1.0]. + * @param g the green intensity, which must be in the range [0.0 .. 1.0]. + * @param b the blue intensity, which must be in the range [0.0 .. 1.0]. + * + * @throws IllegalArgumentException if any of the values is outside the + * specified range. + */ + public ColorUIResource(float r, float g, float b) + { + super(r, g, b); + } + + + /** + * Constructs a <code>ColorUIResource</code>, using the intensities + * of another color. + * + * @param c the color whose intensities will be considered when + * constructing this <code>ColorUIResource</code> (<code>null</code> + * not permitted). + * + * @throws NullPointerException if <code>c</code> is <code>null</code>. + */ + public ColorUIResource(Color c) + { + super(c.getRGB()); + } +} diff --git a/libjava/classpath/javax/swing/plaf/ComboBoxUI.java b/libjava/classpath/javax/swing/plaf/ComboBoxUI.java new file mode 100644 index 0000000..9498a48 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/ComboBoxUI.java @@ -0,0 +1,96 @@ +/* ComboBoxUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + +import javax.swing.JComboBox; + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a <code>JButton</code>. + * + * @see javax.swing.JComboBox + * + * @author Andrew Selkirk + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class ComboBoxUI + extends ComponentUI +{ + /** + * Constructs a new <code>ComboBoxUI</code>. + */ + public ComboBoxUI() + { + } + + + /** + * Sets the visibility of the popup button. + * + * @param c the <code>JComboBox</code> whose popup + * is shown or hidden. + * + * @param visible <code>true</code> to show the popup, <code>false</code> + * to hide it. + */ + public abstract void setPopupVisible(JComboBox c, boolean visible); + + + /** + * Determines whether the popup button is currently visible. + * + * @param c the <code>JComboBox</code> whose popup visibility + * is retrieved. + * + * @return <code>true</code> if the popup button is currently + * visible, <code>false</code> otherwise. + */ + public abstract boolean isPopupVisible(JComboBox c); + + + /** + * Determines whether the combo box can receive input focus. + * + * @param c <code>JComboBox</code> whose focus traversability + * is to be retrieved. + * + * @returns <code>true</code> if <code>c</code> can receive + * input focus, <code>false</code> otherwise. + */ + public abstract boolean isFocusTraversable(JComboBox c); +} diff --git a/libjava/classpath/javax/swing/plaf/ComponentInputMapUIResource.java b/libjava/classpath/javax/swing/plaf/ComponentInputMapUIResource.java new file mode 100644 index 0000000..e141871 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/ComponentInputMapUIResource.java @@ -0,0 +1,70 @@ +/* ComponentInputMapUIResource.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + +import javax.swing.ComponentInputMap; +import javax.swing.JComponent; + + +/** + * A <code>ComponentInputMap</code> that implements the {@link UIResource} + * interface to indicate that it belongs to a pluggable + * LookAndFeel. + * + * @see javax.swing.ComponentInputMap + * @see javax.swing.InputMap + * + * @author Andrew Selkirk + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class ComponentInputMapUIResource + extends ComponentInputMap + implements UIResource +{ + /** + * Constructs a new <code>ComponentInputMapUIResource</code>. + * + * @param component the <code>JComponent</code> associated with + * this <code>InputMap</code>. + */ + public ComponentInputMapUIResource(JComponent component) + { + super(component); + } +} + diff --git a/libjava/classpath/javax/swing/plaf/ComponentUI.java b/libjava/classpath/javax/swing/plaf/ComponentUI.java new file mode 100644 index 0000000..0e76805 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/ComponentUI.java @@ -0,0 +1,326 @@ +/* ComponentUI.java -- + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +import java.awt.Dimension; +import java.awt.Graphics; + +import javax.accessibility.Accessible; +import javax.swing.JComponent; + +/** + * The abstract base class for all delegates that provide the + * pluggable look and feel for Swing components. User applications + * should not need to access this class; it is internal to Swing + * and the look-and-feel implementations. + * + * <p><img src="doc-files/ComponentUI-1.png" width="700" height="550" + * alt="[UML diagram illustrating the architecture for pluggable + * look and feels]" /></p> + * + * <p>Components such as {@link javax.swing.JSlider} do not directly + * implement operations related to the look and feel of the user + * interface, such as painting or layout. Instead, they use a delegate + * object for all such tasks. In the case of <code>JSlider</code>, the + * user interface would be provided by some concrete subclass of + * {@link javax.swing.plaf.SliderUI}. + * + * <p>Soon after its creation, a <code>ComponentUI</code> will be sent + * an {@link #installUI} message. The <code>ComponentUI</code> will + * react by setting properties such as the border or the background + * color of the <code>JComponent</code> for which it provides its + * services. Soon before the end of its lifecycle, the + * <code>ComponentUI</code> will receive an {@link #uninstallUI} + * message, at which time the <code>ComponentUI</code> is expected to + * undo any changes.</p> + * + * <p>Note that the <code>ui</code> of a <code>JComponent</code> + * changes whenever the user switches between look and feels. For + * example, the <code>ui</code> property of a <code>JSlider</code> + * could change from an instance of <code>MetalSliderUI</code> to an + * instance of <code>FooSliderUI</code>. This switch can happen at any + * time, but it will always be performed from inside the Swing thread.</p> + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class ComponentUI +{ + /** + * Constructs a new UI delegate. + */ + public ComponentUI() + { + } + + + /** + * Sets up the specified component so it conforms the the design + * guidelines of the implemented look and feel. When the look and + * feel changes, a <code>ComponentUI</code> delegate is created. + * The delegate object then receives an <code>installUI</code> + * message. + * + * <p>This method should perform the following tasks:</p> + * + * <ul> + * <li>Set visual properties such as borders, fonts, colors, or + * icons. However, no change should be performed for those + * properties whose values have been directly set by the client + * application. To allow the distinction, LookAndFeels are expected + * to use values that implement the {@link UIResource} marker + * interface, such as {@link BorderUIResource} or {@link + * ColorUIResource}.</li> + * <li>If necessary, install a {@link java.awt.LayoutManager}.</li> + * <li>Embed custom sub-components. For instance, the UI delegate + * for a {@link javax.swing.JSplitPane} might install a special + * component for the divider.</li> + * <li>Register event listeners.</li> + * <li>Set up properties related to keyborad navigation, such as + * mnemonics or focus traversal policies.</li> + * </ul> + * + * @param c the component for which this delegate will provide + * services. + * + * @see #uninstallUI + * @see javax.swing.JComponent#setUI + * @see javax.swing.JComponent#updateUI + */ + public void installUI(JComponent c) + { + // The default implementation does not change any properties. + } + + + /** + * Puts the specified component into the state it had before + * {@link #installUI} was called. + * + * @param c the component for which this delegate has provided + * services. + * + * @see #installUI + * @see javax.swing.JComponent#setUI + * @see javax.swing.JComponent#updateUI + */ + public void uninstallUI(JComponent c) + { + // The default implementation does not change any properties. + } + + + /** + * Paints the component according to the design guidelines + * of the look and feel. Most subclasses will want to override + * this method. + * + * @param g the graphics for painting. + * + * @param c the component for which this delegate performs + * services. + */ + public void paint(Graphics g, JComponent c) + { + } + + + /** + * Fills the specified component with its background color + * (unless the <code>opaque</code> property is <code>false</code>) + * before calling {@link #paint}. + * + * <p>It is unlikely that a subclass needs to override this method. + * The actual rendering should be performed by the {@link #paint} + * method. + * + * @param g the graphics for painting. + * + * @param c the component for which this delegate performs + * services. + * + * @see #paint + * @see javax.swing.JComponent#paintComponent + */ + public void update(Graphics g, JComponent c) + { + if (c.isOpaque()) + { + g.setColor(c.getBackground()); + g.fillRect(0, 0, c.getWidth(), c.getHeight()); + } + paint(g, c); + } + + + /** + * Determines the preferred size of a component. The default + * implementation returns <code>null</code>, which means that + * <code>c</code>’s layout manager should be asked to + * calculate the preferred size. + * + * @param c the component for which this delegate performs services. + * + * @return the preferred size, or <code>null</code> to indicate that + * <code>c</code>’s layout manager should be asked + * for the preferred size. + */ + public Dimension getPreferredSize(JComponent c) + { + return null; + } + + + /** + * Determines the minimum size of a component. The default + * implementation calls {@link #getPreferredSize}, but subclasses + * might want to override this. + * + * @param c the component for which this delegate performs services. + * + * @return the minimum size, or <code>null</code> to indicate that + * <code>c</code>’s layout manager should be asked + * to calculate the minimum size. + */ + public Dimension getMinimumSize(JComponent c) + { + return getPreferredSize(c); + } + + + /** + * Determines the maximum size of a component. The default + * implementation calls {@link #getPreferredSize}, but subclasses + * might want to override this. + * + * @param c the component for which this delegate performs services. + * + * @return the maximum size, or <code>null</code> to indicate that + * <code>c</code>’s layout manager should be asked + * to calculate the maximum size. + */ + public Dimension getMaximumSize(JComponent c) + { + return getPreferredSize(c); + } + + + /** + * Determines whether a click into the component at a specified + * location is considered as having hit the component. The default + * implementation checks whether the point falls into the + * component’s bounding rectangle. Some subclasses might want + * to override this, for example in the case of a rounded button. + * + * @param c the component for which this delegate performs services. + * + * @param x the x coordinate of the point, relative to the local + * coordinate system of the component. Zero would be be + * component’s left edge, irrespective of the location + * inside its parent. + * + * @param y the y coordinate of the point, relative to the local + * coordinate system of the component. Zero would be be + * component’s top edge, irrespective of the location + * inside its parent. + */ + public boolean contains(JComponent c, int x, int y) + { + /* JComponent.contains calls the ui delegate for hit + * testing. Therefore, endless mutual recursion would result if we + * called c.contains(x, y) here. + * + * The previous Classpath implementation called the deprecated + * method java.awt.Component.inside. In the Sun implementation, it + * can be observed that inside, other than contains, does not call + * the ui delegate. But that inside() behaves different to + * contains() clearly is in violation of the method contract, and + * it is not something that a good implementation should rely upon + * -- even if Classpath ends up being forced to replicate this + * apparent bug of the Sun implementation. + */ + return (x >= 0) && (x < c.getWidth()) + && (y >= 0) && (y < c.getHeight()); + } + + + /** + * Creates a delegate object for the specified component. Users + * should use the <code>createUI</code> method of a suitable + * subclass. The implementation of <code>ComponentUI</code> + * always throws an error. + * + * @param c the component for which a UI delegate is requested. + */ + public static ComponentUI createUI(JComponent c) + { + throw new Error( + "javax.swing.plaf.ComponentUI does not implement createUI; call " + + "createUI on a subclass."); + } + + + /** + * Counts the number of accessible children in the component. The + * default implementation delegates the inquiry to the {@link + * javax.accessibility.AccessibleContext} of <code>c</code>. + * + * @param c the component whose accessible children + * are to be counted. + */ + public int getAccessibleChildrenCount(JComponent c) + { + return c.getAccessibleContext().getAccessibleChildrenCount(); + } + + + /** + * Returns the specified accessible child of the component. The + * default implementation delegates the inquiry to the {@link + * javax.accessibility.AccessibleContext} of <code>c</code>. + * + * @param i the index of the accessible child, starting at zero. + * + * @param c the component whose <code>i</code>-th accessible child + * is requested. + */ + public Accessible getAccessibleChild(JComponent c, int i) + { + return c.getAccessibleContext().getAccessibleChild(i); + } +} diff --git a/libjava/classpath/javax/swing/plaf/DesktopIconUI.java b/libjava/classpath/javax/swing/plaf/DesktopIconUI.java new file mode 100644 index 0000000..2e44088 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/DesktopIconUI.java @@ -0,0 +1,56 @@ +/* DesktopIconUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a desktop icon. + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class DesktopIconUI + extends ComponentUI +{ + /** + * Constructs a new <code>DesktopIconUI</code>. + */ + public DesktopIconUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/DesktopPaneUI.java b/libjava/classpath/javax/swing/plaf/DesktopPaneUI.java new file mode 100644 index 0000000..de553ea --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/DesktopPaneUI.java @@ -0,0 +1,59 @@ +/* DesktopPaneUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a <code>JDesktopPane</code>. + * + * @see javax.swing.JDesktopPane + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class DesktopPaneUI + extends ComponentUI +{ + /** + * Constructs a new <code>DesktopPaneUI</code>. + */ + public DesktopPaneUI() + { + } +} + diff --git a/libjava/classpath/javax/swing/plaf/DimensionUIResource.java b/libjava/classpath/javax/swing/plaf/DimensionUIResource.java new file mode 100644 index 0000000..63c6838 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/DimensionUIResource.java @@ -0,0 +1,68 @@ +/* DimensionUIResource.java + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +import java.awt.Dimension; + +/** + * A Dimension that is marked as <code>UIResource</code>, which + * indicates that it has been installed by a pluggable + * LookAndFeel. Such dimensions are replaced when the LookAndFeel + * changes. + * + * @see java.awt.Dimension + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class DimensionUIResource + extends Dimension + implements UIResource +{ + /** + * Constructs a new DimensionUIResource, given its width and height. + * + * @param width the width in pixels. + * @param height the height in pixels. + */ + public DimensionUIResource(int width, int height) + { + super(width, height); + } +} diff --git a/libjava/classpath/javax/swing/plaf/FileChooserUI.java b/libjava/classpath/javax/swing/plaf/FileChooserUI.java new file mode 100644 index 0000000..87847c4 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/FileChooserUI.java @@ -0,0 +1,138 @@ +/* FileChooserUI.java -- + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +import java.io.File; + +import javax.swing.JFileChooser; +import javax.swing.filechooser.FileFilter; +import javax.swing.filechooser.FileView; + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a <code>JFileChooser</code>. + * + * @see javax.swing.JFileChooser + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class FileChooserUI + extends ComponentUI +{ + /** + * Constructs a new <code>FileChooserUI</code>. + */ + public FileChooserUI() + { + } + + + /** + * Returns a <code>FileFilter</code> that accepts every file. While + * the filtering itself is not specific to any look and feel, the + * text returned by <code>FileFilter.getDescription()</code> need + * not be the same across all look and feels. + * + * @param chooser the <code>JFileChooser</code> for which + * a <code>FileFilter</code> is requested. + * + * @see javax.swing.JFileChooser#getAcceptAllFileFilter + * @see javax.swing.filechooser.FileFilter#getDescription + */ + public abstract FileFilter getAcceptAllFileFilter(JFileChooser chooser); + + + /** + * Returns a view to a file, which is able to retrieve its name, + * icon, and other properties that are relevant for presenting + * the file to the user. + * + * @param chooser the <code>JFileChooser</code> for which + * a <code>FileFilter</code> is requested. + */ + public abstract FileView getFileView(JFileChooser chooser); + + + /** + * Determines which text is appropriate for the approve button + * according to the design guidelines of the implemented + * look and feel. + * + * @param chooser the <code>JFileChooser</code> whose + * button text is requested. + * + * @see javax.swing.JFileChoose#getApproveButtonText + */ + public abstract String getApproveButtonText(JFileChooser chooser); + + + /** + * Determines which text is appropriate for the title bar of a + * <code>JFileChooser</code> according to the design guidelines of + * the implemented look and feel. + * + * @param chooser the <code>JFileChooser</code> whose + * dialog title is requested. + * + * @see javax.swing.JFileChoose#getDialogtitle + */ + public abstract String getDialogTitle(JFileChooser chooser); + + + /** + * Refreshes the currently displayed directory. + * + * @param chooser the <code>JFileChooser</code> whose + * dialog title needs re-scanning. + */ + public abstract void rescanCurrentDirectory(JFileChooser chooser); + + + /** + * Ensures that a specified file is visible in the + * <code>JFileChooser</code> + * + * @param chooser the <code>JFileChooser</code> that + * should display the file <code>file</code>. + * + * @param file the file that needs to be made visible. + */ + public abstract void ensureFileIsVisible(JFileChooser chooser, File file); +} diff --git a/libjava/classpath/javax/swing/plaf/FontUIResource.java b/libjava/classpath/javax/swing/plaf/FontUIResource.java new file mode 100644 index 0000000..1c17310 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/FontUIResource.java @@ -0,0 +1,101 @@ +/* FontUIResource.java + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +import java.awt.Font; + + +/** + * A font that is marked as <code>UIResource</code>, which + * indicates that it has been installed by a pluggable + * LookAndFeel. Such dimensions are replaced when the LookAndFeel + * changes. + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class FontUIResource + extends Font + implements UIResource +{ + /** + * Constructs a new <code>FontUIResource</code> given + * the name, style and size of the font. + * + * @param name the name of the font. A number of + * “logical” names are supported by any Java + * implementation. These are + * <code>“Dialog”</code>, + * <code>“DialogInput”</code>, + * <code>“Monospaced”</code>, + * <code>“Serif”</code>, and + * <code>“SansSerif”</code>. + * + * @param style the style of the font, for instance {@link + * java.awt.Font#BOLD} or {@link java.awt.Font#PLAIN}. + * + * @param size the size of the font in typographic points, for + * instance 10, 12 or 13. Designers of LookAndFeels should be + * aware that some languages (like Japanese and Chinese) have + * glyphs that are too complex to be legible at small point + * sizes. + */ + public FontUIResource(String name, int style, int size) + { + super(name, style, size); + } + + + /** + * Constructs a new <code>FontUIResource</code> given + * an existing font. + * + * @param f the font that serves as a template. + */ + public FontUIResource(Font f) + { + /* This implementation will get rid of many font properties, + * such as skewing, values of multiple master design axes, + * etc., unless they get encoded into the name. It probably + * is not a problem for LookAndFeels because user interfaces + * are usually not very advanced with respect to typography. + */ + super(f.getName(), f.getStyle(), f.getSize()); + } +} diff --git a/libjava/classpath/javax/swing/plaf/IconUIResource.java b/libjava/classpath/javax/swing/plaf/IconUIResource.java new file mode 100644 index 0000000..1b09ed3 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/IconUIResource.java @@ -0,0 +1,122 @@ +/* IconUIResource.java -- + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +import java.awt.Component; +import java.awt.Graphics; +import java.io.Serializable; + +import javax.swing.Icon; + +/** + * An icon that is marked as <code>UIResource</code>, which + * indicates that it has been installed by a pluggable + * LookAndFeel. Such icons are replaced when the LookAndFeel + * changes. + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class IconUIResource + implements Icon, UIResource, Serializable +{ + /** + * Verified using the <code>serialver</code> tool of Sun JDK 1.4.1_01 + * on GNU/Linux 2.4.18. + */ + static final long serialVersionUID = 3327049506004830542L; + + + /** + * The icon that is wrapped by this <code>IconUIResource</code>. + */ + private Icon delegate; + + + /** + * Constructs a <code>IconUIResource</code> that wraps another + * icon. All messages are forwarded to the delegate icon. + * + * @param delegate the icon that is wrapped by this + * <code>IconUIResource</code>. + */ + public IconUIResource(Icon delegate) + { + this.delegate = delegate; + } + + + /** + * Paints the icon by asking the delegate icon to paint itself. + * + * @param c the Component whose icon is being painted. Some icons + * use this argument to retrieve properties like the + * background color. + * + * @param g the graphics into which the icon will be painted. + * + * @param x the horizontal position of the icon. + * + * @param y the vertical position of the icon. + */ + public void paintIcon(Component c, Graphics g, int x, int y) + { + delegate.paintIcon(c, g, x, y); + } + + + /** + * Returns the width of the icon in pixels. The implementation + * determines and returns the width of the delegate icon. + */ + public int getIconWidth() + { + return delegate.getIconWidth(); + } + + + /** + * Returns the height of the icon in pixels. The implementation + * determines and returns the height of the delegate icon. + */ + public int getIconHeight() + { + return delegate.getIconHeight(); + } +} diff --git a/libjava/classpath/javax/swing/plaf/InputMapUIResource.java b/libjava/classpath/javax/swing/plaf/InputMapUIResource.java new file mode 100644 index 0000000..ae032e5 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/InputMapUIResource.java @@ -0,0 +1,63 @@ +/* InputMapUIResource.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + +import javax.swing.InputMap; + + +/** + * An <code>InputMap</code> that is marked as <code>UIResource</code>, + * which indicates that it has been installed by a pluggable + * LookAndFeel. Such dimensions are replaced when the LookAndFeel + * changes. + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class InputMapUIResource + extends InputMap + implements UIResource +{ + /** + * Constructs a new <code>InputMapUIResource</code>. + */ + public InputMapUIResource() + { + } +} + diff --git a/libjava/classpath/javax/swing/plaf/InsetsUIResource.java b/libjava/classpath/javax/swing/plaf/InsetsUIResource.java new file mode 100644 index 0000000..755d8ad --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/InsetsUIResource.java @@ -0,0 +1,77 @@ +/* InsetsUIResource.java + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +import java.awt.Insets; +import java.io.Serializable; + + +/** + * An <code>Insets</code> that is marked as <code>UIResource</code>, + * which indicates that it has been installed by a pluggable + * LookAndFeel. Such insets are replaced when the LookAndFeel changes. + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class InsetsUIResource + extends Insets + implements Cloneable, UIResource, Serializable +{ + /** + * Determined using the <code>serialver</code> tool + * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5. + */ + static final long serialVersionUID = 5622110143266315421L; + + + /** + * Constructs a new <code>InsetsUIResource</code> given the + * inset at each edge. + * + * @param top the inset at the top, in pixels. + * @param left the inset at the left, in pixels. + * @param bottom the inset at the bottom, in pixels. + * @param right the inset at the right, in pixels. + */ + public InsetsUIResource(int top, int left, int bottom, int right) + { + super(top, left, bottom, right); + } +} diff --git a/libjava/classpath/javax/swing/plaf/InternalFrameUI.java b/libjava/classpath/javax/swing/plaf/InternalFrameUI.java new file mode 100644 index 0000000..fd1e337 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/InternalFrameUI.java @@ -0,0 +1,59 @@ +/* InternalFrameUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a <code>JInternalFrame</code>. + * + * @see javax.swing.JInternalFrame + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class InternalFrameUI + extends ComponentUI +{ + /** + * Constructs a new <code>InternalFrameUI</code>. + */ + public InternalFrameUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/LabelUI.java b/libjava/classpath/javax/swing/plaf/LabelUI.java new file mode 100644 index 0000000..8fc1d71 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/LabelUI.java @@ -0,0 +1,59 @@ +/* LabelUI.java + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a <code>JLabel</code>. + * + * @see javax.swing.JLabel + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class LabelUI + extends ComponentUI +{ + /** + * Constructs a new <code>LabelUI</code>. + */ + public LabelUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/ListUI.java b/libjava/classpath/javax/swing/plaf/ListUI.java new file mode 100644 index 0000000..66d5cf5 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/ListUI.java @@ -0,0 +1,114 @@ +/* ListUI.java -- + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +import java.awt.Point; +import java.awt.Rectangle; + +import javax.swing.JList; + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a <code>JList</code>. + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class ListUI + extends ComponentUI +{ + /** + * Constructs a new <code>ListUI</code>. + */ + public ListUI() + { + } + + + /** + * Determines the cell index which is the closest to the specified + * location. The find out whether the returned cell actually + * contains the location, the caller should also use {@link + * #getCellBounds}. + * + * @param list the <code>JList</code> for which this delegate object + * provides the pluggable user interface. + * + * @param location a point in the <code>JList</code> coordinate + * system. + * + * @return the index of the closest cell, or -1 if the list model + * is empty. + */ + public abstract int locationToIndex(JList list, Point location); + + + /** + * Determines the location of the specified cell. + * + * @param list the <code>JList</code> for which this delegate object + * provides the pluggable user interface. + * + * @param index the zero-based index of the cell whose location shall be + * determined. + * + * @return the position of the top left corner of the cell in the + * <code>JList</code> coordinate system, or <code>null</code> + * if <code>cell</code> does not designate a valid cell. + */ + public abstract Point indexToLocation(JList list, int index); + + + /** + * Determines the bounding box of the rectangle spanned by + * two list indices. + * + * @param list the <code>JList</code> for which this delegate object + * provides the pluggable user interface. + * + * @param index1 the zero-based index of the first cell. + * + * @param index2 the zero-based index of the second cell. + * + * @return the spanned rectangle, or <code>null</code> if either + * <code>index1</code> or <code>index2</code> does not + * designate a valid cell. + */ + public abstract Rectangle getCellBounds(JList list, + int index1, int index2); +} diff --git a/libjava/classpath/javax/swing/plaf/MenuBarUI.java b/libjava/classpath/javax/swing/plaf/MenuBarUI.java new file mode 100644 index 0000000..8835571 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/MenuBarUI.java @@ -0,0 +1,59 @@ +/* MenuBarUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a <code>JMenuBar</code>. + * + * @see javax.swing.JMenuBar + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class MenuBarUI + extends ComponentUI +{ + /** + * Constructs a new <code>MenuBarUI</code>. + */ + public MenuBarUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/MenuItemUI.java b/libjava/classpath/javax/swing/plaf/MenuItemUI.java new file mode 100644 index 0000000..31d7319 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/MenuItemUI.java @@ -0,0 +1,59 @@ +/* MenuItemUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a <code>JMenuItem</code>. + * + * @see javax.swing.JMenuItem + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class MenuItemUI + extends ButtonUI +{ + /** + * Constructs a new <code>MenuItemUI</code>. + */ + public MenuItemUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/OptionPaneUI.java b/libjava/classpath/javax/swing/plaf/OptionPaneUI.java new file mode 100644 index 0000000..13d1caa --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/OptionPaneUI.java @@ -0,0 +1,75 @@ +/* OptionPaneUI.java + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + +import javax.swing.JOptionPane; + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a <code>JOptionPane</code>. + * + * @see javax.swing.JOptionPane + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class OptionPaneUI + extends ComponentUI +{ + /** + * Gives keyboard input focus to the component that represents + * the default value. + * + * @param pane the <code>JOptionPane</code> for which this delegate + * object provides the pluggable user interface. + */ + public abstract void selectInitialValue(JOptionPane pane); + + + /** + * Determines whether the user has provided custom components + * for the options or the message. + * + * @param pane the <code>JOptionPane</code> for which this delegate + * object provides the pluggable user interface. + * + * @return <code>true</code> if the user has supplied any custom + * components; <code>false</code> if all components are + * provided by Swing or a LookAndFeel. + */ + public abstract boolean containsCustomComponents(JOptionPane pane); +} diff --git a/libjava/classpath/javax/swing/plaf/PanelUI.java b/libjava/classpath/javax/swing/plaf/PanelUI.java new file mode 100644 index 0000000..b1171b8 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/PanelUI.java @@ -0,0 +1,58 @@ +/* PanelUI.java + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a <code>JPanel</code>. + * + * @see javax.swing.JPanel + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class PanelUI + extends ComponentUI +{ + /** + * Constructs a new <code>PanelUI</code>. + */ + public PanelUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/PopupMenuUI.java b/libjava/classpath/javax/swing/plaf/PopupMenuUI.java new file mode 100644 index 0000000..c70ad2a --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/PopupMenuUI.java @@ -0,0 +1,117 @@ +/* PopupMenuUI.java -- + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +import java.awt.event.MouseEvent; + +import javax.swing.JPopupMenu; +import javax.swing.Popup; +import javax.swing.PopupFactory; + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a <code>JPopupMenu</code>. + * + * @see javax.swing.JPopupMenu + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class PopupMenuUI + extends ComponentUI +{ + /** + * Constructs a new <code>PopupMenuUI</code>. + */ + public PopupMenuUI() + { + } + + + /** + * Tests whether or not a mouse event triggers a popup menu. + * + * <p>The default implementation calls + * <code>event.isPopupTrigger()</code>, which checks for the gesture + * that is common for the platform on which the application runs. If + * a look and feel wants to employ non-standard conventions for + * triggering a popup menu, it can override this method. + * + * @param event the event to check. + * + * @return <code>true</code> if the event triggers a popup menu; + * <code>false</code> otherwise. + * + * @since 1.3 + */ + public boolean isPopupTrigger(MouseEvent event) + { + return event.isPopupTrigger(); + } + + + /** + * Creates a <code>Popup</code> for displaying the popup menu. The + * default implementation uses the {@link javax.swing.PopupFactory} + * for retrieving a suitable <code>Popup</code>, but subclasses + * might want to override this method if a LookAndFeel needs special + * Popups. + * + * @param popup the <code>JPopupMenu</code> for whose display + * a <code>Popup</code> is needed. + * + * @param x the horizontal position where the popup will be + * displayed. + * + * @param y the vertical position where the popup will be + * displayed. + * + * @return a <code>Popup</code> for showing and hiding + * the menu. + * + * @since 1.4 + */ + public Popup getPopup(JPopupMenu popup, int x, int y) + { + return PopupFactory.getSharedInstance().getPopup( + /* origin/owner of the popup */ popup.getInvoker(), + /* contents */ popup, + x, y); + } +} diff --git a/libjava/classpath/javax/swing/plaf/ProgressBarUI.java b/libjava/classpath/javax/swing/plaf/ProgressBarUI.java new file mode 100644 index 0000000..79c1b95 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/ProgressBarUI.java @@ -0,0 +1,59 @@ +/* ProgressBarUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a <code>JProgressBar</code>. + * + * @see javax.swing.JProgressBar + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class ProgressBarUI + extends ComponentUI +{ + /** + * Constructs a new <code>ProgressBarUI</code>. + */ + public ProgressBarUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/RootPaneUI.java b/libjava/classpath/javax/swing/plaf/RootPaneUI.java new file mode 100644 index 0000000..ff7d0a6 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/RootPaneUI.java @@ -0,0 +1,58 @@ +/* RootPaneUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a <code>JRootPane</code>. + * + * @see javax.swing.JRootPane + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class RootPaneUI + extends ComponentUI +{ + /** + * Constructs a new <code>RootPaneUI</code>. + */ + public RootPaneUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/ScrollBarUI.java b/libjava/classpath/javax/swing/plaf/ScrollBarUI.java new file mode 100644 index 0000000..3cad393 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/ScrollBarUI.java @@ -0,0 +1,58 @@ +/* ScrollBarUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a <code>JScrollBar</code>. + * + * @see javax.swing.JScrollBar + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class ScrollBarUI + extends ComponentUI +{ + /** + * Constructs a new <code>ScrollBarUI</code>. + */ + public ScrollBarUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/ScrollPaneUI.java b/libjava/classpath/javax/swing/plaf/ScrollPaneUI.java new file mode 100644 index 0000000..14d2ac6 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/ScrollPaneUI.java @@ -0,0 +1,59 @@ +/* ScrollPaneUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a <code>JScrollPane</code>. + * + * @see javax.swing.JScrollPane + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class ScrollPaneUI + extends ComponentUI +{ + /** + * Constructs a new <code>ScrollPaneUI</code>. + */ + public ScrollPaneUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/SeparatorUI.java b/libjava/classpath/javax/swing/plaf/SeparatorUI.java new file mode 100644 index 0000000..6855bd0 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/SeparatorUI.java @@ -0,0 +1,58 @@ +/* SeparatorUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a <code>JSeparator</code>. + * + * @see javax.swing.JSeparator + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class SeparatorUI + extends ComponentUI +{ + /** + * Constructs a new <code>SeparatorUI</code>. + */ + public SeparatorUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/SliderUI.java b/libjava/classpath/javax/swing/plaf/SliderUI.java new file mode 100644 index 0000000..775f196 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/SliderUI.java @@ -0,0 +1,59 @@ +/* SliderUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a <code>JSlider</code>. + * + * @see javax.swing.JSlider + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class SliderUI + extends ComponentUI +{ + /** + * Constructs a new <code>SliderUI</code>. + */ + public SliderUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/SpinnerUI.java b/libjava/classpath/javax/swing/plaf/SpinnerUI.java new file mode 100644 index 0000000..fb4a3b1 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/SpinnerUI.java @@ -0,0 +1,59 @@ +/* SpinnerUI.java -- + Copyright (C) 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a <code>JSpinner</code>. + * + * @since 1.4 + * @see javax.swing.JSpinner + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class SpinnerUI + extends ComponentUI +{ + /** + * Constructs a new <code>SpinnerUI</code>. + */ + public SpinnerUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/SplitPaneUI.java b/libjava/classpath/javax/swing/plaf/SplitPaneUI.java new file mode 100644 index 0000000..ea9af2b --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/SplitPaneUI.java @@ -0,0 +1,133 @@ +/* SplitPaneUI.java -- + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +import java.awt.Graphics; + +import javax.swing.JSplitPane; + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a <code>JSplitPane</code>. + * + * @see javax.swing.JSplitPane + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class SplitPaneUI + extends ComponentUI +{ + /** + * Constructs a new <code>SplitPaneUI</code>. + */ + public SplitPaneUI() + { + } + + + /** + * Moves the divider to the location which best respects + * the preferred sizes of the children. + * + * @param pane the <code>JSplitPane</code> for thich this + * delegate provides the look and feel. + */ + public abstract void resetToPreferredSizes(JSplitPane pane); + + + /** + * Moves the divider to the specified location. + * + * @param pane the <code>JSplitPane</code> for thich this + * delegate provides the look and feel. + * + * @param location the new location of the divider. + */ + public abstract void setDividerLocation(JSplitPane pane, + int location); + + + /** + * Determines the current location of the divider. + * + * @param pane the <code>JSplitPane</code> for thich this + * delegate provides the look and feel. + * + * @return the current location of the divider. + */ + public abstract int getDividerLocation(JSplitPane pane); + + + /** + * Determines the minimum location of the divider. + * + * @param pane the <code>JSplitPane</code> for thich this + * delegate provides the look and feel. + * + * @return the leftmost (or topmost) possible location + * of the divider. + */ + public abstract int getMinimumDividerLocation(JSplitPane pane); + + + /** + * Determines the maximum location of the divider. + * + * @param pane the <code>JSplitPane</code> for thich this + * delegate provides the look and feel. + * + * @return the bottommost (or rightmost) possible location + * of the divider. + */ + public abstract int getMaximumDividerLocation(JSplitPane pane); + + + /** + * Called by the <code>JSplitPane</code> after it has finished + * painting its children. + * + * @param pane the <code>JSplitPane</code> for thich this + * delegate provides the look and feel. + * + * @param g the Graphics used for painting. + */ + public abstract void finishedPaintingChildren(JSplitPane pane, + Graphics g); +} diff --git a/libjava/classpath/javax/swing/plaf/TabbedPaneUI.java b/libjava/classpath/javax/swing/plaf/TabbedPaneUI.java new file mode 100644 index 0000000..6ab823b --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/TabbedPaneUI.java @@ -0,0 +1,111 @@ +/* TabbedPaneUI.java -- + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +import java.awt.Rectangle; + +import javax.swing.JTabbedPane; + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a <code>JTabbedPane</code>. + * + * @see javax.swing.JTabbedPane + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class TabbedPaneUI + extends ComponentUI +{ + /** + * Constructs a new <code>TabbedPaneUI</code>. + */ + public TabbedPaneUI() + { + } + + + /** + * Determines which tab lies at a given position. + * + * @param pane the <code>JTabbedPane</code> for which this + * delegate object provides the user interface. + * + * @param x the horizontal position, where zero is the left + * edge of <code>pane</code>. + * + * @param y the vertical position, where zero is the top + * edge of <code>pane</code>. + * + * @return the zero-based index of the tab, or -1 if no + * tab is at the specified position. + */ + public abstract int tabForCoordinate(JTabbedPane pane, + int x, int y); + + + /** + * Calculates the bounding box of a tab. + * + * @param pane the <code>JTabbedPane</code> for which this + * delegate object provides the user interface. + * + * @param index the index of the tab, which must be an integer + * in the range <code>[0 .. pane.getTabCount() - 1]</code>. + * + * @return the bounding box of the <code>index</code>-th tab, + * in the coordinate system of <code>pane</code>. + */ + public abstract Rectangle getTabBounds(JTabbedPane pane, int index); + + + /** + * Determines how many runs are used to display tabs. + * + * @param pane the <code>JTabbedPane</code> for which this + * delegate object provides the user interface. + * + * @return the number of tab runs. + * + * @see javax.swing.JTabbedPane#getTabRunCount() + */ + public abstract int getTabRunCount(JTabbedPane pane); +} + diff --git a/libjava/classpath/javax/swing/plaf/TableHeaderUI.java b/libjava/classpath/javax/swing/plaf/TableHeaderUI.java new file mode 100644 index 0000000..f23ca74 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/TableHeaderUI.java @@ -0,0 +1,59 @@ +/* TableHeaderUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a <code>JTableHeader</code>. + * + * @see javax.swing.table.JTableHeader + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class TableHeaderUI + extends ComponentUI +{ + /** + * Constructs a new <code>TableHeaderUI</code>. + */ + public TableHeaderUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/TableUI.java b/libjava/classpath/javax/swing/plaf/TableUI.java new file mode 100644 index 0000000..e56bcd1 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/TableUI.java @@ -0,0 +1,59 @@ +/* TableUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a <code>JTable</code>. + * + * @see javax.swing.JTable + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class TableUI + extends ComponentUI +{ + /** + * Constructs a new <code>TableUI</code>. + */ + public TableUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/TextUI.java b/libjava/classpath/javax/swing/plaf/TextUI.java new file mode 100644 index 0000000..86d1f1f --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/TextUI.java @@ -0,0 +1,284 @@ +/* TextUI.java -- + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +import java.awt.Point; +import java.awt.Rectangle; + +import javax.swing.text.BadLocationException; +import javax.swing.text.EditorKit; +import javax.swing.text.JTextComponent; +import javax.swing.text.Position; +import javax.swing.text.View; + +/** + * An abstract base class for delegates that provide the user + * interface for text editors. + * + * @see javax.swing.text.JTextComponent + * + * @author Ronald Veldema (rveldema@cs.vu.nl) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class TextUI + extends ComponentUI +{ + /** + * Constructs a new <code>TextUI</code>. + */ + public TextUI() + { + } + + + /** + * Calculates the geometric extent of the character at the + * given offset. + * + * @param tc the <code>JTextComponent</code> for which this + * delegate object provides the user interface. + * + * @param pos the zero-based index of the character into the + * document model. + * + * @return the bounding box of the character at index + * <code>pos</code>, in view coordinates. + * + * @throws BadLocationException if <code>pos</code> does not + * designate a valid position in the document model. + * + * @see javax.swing.text.View#modelToView(int, + * javax.swing.text.Position.Bias, int, + * javax.swing.text.position.Bias, java.awt.Shape) + */ + public abstract Rectangle modelToView(JTextComponent tc, int pos) + throws BadLocationException; + + + /** + * Calculates the geometric extent of the character at the + * given offset. + * + * @param tc the <code>JTextComponent</code> for which this + * delegate object provides the user interface. + * + * @param pos the zero-based index of the character into the + * document model. + * + * @param bias whether to take the character before or after the + * caret position indicated by <code>pos</code>. The value + * must be either {@link + * javax.swing.text.Position.Bias#Backward} or {@link + * javax.swing.text.Position.Bias#Forward}. + * + * @return the bounding box of the character at index + * <code>pos</code>, in view coordinates. + * + * @throws BadLocationException if <code>pos</code> does not + * designate a valid position in the document model. + * + * @see javax.swing.text.View#modelToView(int, + * javax.swing.text.Position.Bias, int, + * javax.swing.text.position.Bias, java.awt.Shape) + */ + public abstract Rectangle modelToView(JTextComponent tc, int pos, + Position.Bias bias) + throws BadLocationException; + + + /** + * Finds the caret position which is closest to the specified visual + * location. + * + * @param tc the <code>JTextComponent</code> for which this + * delegate object provides the user interface. + * + * @param loc the position in view coordinates. + * + * @return the caret position which is closest to <code>loc</code>. + * + * @see #viewToModel(JTextComponent, Point, Position.Bias[]) + */ + public abstract int viewToModel(JTextComponent t, Point pt); + + + /** + * Finds the caret position which is closest to the specified visual + * location. + * + * @param tc the <code>JTextComponent</code> for which this + * delegate object provides the user interface. + * + * @param loc the position in view coordinates. + * + * @param outBias an array whose size must be at least one. + * After the call, <code>outBias[0]</code> will indicate + * whether <code>loc</code> is in the glyph before + * (<code>Position.Bias.Backward</code>) or after + * (<code>Position.Bias.Forward</code>) the returned + * caret position. + * + * @return the caret position which is closest to <code>loc</code>. + */ + public abstract int viewToModel(JTextComponent tc, Point loc, + Position.Bias[] outBias); + + + + /** + * Calculates the caret position that is visually next to the given + * position. This is useful to determine where to move the caret + * after the user has pressed an arrow key. + * + * @param tc the <code>JTextComponent</code> for which this + * delegate object provides the user interface. + * + * @param pos the current caret position, a zero-based index + * into the document model. + * + * @param bias whether to take the character before or after the + * caret position indicated by <code>pos</code>. The value + * must be either {@link + * javax.swing.text.Position.Bias#Backward} or {@link + * javax.swing.text.Position.Bias#Forward}. + * + * @param direction the visual direction. Pass + * {@link javax.swing.SwingConstants#WEST} for the left + * arrow key, {@link javax.swing.SwingConstants#EAST} + * for the right arrow key, {@link + * javax.swing.SwingConstants#NORTH} for the up arrow + * key, or {@link javax.swing.SwingConstants#SOUTH} + * for the down arrow key. + * + * @throws BadLocationException if <code>pos</code> does not + * designate a valid position in the document model. + * + * @throws IllegalArgumentException if <code>direction</code> + * is not one of <code>Position.Bias.Forward</code> + * or <code>Position.Biad.Backward</code>. + */ + public abstract int getNextVisualPositionFrom(JTextComponent tc, + int pos, + Position.Bias bias, + int direction, + Position.Bias[] outBias) + throws BadLocationException; + + + /** + * Repaints a range of characters. + * + * @param tc the <code>JTextComponent</code> for which this + * delegate object provides the user interface. + * + * @param start the first character in the range that needs + * painting, indicated as an index into the document model. + * + * @param end the last character in the range that needs + * painting, indicated as an index into the document model. + * <code>end</code> must be greater than or equal to + * <code>start</code>. + */ + public abstract void damageRange(JTextComponent tc, int start, int end); + + + /** + * Repaints a range of characters, also specifying the bias for the + * start and end of the range. + * + * @param tc the <code>JTextComponent</code> for which this + * delegate object provides the user interface. + * + * @param start the first character in the range that needs + * painting, indicated as an index into the document model. + * + * @param end the last character in the range that needs + * painting, indicated as an index into the document model. + * <code>end</code> must be greater than or equal to + * <code>start</code>. + */ + public abstract void damageRange(JTextComponent tc, + int start, int end, + Position.Bias startBias, + Position.Bias endBias); + + + /** + * Retrieves the <code>EditorKit</code> managing policies and + * persistent state. + * + * @param tc the <code>JTextComponent</code> for which this + * delegate object provides the user interface. + * + * @return the <code>EditorKit</code> used by <code>tc</code>. + */ + public abstract EditorKit getEditorKit(JTextComponent tc); + + + /** + * Retrieves the root of the view tree that visually presents + * the text. + * + * @param tc the <code>JTextComponent</code> for which this + * delegate object provides the user interface. + * + * @return the root <code>View</code> used by <code>tc</code>. + */ + public abstract View getRootView(JTextComponent tc); + + + /** + * Returns a String for presenting a tool tip at the specified + * location. + * + * @param tc the <code>JTextComponent</code> for which this + * delegate object provides the user interface. + * + * @param loc the location for which the tool tip is requested. + * + * @return the text for the tool tip, or <code>null</code> to + * display no tool tip. + * + * @since 1.4 + */ + public String getToolTipText(JTextComponent tc, Point loc) + { + return null; + } +} diff --git a/libjava/classpath/javax/swing/plaf/ToolBarUI.java b/libjava/classpath/javax/swing/plaf/ToolBarUI.java new file mode 100644 index 0000000..730cf488 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/ToolBarUI.java @@ -0,0 +1,59 @@ +/* ToolBarUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a <code>JToolBar</code>. + * + * @see javax.swing.JToolBar + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class ToolBarUI + extends ComponentUI +{ + /** + * Constructs a new <code>ToolBarUI</code>. + */ + public ToolBarUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/ToolTipUI.java b/libjava/classpath/javax/swing/plaf/ToolTipUI.java new file mode 100644 index 0000000..4383d0e --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/ToolTipUI.java @@ -0,0 +1,59 @@ +/* ToolTipUI.java -- + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf; + + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a <code>JToolTip</code>. + * + * @see javax.swing.JToolTip + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class ToolTipUI + extends ComponentUI +{ + /** + * Constructs a new <code>ToolTipUI</code>. + */ + public ToolTipUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/TreeUI.java b/libjava/classpath/javax/swing/plaf/TreeUI.java new file mode 100644 index 0000000..e32952d --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/TreeUI.java @@ -0,0 +1,211 @@ +/* TreeUI.java -- + Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +import java.awt.Rectangle; + +import javax.swing.JTree; +import javax.swing.tree.TreePath; + +/** + * An abstract base class for delegates that provide the user + * interface for <code>JTree</code>. + * + * @see javax.swing.JTree + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class TreeUI + extends ComponentUI +{ + /** + * Constructs a new <code>TreeUI</code>. + */ + public TreeUI() + { + } + + + /** + * Determines the geometric extent of the label that is + * drawn for a path. + * + * @param tree the <code>JTree</code> for which this delegate + * object provides the user interface. + * + * @param path the path whose label extent is requested. + * + * @return a rectangle enclosing the label, or <code>null</code> + * if <code>path</code> contains invalid nodes. + */ + public abstract Rectangle getPathBounds(JTree tree, TreePath path); + + + /** + * Creates a <code>TreePath</code> for the specified row. + * + * @param tree the <code>JTree</code> for which this delegate + * object provides the user interface. + * + * @param row the index of the row, which should be a number + * in the range <code>[0, getRowCount(tree) - 1]</code>. + * + * @return a <code>TreePath</code> for the specified row, or + * <code>null</code> if <code>row</code> is outside + * the valid range. + */ + public abstract TreePath getPathForRow(JTree tree, int row); + + + /** + * Determines in which row a <code>TreePath</code> is currently + * being displayed. + * + * @param tree the <code>JTree</code> for which this delegate + * object provides the user interface. + * + * @param path the path for which the caller wants to know + * in which row it is being displayed. + * + * @return a number in the range <code>[0, getRowCount(tree) + * - 1]</code> if the path is currently on display; + * <code>-1</code> if the path is not shown to the + * user. + */ + public abstract int getRowForPath(JTree tree, TreePath path); + + + /** + * Counts how many rows are currently displayed. + * + * @param tree the <code>JTree</code> for which this delegate + * object provides the user interface. + * + * @return the number of visible rows. + */ + public abstract int getRowCount(JTree tree); + + + /** + * Finds the path that is closest to the specified position. + * + * <p><img src="doc-files/TreeUI-1.png" width="300" height="250" + * alt="[A screen shot of a JTree]" /> + * + * <p>As shown by the above illustration, the bounds of the + * closest path do not necessarily need to contain the passed + * location. + * + * @param tree the <code>JTree</code> for which this delegate + * object provides the user interface. + * + * @param x the horizontal location, relative to the origin + * of <code>tree</code>. + * + * @param y the vertical location, relative to the origin + * of <code>tree</code>. + * + * @return the closest path, or <code>null</code> if the + * tree is currenlty not displaying any paths at all. + */ + public abstract TreePath getClosestPathForLocation(JTree tree, + int x, int y); + + + /** + * Determines whether the user is currently editing a tree cell. + * + * @param tree the <code>JTree</code> for which this delegate + * object provides the user interface. + * + * @see #getEditingPath + */ + public abstract boolean isEditing(JTree tree); + + + /** + * Stops editing a tree cell, committing the entered value into the + * tree’s model. If no editing session is active, or if the + * active editor does not agree to stopping, nothing happens. In + * some look and feels, this action happens when the user has + * pressed the enter key. + * + * @param tree the <code>JTree</code> for which this delegate + * object provides the user interface. + * + * @return <code>false</code> if the editing still goes on because + * the cell editor has objected to stopping the session; + * <code>true</code> if editing has been stopped. + */ + public abstract boolean stopEditing(JTree tree); + + + /** + * Cancels editing a tree cell, discarding any entered value. + * If no editing session is active, nothing happens. The cell + * editor is not given an opportunity to veto the canceling. + * In some look and feels, this action happens when the user has + * pressed the escape key. + * + * @param tree the <code>JTree</code> for which this delegate + * object provides the user interface. + */ + public abstract void cancelEditing(JTree tree); + + + /** + * Starts a session to edit a tree cell. If the cell editor + * rejects editing the cell, it will just be selected. + * + * @param tree the <code>JTree</code> for which this delegate + * object provides the user interface. + * + * @param path the cell to edit. + */ + public abstract void startEditingAtPath(JTree tree, TreePath path); + + + /** + * Retrieves the tree cell that is currently being edited. + * + * @return the currently edited path, or <code>null</code> + * if no editing session is currently active. + */ + public abstract TreePath getEditingPath(JTree tree); +} diff --git a/libjava/classpath/javax/swing/plaf/UIResource.java b/libjava/classpath/javax/swing/plaf/UIResource.java new file mode 100644 index 0000000..1e28280 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/UIResource.java @@ -0,0 +1,55 @@ +/* UIResource.java + Copyright (C) 1999 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + +/** + * This public interface is used to designate which objects were created by + * <code>ComponentUI</code> delegates. When uninstalling the user public interface + * renderer with <code>ComponentUI.uninstallUI()</code> the renderer + * property is set to <code>null</code>. + * <br> + * A comparison against null can be used with all properties except for + * the <code>java.awt.Component</code> properties font, foreground, and + * background. The container can provide the value of the properties if + * they are initialized or set to <code>null</code>. + * + * @author Brian Jones + * @see java.lang.ComponentUI + */ +public interface UIResource { } diff --git a/libjava/classpath/javax/swing/plaf/ViewportUI.java b/libjava/classpath/javax/swing/plaf/ViewportUI.java new file mode 100644 index 0000000..087938f --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/ViewportUI.java @@ -0,0 +1,60 @@ +/* ViewportUI.java + Copyright (C) 2002, 2003 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf; + + +/** + * An abstract base class for delegates that implement the pluggable + * look and feel for a <code>JViewport</code>. + * + * @see javax.swing.JViewport + * + * @author Andrew Selkirk (aselkirk@sympatico.ca) + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public abstract class ViewportUI + extends ComponentUI +{ + /** + * Constructs a new <code>ViewportUI</code>. + */ + public ViewportUI() + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicArrowButton.java b/libjava/classpath/javax/swing/plaf/basic/BasicArrowButton.java new file mode 100644 index 0000000..4da4691 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicArrowButton.java @@ -0,0 +1,350 @@ +/* BasicArrowButton.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Polygon; +import java.awt.Rectangle; + +import javax.swing.JButton; +import javax.swing.SwingConstants; +import javax.swing.border.Border; + +/** + * This class draws simple arrow buttons for the Basic Look and Feel. + */ +public class BasicArrowButton extends JButton implements SwingConstants +{ + /** The default size of the Arrow buttons. */ + private static int defaultSize = 10; + + /** The Polygon that points up. */ + private static Polygon upIcon = new Polygon(new int[] { 0, 5, 9 }, + new int[] { 7, 2, 7 }, 3); + + /** The Polygon that points down. */ + private static Polygon downIcon = new Polygon(new int[] { 1, 5, 9 }, + new int[] { 3, 7, 3 }, 3); + + /** The Polygon that points left. */ + private static Polygon leftIcon = new Polygon(new int[] { 7, 3, 7 }, + new int[] { 1, 5, 9 }, 3); + + /** The Polygon that points right. */ + private static Polygon rightIcon = new Polygon(new int[] { 3, 7, 3 }, + new int[] { 1, 5, 9 }, 3); + + /** The direction to point in. */ + protected int direction; + + /** + * The color the arrow is painted in if disabled and the bottom and right + * edges of the button. + * This is package-private to avoid an accessor method. + */ + transient Color shadow = Color.GRAY; + + /** + * The color the arrow is painted in if enabled and the bottom and right + * edges of the button. + * This is package-private to avoid an accessor method. + */ + transient Color darkShadow = Color.DARK_GRAY; + + /** + * The top and left edges of the button. + * This is package-private to avoid an accessor method. + */ + transient Color highlight = Color.WHITE; + + /** The border around the ArrowButton. */ + private transient Border buttonBorder = new Border() + { + public Insets getBorderInsets(Component c) + { + return new Insets(2, 2, 2, 2); + } + + public boolean isBorderOpaque() + { + return true; + } + + public void paintBorder(Component c, Graphics g, int x, int y, int w, + int h) + { + Color saved = g.getColor(); + g.setColor(highlight); + + g.drawLine(x + 1, y + 1, x + w - 1, y + 1); + g.drawLine(x + 1, y + 1, x + 1, y + h - 1); + + g.setColor(shadow); + + g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1); + g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1); + + g.setColor(darkShadow); + + g.drawLine(x, y + h, x + w, y + h); + g.drawLine(x + w, y, x + w, y + h); + + g.setColor(saved); + } + }; + + /** + * Creates a new BasicArrowButton object. + * + * @param direction The direction the arrow points in. + */ + public BasicArrowButton(int direction) + { + super(); + setBorder(buttonBorder); + setDirection(direction); + } + + /** + * Creates a new BasicArrowButton object with the given colors and + * direction. + * + * @param direction The direction to point in. + * @param background The background color. + * @param shadow The shadow color. + * @param darkShadow The dark shadow color. + * @param highlight The highlight color. + */ + public BasicArrowButton(int direction, Color background, Color shadow, + Color darkShadow, Color highlight) + { + this(direction); + setBackground(background); + this.shadow = shadow; + this.darkShadow = darkShadow; + this.highlight = highlight; + } + + /** + * This method returns whether the focus can traverse to this component. + * + * @return Whether the focus can traverse to this component. + */ + public boolean isFocusTraversable() + { + return false; + } + + /** + * This method returns the direction of the arrow. + * + * @return The direction of the arrow. + */ + public int getDirection() + { + return direction; + } + + /** + * This method changes the direction of the arrow. + * + * @param dir The new direction of the arrow. + */ + public void setDirection(int dir) + { + this.direction = dir; + } + + /** + * This method paints the arrow button. The painting is delegated to the + * paintTriangle method. + * + * @param g The Graphics object to paint with. + */ + public void paint(Graphics g) + { + super.paint(g); + Insets insets = getInsets(); + Rectangle bounds = getBounds(); + int x = insets.left + + (bounds.width - insets.left - insets.right - defaultSize) / 2; + int y = insets.top + + (bounds.height - insets.left - insets.right - defaultSize) / 2; + paintTriangle(g, x, y, defaultSize, direction, isEnabled()); + } + + /** + * This method returns the preferred size of the arrow button. + * + * @return The preferred size. + */ + public Dimension getPreferredSize() + { + Insets insets = getInsets(); + int w = defaultSize + insets.left + insets.right; + int h = defaultSize + insets.top + insets.bottom; + + return new Dimension(w, h); + } + + /** + * This method returns the minimum size of the arrow button. + * + * @return The minimum size. + */ + public Dimension getMinimumSize() + { + return getPreferredSize(); + } + + /** + * This method returns the maximum size of the arrow button. + * + * @return The maximum size. + */ + public Dimension getMaximumSize() + { + return getPreferredSize(); + } + + /** + * The method paints a triangle with the given size and direction at the + * given x and y coordinates. + * + * @param g The Graphics object to paint with. + * @param x The x coordinate to paint at. + * @param y The y coordinate to paint at. + * @param size The size of the icon. + * @param direction The direction of the icon. + * @param isEnabled Whether it is enabled. + */ + public void paintTriangle(Graphics g, int x, int y, int size, int direction, + boolean isEnabled) + { + Polygon arrow = null; + switch (direction) + { + case NORTH: + arrow = upIcon; + break; + case SOUTH: + arrow = downIcon; + break; + case EAST: + case RIGHT: + arrow = rightIcon; + break; + case WEST: + case LEFT: + arrow = leftIcon; + break; + } + + int[] xPoints = arrow.xpoints; + int[] yPoints = arrow.ypoints; + int x1; + int y1; + int x2; + int y2; + x1 = y1 = x2 = y2 = 0; + + if (size != defaultSize) + { + float scale = size * 1f / defaultSize; + for (int i = 0; i < 3; i++) + { + xPoints[i] *= scale; + yPoints[i] *= scale; + } + } + g.translate(x, y); + + switch (direction) + { + case NORTH: + x1 = xPoints[0] + 2; + y1 = yPoints[0]; + y2 = y1; + x2 = xPoints[2] - 1; + break; + case SOUTH: + x1 = xPoints[1]; + y1 = yPoints[1] + 1; + x2 = xPoints[2] - 1; + y2 = yPoints[2]; + break; + case LEFT: + case WEST: + x1 = xPoints[0] + 1; + y1 = yPoints[0] + 1; + x2 = x1; + y2 = yPoints[2] + 1; + break; + case RIGHT: + case EAST: + x1 = xPoints[2]; + y1 = yPoints[2] + 1; + x2 = xPoints[1] - 1; + y2 = yPoints[1] + 1; + break; + } + Color saved = g.getColor(); + + if (isEnabled) + { + g.setColor(Color.DARK_GRAY); + + if (arrow != null) + g.fillPolygon(xPoints, yPoints, 3); + } + else + { + g.setColor(Color.GRAY); + g.fillPolygon(xPoints, yPoints, 3); + g.setColor(Color.WHITE); + g.drawLine(x1, y1, x2, y2); + } + g.setColor(saved); + g.translate(-x, -y); + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicBorders.java b/libjava/classpath/javax/swing/plaf/basic/BasicBorders.java new file mode 100644 index 0000000..e7d6e43 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicBorders.java @@ -0,0 +1,1814 @@ +/* BasicBorders.java -- + Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Rectangle; +import java.io.Serializable; + +import javax.swing.AbstractButton; +import javax.swing.ButtonModel; +import javax.swing.JButton; +import javax.swing.JPopupMenu; +import javax.swing.JSplitPane; +import javax.swing.JToolBar; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.border.AbstractBorder; +import javax.swing.border.BevelBorder; +import javax.swing.border.Border; +import javax.swing.plaf.BorderUIResource; +import javax.swing.plaf.UIResource; +import javax.swing.text.JTextComponent; + +/** + * Provides various borders for the Basic look and feel. + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class BasicBorders +{ + /** + * A MarginBorder that gets shared by multiple components. + * Created on demand by the private helper function {@link + * #getMarginBorder()}. + */ + private static MarginBorder sharedMarginBorder; + + + /** + * Returns a border for drawing push buttons. + * + * <p>The colors of the border are retrieved from the + * <code>UIDefaults</code> of the currently active look and feel + * using the keys <code>“Button.shadow”</code>, + * <code>“Button.darkShadow”</code>, + * <code>“Button.light”</code>, and + * <code>“Button.highlight”</code>. + * + * <p><img src="doc-files/BasicBorders.ButtonBorder-1.png" width="300" + * height="170" alt="[A screen shot of the returned border]" /> + * + * @return a {@link + * javax.swing.plaf.BorderUIResource.CompoundBorderUIResource} + * whose outer border is a {@link ButtonBorder} and whose + * inner border is a {@link MarginBorder}. + */ + public static Border getButtonBorder() + { + UIDefaults defaults; + Border outer; + + defaults = UIManager.getLookAndFeelDefaults(); + + /* The keys for UIDefaults have been determined by writing a + * test program that dumps the UIDefaults to stdout; that program + * was run on a JDK 1.4.1_01 for GNU/Linux. Note that in the API, + * the key "light" is usually called "highlight", and "highlight" + * is usually called "lightHighlight". + */ + outer = new ButtonBorder(defaults.getColor("Button.shadow"), + defaults.getColor("Button.darkShadow"), + defaults.getColor("Button.light"), + defaults.getColor("Button.highlight")); + + /* While the inner border is shared between multiple buttons, + * we do not share the outer border because ButtonBorders store + * their border colors. We cannot guarantee that the colors + * (which come from UIDefaults) are unchanged between invocations + * of getButtonBorder. We could store the last colors, and share + * the button border if the colors are the same as in the last + * invocation, but it probably is not worth the effort. + */ + return new BorderUIResource.CompoundBorderUIResource( + outer, + /* inner */ getMarginBorder()); + } + + + /** + * Returns a border for drawing radio buttons. + * + * <p>The colors of the border are retrieved from the + * <code>UIDefaults</code> of the currently active look and feel + * using the keys <code>“RadioButton.shadow”</code>, + * <code>“RadioButton.darkShadow”</code>, + * <code>“RadioButton.light”</code>, and + * <code>“RadioButton.highlight”</code>. + * + * <p><img src="doc-files/BasicBorders.RadioButtonBorder-1.png" width="300" + * height="135" alt="[A screen shot of the returned border]" /> + * + * @return a {@link + * javax.swing.plaf.BorderUIResource.CompoundBorderUIResource} + * whose outer border is a {@link RadioButtonBorder} and whose + * inner border is a {@link MarginBorder}. + */ + public static Border getRadioButtonBorder() + { + UIDefaults defaults; + Border outer; + + defaults = UIManager.getLookAndFeelDefaults(); + + /* The keys for UIDefaults have been determined by writing a + * test program that dumps the UIDefaults to stdout; that program + * was run on a JDK 1.4.1_01 for GNU/Linux. Note that in the API, + * the key "light" is usually called "highlight", and "highlight" + * is usually called "lightHighlight". + */ + outer = new RadioButtonBorder( + defaults.getColor("RadioButton.shadow"), + defaults.getColor("RadioButton.darkShadow"), + defaults.getColor("RadioButton.light"), + defaults.getColor("RadioButton.highlight")); + + /* While the inner border is shared between multiple buttons, we + * do not share the outer border because RadioButtonBorders, being + * ButtonBorders, store their border colors. We cannot guarantee + * that the colors (which come from UIDefaults) are unchanged + * between invocations of getButtonBorder. We could store the last + * colors, and share the button border if the colors are the same + * as in the last invocation, but it probably is not worth the + * effort. + */ + return new BorderUIResource.CompoundBorderUIResource( + outer, + /* inner */ getMarginBorder()); + } + + + /** + * Returns a border for drawing toggle buttons. + * + * <p>The colors of the border are retrieved from the + * <code>UIDefaults</code> of the currently active look and feel + * using the keys <code>“ToggleButton.shadow”</code>, + * <code>“ToggleButton.darkShadow”</code>, + * <code>“ToggleButton.light”</code>, and + * <code>“ToggleButton.highlight”</code>. + * + * <p><img src="doc-files/BasicBorders.ToggleButtonBorder-1.png" width="270" + * height="135" alt="[A screen shot of the returned border]" /> + * + * @return a {@link + * javax.swing.plaf.BorderUIResource.CompoundBorderUIResource} + * whose outer border is a {@link ToggleButtonBorder} and whose + * inner border is a {@link MarginBorder}. + */ + public static Border getToggleButtonBorder() + { + UIDefaults defaults; + Border outer; + + defaults = UIManager.getLookAndFeelDefaults(); + + /* The keys for UIDefaults have been determined by writing a + * test program that dumps the UIDefaults to stdout; that program + * was run on a JDK 1.4.1_01 for GNU/Linux. Note that in the API, + * the key "light" is usually called "highlight", and "highlight" + * is usually called "lightHighlight". + */ + outer = new ToggleButtonBorder( + defaults.getColor("ToggleButton.shadow"), + defaults.getColor("ToggleButton.darkShadow"), + defaults.getColor("ToggleButton.light"), + defaults.getColor("ToggleButton.highlight")); + + /* While the inner border is shared between multiple buttons, we + * do not share the outer border because ToggleButtonBorders, being + * ButtonBorders, store their border colors. We cannot guarantee + * that the colors (which come from UIDefaults) are unchanged + * between invocations of getButtonBorder. We could store the last + * colors, and share the button border if the colors are the same + * as in the last invocation, but it probably is not worth the + * effort. + */ + return new BorderUIResource.CompoundBorderUIResource( + outer, + /* inner */ getMarginBorder()); + } + + + /** + * Returns a border for drawing a two-pixel thick separator line + * below menu bars. + * + * <p>The colors of the border are retrieved from the + * <code>UIDefaults</code> of the currently active look and feel + * using the keys <code>“MenuBar.shadow”</code> and + * <code>“MenuBar.highlight”</code>. + * + * <p><img src="doc-files/BasicBorders.MenuBarBorder-1.png" width="500" + * height="140" alt="[A screen shot of a JMenuBar with this border]" /> + * + * @return a {@link MenuBarBorder}. + * + * @see javax.swing.JMenuBar + */ + public static Border getMenuBarBorder() + { + UIDefaults defaults; + + /* See comment in methods above for why this border is not shared. */ + defaults = UIManager.getLookAndFeelDefaults(); + return new MenuBarBorder(defaults.getColor("MenuBar.shadow"), + defaults.getColor("MenuBar.highlight")); + } + + + /** + * Returns a border for drawing a one-pixel thick border around + * split panes that are interrupted where the divider joins the + * border. + * + * <p>The colors of the border are retrieved from the + * <code>UIDefaults</code> of the currently active look and feel + * using the keys <code>“SplitPane.darkShadow”</code> and + * <code>“SplitPane.highlight”</code>. + * + * <p><img src="doc-files/BasicBorders.SplitPaneBorder-1.png" width="520" + * height="200" alt="[A screen shot for JSplitPane.HORIZONTAL_SPLIT]" /> + * + * <p><img src="doc-files/BasicBorders.SplitPaneBorder-2.png" width="520" + * height="200" alt="[A screen shot for JSplitPane.VERTICAL_SPLIT]" /> + * + * @return a {@link SplitPaneBorder}. + * + * @see javax.swing.JSplitPane + * @see #getSplitPaneDividerBorder() + */ + public static Border getSplitPaneBorder() + { + UIDefaults defaults; + + /* See comment in methods above for why this border is not shared. */ + defaults = UIManager.getLookAndFeelDefaults(); + return new SplitPaneBorder(defaults.getColor("SplitPane.highlight"), + defaults.getColor("SplitPane.darkShadow")); + } + + + /** + * Returns a border for drawing a one-pixel thick border around + * the divider of split panes. + * + * <p>The colors of the edges that are adjacent to the child components + * of the <code>JSplitPane</code> are retrieved from the + * <code>UIDefaults</code> of the currently active look and feel + * using the keys <code>“SplitPane.darkShadow”</code> and + * <code>“SplitPane.highlight”</code>. The color of the + * other two edges is the background color of the divider. + * + * <p><img src="doc-files/BasicBorders.SplitPaneDividerBorder-1.png" + * width="520" height="200" alt= + * "[A screen shot for JSplitPane.HORIZONTAL_SPLIT]" /> + * + * @return an instance of <code>SplitPaneDividerBorder</code>, which is + * not a public API class of this package. + * + * @see javax.swing.JSplitPane + * @see javax.swing.plaf.basic.BasicSplitPaneDivider + * @see #getSplitPaneBorder() + * + * @since 1.3 + */ + public static Border getSplitPaneDividerBorder() + { + UIDefaults defaults; + + /* See comment in methods above for why this border is not shared. */ + defaults = UIManager.getLookAndFeelDefaults(); + return new SplitPaneDividerBorder( + defaults.getColor("SplitPane.highlight"), + defaults.getColor("SplitPane.darkShadow")); + } + + + /** + * Returns a border for drawing a border around a text field + * that makes the field appear as etched into the surface. + * + * <p>The colors of the border are retrieved from the + * <code>UIDefaults</code> of the currently active look and feel + * using the keys <code>“TextField.shadow”</code>, + * <code>“TextField.darkShadow”</code>, + * <code>“TextField.light”</code>, and + * <code>“TextField.highlight”</code>. + * + * <p><img src="doc-files/BasicBorders.FieldBorder-1.png" width="500" + * height="200" alt="[A screen shot of a border returned by + * this method]" /> + * + * @return an instance of {@link FieldBorder}. + * + * @see javax.swing.JTextField + * @see javax.swing.text.JTextComponent + */ + public static Border getTextFieldBorder() + { + UIDefaults defaults; + + /* See comment in methods above for why this border is not shared. */ + defaults = UIManager.getLookAndFeelDefaults(); + return new FieldBorder( + defaults.getColor("TextField.shadow"), + defaults.getColor("TextField.darkShadow"), + defaults.getColor("TextField.light"), + defaults.getColor("TextField.highlight")); + } + + + /** + * Returns a two-pixel thick, green + * <code>LineBorderUIResource</code>. This is so ugly that look and + * feels better use different borders for their progress bars, or + * they will look really terrible. + * + * <p><img src="doc-files/BasicBorders-1.png" width="120" height="80" + * alt="[A screen shot of a border returned by this method]" /> + */ + public static Border getProgressBarBorder() + { + /* There does not seem to exist a way to parametrize the color + * or thickness of the border through UIDefaults. + */ + return new BorderUIResource.LineBorderUIResource(Color.green, 2); + } + + + /** + * Returns a border that is composed of a raised bevel border and a + * one-pixel thick line border. + * + * <p><img src="doc-files/BasicBorders-2.png" width="300" height="200" + * alt="[A screen shot of a border returned by this method]" /> + * + * <p>The colors of the border are retrieved from the + * <code>UIDefaults</code> of the currently active look and feel + * using the keys <code>“InternalFrame.borderShadow”</code>, + * <code>“InternalFrame.borderDarkShadow”</code>, + * <code>“InternalFrame.borderLight”</code>, + * <code>“InternalFrame.borderHighlight”</code>, and + * (for the inner one-pixel thick line) + * <code>“InternalFrame.borderColor”</code>. + */ + public static Border getInternalFrameBorder() + { + UIDefaults defaults; + Color shadow, darkShadow, highlight, lightHighlight, line; + + /* See comment in methods above for why this border is not shared. */ + defaults = UIManager.getLookAndFeelDefaults(); + + shadow = defaults.getColor("InternalFrame.borderShadow"); + darkShadow = defaults.getColor("InternalFrame.borderDarkShadow"); + highlight = defaults.getColor("InternalFrame.borderLight"); + lightHighlight = defaults.getColor("InternalFrame.borderHighlight"); + line = defaults.getColor("InternalFrame.borderColor"); + + return new BorderUIResource.CompoundBorderUIResource( + /* outer border */ + new BorderUIResource.BevelBorderUIResource( + BevelBorder.RAISED, + (highlight != null) ? highlight : Color.lightGray, + (lightHighlight != null) ? lightHighlight : Color.white, + (darkShadow != null) ? darkShadow : Color.black, + (shadow != null) ? shadow : Color.gray), + + /* inner border */ + new BorderUIResource.LineBorderUIResource( + (line != null) ? line : Color.lightGray)); + } + + + /** + * Returns a shared MarginBorder. + */ + static Border getMarginBorder() // intentionally not public + { + /* Swing is not designed to be thread-safe, so there is no + * need to synchronize the access to the global variable. + */ + if (sharedMarginBorder == null) + sharedMarginBorder = new MarginBorder(); + + return sharedMarginBorder; + } + + + /** + * A border whose appearance depends on the state of + * the enclosed button. + * + * <p><img src="doc-files/BasicBorders.ButtonBorder-1.png" width="300" + * height="170" alt="[A screen shot of this border]" /> + * + * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class ButtonBorder + extends AbstractBorder + implements Serializable, UIResource + { + /** + * Determined using the <code>serialver</code> tool + * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5. + */ + static final long serialVersionUID = -157053874580739687L; + + + /** + * The color for drawing the shaded parts of the border. + * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel + */ + protected Color shadow; + + + /** + * The color for drawing the dark shaded parts of the border. + * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel + */ + protected Color darkShadow; + + + /** + * The color for drawing the highlighted parts of the border. + * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel + */ + protected Color highlight; + + + /** + * The color for drawing the bright highlighted parts of the border. + * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel + */ + protected Color lightHighlight; + + + /** + * Constructs a new border for drawing a button in the Basic + * look and feel. + * + * @param shadow the shadow color. + * @param darkShadow a darker variant of the shadow color. + * @param highlight the highlight color. + * @param lightHighlight a brighter variant of the highlight color. + */ + public ButtonBorder(Color shadow, Color darkShadow, + Color highlight, Color lightHighlight) + { + /* These colors usually come from the UIDefaults of the current + * look and feel. Use fallback values if the colors are not + * supplied. The API specification is silent about what + * behavior is expected for null colors, so users should not + * rely on this fallback (which is why it is not documented in + * the above Javadoc). + */ + this.shadow = (shadow != null) ? shadow : Color.gray; + this.darkShadow = (darkShadow != null) ? darkShadow : Color.black; + this.highlight = (highlight != null) ? highlight : Color.lightGray; + this.lightHighlight = (lightHighlight != null) + ? lightHighlight + : Color.white; + } + + + /** + * Paints the ButtonBorder around a given component. + * + * @param c the component whose border is to be painted. + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the border. + * @param width the width of the available area for painting the border. + * @param height the height of the available area for painting the border. + * + * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel + */ + public void paintBorder(Component c, Graphics g, + int x, int y, int width, int height) + { + ButtonModel bmodel = null; + + if (c instanceof AbstractButton) + bmodel = ((AbstractButton) c).getModel(); + + BasicGraphicsUtils.drawBezel( + g, x, y, width, height, + /* pressed */ (bmodel != null) + && /* mouse button pressed */ bmodel.isPressed() + && /* mouse inside */ bmodel.isArmed(), + /* default */ (c instanceof JButton) + && ((JButton) c).isDefaultButton(), + shadow, darkShadow, highlight, lightHighlight); + } + + + /** + * Measures the width of this border. + * + * <p>Although the thickness of the actually painted border + * depends on the state of the enclosed component, this + * measurement always returns the same amount of pixels. Indeed, + * it would be rather confusing if a button was appearing to + * change its size depending on whether it is pressed or not. + * + * @param c the component whose border is to be measured. + * + * @return an Insets object whose <code>left</code>, + * <code>right</code>, <code>top</code> and + * <code>bottom</code> fields indicate the width of the + * border at the respective edge. + * + * @see #getBorderInsets(java.awt.Component, java.awt.Insets) + */ + public Insets getBorderInsets(Component c) + { + /* There is no obvious reason for overriding this method, but we + * try to have exactly the same API as the Sun reference + * implementation. + */ + return getBorderInsets(c, null); + } + + + /** + * Measures the width of this border, storing the results into a + * pre-existing Insets object. + * + * <p>Although the thickness of the actually painted border + * depends on the state of the enclosed component, this + * measurement always returns the same amount of pixels. Indeed, + * it would be rather confusing if a button was appearing to + * change its size depending on whether it is pressed or not. + * + * @param insets an Insets object for holding the result values. + * After invoking this method, the <code>left</code>, + * <code>right</code>, <code>top</code> and + * <code>bottom</code> fields indicate the width of the + * border at the respective edge. + * + * @return the same object that was passed for <code>insets</code>. + * + * @see #getBorderInsets(Component) + */ + public Insets getBorderInsets(Component c, Insets insets) + { + /* The exact amount has been determined using a test program + * that was run on the Sun reference implementation. With + * Apple/Sun JDK 1.3.1 on MacOS X 10.1.5, the result is + * [3, 3, 3, 3]. With Sun JDK 1.4.1_01 on Linux/x86, the + * result is [2, 3, 3, 3]. We use the values from the 1.4.1_01 + * release. + */ + if (insets == null) + return new Insets(2, 3, 3, 3); + + insets.top = 2; + insets.bottom = insets.left = insets.right = 3; + return insets; + } + } + + + /** + * A border that makes its enclosed component appear as lowered + * into the surface. Typically used for text fields. + * + * <p><img src="doc-files/BasicBorders.FieldBorder-1.png" width="500" + * height="200" alt="[A screen shot of this border]" /> + * + * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawEtchedRect + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class FieldBorder + extends AbstractBorder + implements UIResource + { + /** + * Determined using the <code>serialver</code> tool + * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5. + */ + static final long serialVersionUID = 949220756998454908L; + + + /** + * The color for drawing the outer half of the top and left + * edges. + */ + protected Color shadow; + + + /** + * The color for drawing the inner half of the top and left + * edges. + */ + protected Color darkShadow; + + + /** + * The color for drawing the inner half of the bottom and right + * edges. + */ + protected Color highlight; + + + /** + * The color for drawing the outer half of the bottom and right + * edges. + */ + protected Color lightHighlight; + + + /** + * Constructs a new border for drawing a text field in the Basic + * look and feel. + * + * @param shadow the color for drawing the outer half + * of the top and left edges. + * + * @param darkShadow the color for drawing the inner half + * of the top and left edges. + * + * @param highlight the color for drawing the inner half + * of the bottom and right edges. + * + * @param lightHighlight the color for drawing the outer half + * of the bottom and right edges. + */ + public FieldBorder(Color shadow, Color darkShadow, + Color highlight, Color lightHighlight) + { + /* These colors usually come from the UIDefaults of the current + * look and feel. Use fallback values if the colors are not + * supplied. The API specification is silent about what + * behavior is expected for null colors, so users should not + * rely on this fallback (which is why it is not documented in + * the above Javadoc). + */ + this.shadow = (shadow != null) ? shadow : Color.gray; + this.darkShadow = (darkShadow != null) ? darkShadow : Color.black; + this.highlight = (highlight != null) ? highlight : Color.lightGray; + this.lightHighlight = (lightHighlight != null) + ? lightHighlight : Color.white; + } + + + /** + * Paints the FieldBorder around a given component. + * + * @param c the component whose border is to be painted. + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the border. + * @param width the width of the available area for painting the border. + * @param height the height of the available area for painting the border. + * + * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawEtchedRect + */ + public void paintBorder(Component c, Graphics g, + int x, int y, int width, int height) + { + BasicGraphicsUtils.drawEtchedRect(g, x, y, width, height, + shadow, darkShadow, + highlight, lightHighlight); + } + + + /** + * Measures the width of this border. + * + * @param c the component whose border is to be measured. + * If <code>c</code> is an instance of {@link + * javax.swing.text.JTextComponent}, its margin is + * added to the border size. + * + * @return an Insets object whose <code>left</code>, + * <code>right</code>, <code>top</code> and + * <code>bottom</code> fields indicate the width of the + * border at the respective edge. + * + * @see #getBorderInsets(java.awt.Component, java.awt.Insets) + */ + public Insets getBorderInsets(Component c) + { + return getBorderInsets(c, null); + } + + + /** + * Measures the width of this border, storing the results into a + * pre-existing Insets object. + * + * @param c the component whose border is to be measured. + * If <code>c</code> is an instance of {@link + * javax.swing.text.JTextComponent}, its margin is + * added to the border size. + * + * @param insets an Insets object for holding the result values. + * After invoking this method, the <code>left</code>, + * <code>right</code>, <code>top</code> and + * <code>bottom</code> fields indicate the width of the + * border at the respective edge. + * + * @return the same object that was passed for <code>insets</code>. + * + * @see #getBorderInsets(Component) + */ + public Insets getBorderInsets(Component c, Insets insets) + { + if (insets == null) + insets = new Insets(2, 2, 2, 2); + else + insets.top = insets.left = insets.bottom = insets.right = 2; + + if (c instanceof JTextComponent) + { + Insets margin = ((JTextComponent) c).getMargin(); + insets.top += margin.top; + insets.left += margin.left; + insets.bottom += margin.bottom; + insets.right += margin.right; + } + + return insets; + } + } + + + /** + * An invisible, but spacing border whose margin is determined + * by calling the <code>getMargin()</code> method of the enclosed + * component. If the enclosed component has no such method, + * this border will not occupy any space. + * + * <p><img src="doc-files/BasicBorders.MarginBorder-1.png" width="325" + * height="200" alt="[An illustration that shows how MarginBorder + * determines its borders]" /> + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class MarginBorder + extends AbstractBorder + implements Serializable, UIResource + { + /** + * Determined using the <code>serialver</code> tool + * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5. + */ + static final long serialVersionUID = -3035848353448896090L; + + + /** + * Constructs a new MarginBorder. + */ + public MarginBorder() + { + } + + + /** + * Measures the width of this border. + * + * @param c the component whose border is to be measured. + * + * @return an Insets object whose <code>left</code>, <code>right</code>, + * <code>top</code> and <code>bottom</code> fields indicate the + * width of the border at the respective edge. + * + * @see #getBorderInsets(java.awt.Component, java.awt.Insets) + */ + public Insets getBorderInsets(Component c) + { + return getBorderInsets(c, new Insets(0, 0, 0, 0)); + } + + + /** + * Determines the insets of this border by calling the + * <code>getMargin()</code> method of the enclosed component. The + * resulting margin will be stored into the the <code>left</code>, + * <code>right</code>, <code>top</code> and <code>bottom</code> + * fields of the passed <code>insets</code> parameter. + * + * <p>Unfortunately, <code>getMargin()</code> is not a method of + * {@link javax.swing.JComponent} or some other common superclass + * of things with margins. While reflection could be used to + * determine the existence of this method, this would be slow on + * many virtual machines. Therefore, the current implementation + * knows about {@link javax.swing.AbstractButton#getMargin()}, + * {@link javax.swing.JPopupMenu#getMargin()}, {@link + * javax.swing.JToolBar#getMargin()}, and {@link + * javax.swing.text.JTextComponent}. If <code>c</code> is an + * instance of a known class, the respective + * <code>getMargin()</code> method is called to determine the + * correct margin. Otherwise, a zero-width margin is returned. + * + * @param c the component whose border is to be measured. + * + * @return the same object that was passed for <code>insets</code>, + * but with changed fields. + */ + public Insets getBorderInsets(Component c, Insets insets) + { + Insets margin = null; + + /* This is terrible object-oriented design. See the above Javadoc + * for an excuse. + */ + if (c instanceof AbstractButton) + margin = ((AbstractButton) c).getMargin(); + else if (c instanceof JPopupMenu) + margin = ((JPopupMenu) c).getMargin(); + else if (c instanceof JToolBar) + margin = ((JToolBar) c).getMargin(); + else if (c instanceof JTextComponent) + margin = ((JTextComponent) c).getMargin(); + + if (margin == null) + insets.top = insets.left = insets.bottom = insets.right = 0; + else + { + insets.top = margin.top; + insets.left = margin.left; + insets.bottom = margin.bottom; + insets.right = margin.right; + } + + return insets; + } + } + + + /** + * A border for drawing a separator line below JMenuBar. + * + * <p><img src="doc-files/BasicBorders.MenuBarBorder-1.png" width="500" + * height="140" alt="[A screen shot of a JMenuBar with this border]" /> + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class MenuBarBorder + extends AbstractBorder + implements UIResource + { + /** + * Determined using the <code>serialver</code> tool + * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5. + */ + static final long serialVersionUID = -6909056571935227506L; + + + /** + * The shadow color, which is used for the upper line of the + * two-pixel thick bottom edge. + */ + private Color shadow; + + + /** + * The highlight color, which is used for the lower line of the + * two-pixel thick bottom edge. + */ + private Color highlight; + + + /** + * Constructs a new MenuBarBorder for drawing a JMenuBar in + * the Basic look and feel. + * + * <p><img src="doc-files/BasicBorders.MenuBarBorder-1.png" width="500" + * height="140" alt="[A screen shot of a JMenuBar with this + * border]" /> + * + * @param shadow the shadow color, which is used for the upper + * line of the two-pixel thick bottom edge. + * + * @param highlight the shadow color, which is used for the lower + * line of the two-pixel thick bottom edge. + */ + public MenuBarBorder(Color shadow, Color highlight) + { + /* These colors usually come from the UIDefaults of the current + * look and feel. Use fallback values if the colors are not + * supplied. The API specification is silent about what + * behavior is expected for null colors, so users should not + * rely on this fallback (which is why it is not documented in + * the above Javadoc). + */ + this.shadow = (shadow != null) ? shadow : Color.gray; + this.highlight = (highlight != null) ? highlight : Color.white; + } + + + /** + * Paints the MenuBarBorder around a given component. + * + * @param c the component whose border is to be painted, usually + * an instance of {@link javax.swing.JMenuBar}. + * + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the border. + * @param width the width of the available area for painting the border. + * @param height the height of the available area for painting the border. + */ + public void paintBorder(Component c, Graphics g, + int x, int y, int width, int height) + { + Color oldColor; + + /* To understand this code, it might be helpful to look at the + * image "BasicBorders.MenuBarBorder-1.png" that is included + * with the JavaDoc. It is located in the "doc-files" + * subdirectory. + */ + oldColor = g.getColor(); + y = y + height - 2; + try + { + g.setColor(shadow); + g.drawLine(x, y, x + width - 2, y); + g.drawLine(x, y + 1, x, y + 1); + g.drawLine(x + width - 2, y + 1, x + width - 2, y + 1); + + g.setColor(highlight); + g.drawLine(x + 1, y + 1, x + width - 3, y + 1); + g.drawLine(x + width - 1, y, x + width - 1, y + 1); + } + finally + { + g.setColor(oldColor); + } + } + + + /** + * Measures the width of this border. + * + * @param c the component whose border is to be measured. + * + * @return an Insets object whose <code>left</code>, + * <code>right</code>, <code>top</code> and + * <code>bottom</code> fields indicate the width of the + * border at the respective edge. + * + * @see #getBorderInsets(java.awt.Component, java.awt.Insets) + */ + public Insets getBorderInsets(Component c) + { + /* There is no obvious reason for overriding this method, but we + * try to have exactly the same API as the Sun reference + * implementation. + */ + return getBorderInsets(c, null); + } + + + /** + * Measures the width of this border, storing the results into a + * pre-existing Insets object. + * + * @param insets an Insets object for holding the result values. + * After invoking this method, the <code>left</code>, + * <code>right</code>, <code>top</code> and + * <code>bottom</code> fields indicate the width of the + * border at the respective edge. + * + * @return the same object that was passed for <code>insets</code>. + * + * @see #getBorderInsets(Component) + */ + public Insets getBorderInsets(Component c, Insets insets) + { + /* The exact amount has been determined using a test program + * that was run on the Apple/Sun JDK 1.3.1 on MacOS X, and the + * Sun JDK 1.4.1_01 on GNU/Linux for x86. Both gave [0,0,2,0], + * which was expected from looking at the screen shot. + */ + if (insets == null) + return new Insets(0, 0, 2, 0); + + insets.left = insets.right = insets.top = 0; + insets.bottom = 2; + return insets; + } + } + + + /** + * A border for drawing radio buttons in the Basic look and feel. + * + * <p><img src="doc-files/BasicBorders.RadioButtonBorder-1.png" width="300" + * height="135" alt="[A screen shot of this border]" /> + * + * <p>Note about the screen shot: Normally, the + * <code>borderPainted</code> property is <code>false</code> for + * JRadioButtons. For this screen shot, it has been set to + * <code>true</code> so the borders get drawn. Also, a + * concretization of the Basic look and would typically provide + * icons for the various states of radio buttons. + * + * <p>Note that the focus rectangle is invisible If the radio button + * is currently selected. While it might be debatable whether this + * makes a lot of sense, this behavior can be observed in the Sun + * reference implementation (in JDK 1.3.1 and 1.4.1). The Classpath + * implementation tries to exactly replicate the JDK appearance. + * + * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class RadioButtonBorder + extends ButtonBorder + { + /** + * Determined using the <code>serialver</code> tool + * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5. + */ + static final long serialVersionUID = 1596945751743747369L; + + + /** + * Constructs a new border for drawing a JRadioButton in + * the Basic look and feel. + * + * @param shadow the shadow color. + * @param darkShadow a darker variant of the shadow color. + * @param highlight the highlight color. + * @param lightHighlight a brighter variant of the highlight color. + */ + public RadioButtonBorder(Color shadow, Color darkShadow, + Color highlight, Color lightHighlight) + { + /* The superclass ButtonBorder substitutes null arguments + * with fallback colors. + */ + super(shadow, darkShadow, highlight, lightHighlight); + } + + + /** + * Paints the RadioButtonBorder around a given component. + * + * <p>The Sun implementation always seems to draw exactly + * the same border, irrespective of the state of the button. + * This is rather surprising, but GNU Classpath emulates the + * observable behavior. + * + * @param c the component whose border is to be painted. + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the border. + * @param width the width of the available area for painting the border. + * @param height the height of the available area for painting the border. + * + * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel + */ + public void paintBorder(Component c, Graphics g, + int x, int y, int width, int height) + { + AbstractButton button = null; + ButtonModel bmodel = null; + boolean lowered = false; + boolean focused = false; + + if (c instanceof AbstractButton) + { + button = (AbstractButton) c; + bmodel = button.getModel(); + } + + if (bmodel != null) + { + lowered = button.isSelected() + || (/* mouse inside */ bmodel.isArmed() && bmodel.isPressed()); + focused = button.hasFocus() && button.isFocusPainted(); + } + + if (lowered) + BasicGraphicsUtils.drawLoweredBezel(g, x, y, width, height, + shadow, darkShadow, + highlight, lightHighlight); + else + BasicGraphicsUtils.drawBezel(g, x, y, width, height, + /* isPressed */ false, + /* isPefault */ focused, + shadow, darkShadow, + highlight, lightHighlight); + } + + + /** + * Measures the width of this border. + * + * @param c the component whose border is to be measured. + * + * @return an Insets object whose <code>left</code>, + * <code>right</code>, <code>top</code> and + * <code>bottom</code> fields indicate the width of the + * border at the respective edge. + * + * @see #getBorderInsets(java.awt.Component, java.awt.Insets) + */ + public Insets getBorderInsets(Component c) + { + /* There is no obvious reason for overriding this method, but we + * try to have exactly the same API as the Sun reference + * implementation. + */ + return getBorderInsets(c, null); + } + + + /** + * Measures the width of this border, storing the results into a + * pre-existing Insets object. + * + * @param insets an Insets object for holding the result values. + * After invoking this method, the <code>left</code>, + * <code>right</code>, <code>top</code> and + * <code>bottom</code> fields indicate the width of the + * border at the respective edge. + * + * @return the same object that was passed for <code>insets</code>. + * + * @see #getBorderInsets(Component) + */ + public Insets getBorderInsets(Component c, Insets insets) + { + /* The exact amount has been determined using a test program + * that was run on the Apple/Sun JDK 1.3.1 on MacOS X, and the + * Sun JDK 1.4.1_01 on GNU/Linux for x86. Both gave [2,2,2,2]. + */ + if (insets == null) + return new Insets(2, 2, 2, 2); + + insets.left = insets.right = insets.top = insets.bottom = 2; + return insets; + } + } + + + /** + * A one-pixel thick border for rollover buttons, for example in + * tool bars. + * + * @since 1.4 + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class RolloverButtonBorder + extends ButtonBorder + { + /** + * Determined using the <code>serialver</code> tool + * of Sun JDK 1.4.1_01 on GNU/Linux 2.4.20 for x86. + */ + static final long serialVersionUID = 1976364864896996846L; + + + /** + * Constructs a new border for drawing a roll-over button + * in the Basic look and feel. + * + * @param shadow the shadow color. + * @param darkShadow a darker variant of the shadow color. + * @param highlight the highlight color. + * @param lightHighlight a brighter variant of the highlight color. + */ + public RolloverButtonBorder(Color shadow, Color darkShadow, + Color highlight, Color lightHighlight) + { + super(shadow, darkShadow, highlight, lightHighlight); + } + + + /** + * Paints the border around a rollover button. If <code>c</code> + * is not an {@link javax.swing.AbstractButton} whose model + * returns <code>true</code> for {@link + * javax.swing.ButtonModel#isRollover}, nothing gets painted at + * all. + * + * @param c the button whose border is to be painted. + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the border. + * @param width the width of the available area for painting the border. + * @param height the height of the available area for painting the border. + */ + public void paintBorder(Component c, Graphics g, + int x, int y, int width, int height) + { + ButtonModel bmodel = null; + boolean drawPressed; + Color oldColor = g.getColor(); + int x2, y2; + + if (c instanceof AbstractButton) + bmodel = ((AbstractButton) c).getModel(); + + /* Draw nothing if c is not a rollover button. */ + if ((bmodel == null) || !bmodel.isRollover()) + return; + + /* Draw nothing if the mouse is pressed, but outside the button. */ + if (bmodel.isPressed() && !bmodel.isArmed()) + return; + + drawPressed = bmodel.isSelected() || bmodel.isPressed(); + x2 = x + width - 1; + y2 = y + height - 1; + + try + { + g.setColor(drawPressed ? shadow : lightHighlight); + g.drawLine(x, y, x2 - 1, y); // top edge + g.drawLine(x, y + 1, x, y2 - 1); // left edge + + g.setColor(drawPressed ? lightHighlight : shadow); + g.drawLine(x, y2, x2, y2); // bottom edge + g.drawLine(x2, y, x2, y2 - 1); // right edge + } + finally + { + g.setColor(oldColor); + } + } + } + + + /** + * A border for JSplitPanes in the Basic look and feel. The divider + * in the middle of the JSplitPane has its own border class, of which + * an instance can be obtained with {@link #getSplitPaneDividerBorder()}. + * + * <p><img src="doc-files/BasicBorders.SplitPaneBorder-1.png" width="520" + * height="200" alt="[A screen shot for JSplitPane.HORIZONTAL_SPLIT]" /> + * + * <p><img src="doc-files/BasicBorders.SplitPaneBorder-2.png" width="520" + * height="200" alt="[A screen shot for JSplitPane.VERTICAL_SPLIT]" /> + * + * <p>In contrast to the other borders of the Basic look and feel, + * this class is not serializable. While this might be unintended, + * GNU Classpath follows the specification in order to be fully + * compatible with the Sun reference implementation. + * + * <p>In the Sun JDK, the bottom edge of the divider also gets + * painted if the orientation of the enclosed JSplitPane is + * <code>JSplitPane.VERTICAL_SPLIT</code> (at least in versions + * 1.3.1 and 1.4.1). GNU Classpath does not replicate this bug. A + * report has been filed with Sun (bug ID 4885629). + * + * <p>Note that the bottom left pixel of the border has a different + * color depending on the orientation of the enclosed JSplitPane. + * Although this is visually inconsistent, Classpath replicates the + * appearance of the Sun reference implementation. A bug report has + * been filed with Sun (review ID 188774). + * + * @see #getSplitPaneBorder() + * @see #getSplitPaneDividerBorder() + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class SplitPaneBorder + implements Border, UIResource + { + /** + * Indicates that the top edge shall be not be painted + * by {@link #paintRect(java.awt.Graphics, int, int, int, int, int)}. + */ + private static final int SUPPRESS_TOP = 1; + + + /** + * Indicates that the left edge shall be not be painted + * by {@link #paintRect(java.awt.Graphics, int, int, int, int, int)}. + */ + private static final int SUPPRESS_LEFT = 2; + + + /** + * Indicates that the bottom edge shall be not be painted + * by {@link #paintRect(java.awt.Graphics, int, int, int, int, int)}. + */ + private static final int SUPPRESS_BOTTOM = 4; + + + /** + * Indicates that the right edge shall be not be painted + * by {@link #paintRect(java.awt.Graphics, int, int, int, int, int)}. + */ + private static final int SUPPRESS_RIGHT = 8; + + + /** + * The color for drawing the bottom and right edges of the border. + */ + protected Color highlight; + + + /** + * The color for drawing the top and left edges of the border. + */ + protected Color shadow; + + + /** + * Constructs a new border for drawing a JSplitPane in the Basic + * look and feel. The divider in the middle of the JSplitPane has + * its own border class, <code>SplitPaneDividerBorder</code>. + * + * @param shadow the shadow color. + * @param highlight the highlight color. + */ + public SplitPaneBorder(Color highlight, Color shadow) + { + /* These colors usually come from the UIDefaults of the current + * look and feel. Use fallback values if the colors are not + * supplied. The API specification is silent about what + * behavior is expected for null colors, so users should not + * rely on this fallback (which is why it is not documented in + * the above Javadoc). + */ + this.shadow = (shadow != null) ? shadow : Color.black; + this.highlight = (highlight != null) ? highlight : Color.white; + } + + + /** + * Paints the border around a <code>JSplitPane</code>. + * + * <p><img src="doc-files/BasicBorders.SplitPaneBorder-1.png" width="520" + * height="200" alt="[A screen shot for JSplitPane.HORIZONTAL_SPLIT]" /> + * + * <p><img src="doc-files/BasicBorders.SplitPaneBorder-2.png" width="520" + * height="200" alt="[A screen shot for JSplitPane.VERTICAL_SPLIT]" /> + * + * @param c the <code>JSplitPane</code> whose border is to be painted. + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the border. + * @param width the width of the available area for painting the border. + * @param height the height of the available area for painting the border. + */ + public void paintBorder(Component c, Graphics g, + int x, int y, int width, int height) + { + JSplitPane splitPane; + Component content; + + if (!(c instanceof JSplitPane)) + return; + + splitPane = (JSplitPane) c; + switch (splitPane.getOrientation()) + { + case JSplitPane.HORIZONTAL_SPLIT: + if ((content = splitPane.getLeftComponent()) != null) + paintRect(g, SUPPRESS_RIGHT, true, x, y, content.getBounds()); + if ((content = splitPane.getRightComponent()) != null) + paintRect(g, SUPPRESS_LEFT, true, x, y, content.getBounds()); + break; + + case JSplitPane.VERTICAL_SPLIT: + if ((content = splitPane.getTopComponent()) != null) + paintRect(g, SUPPRESS_BOTTOM, false, x, y, content.getBounds()); + if ((content = splitPane.getBottomComponent()) != null) + paintRect(g, SUPPRESS_TOP, false, x, y, content.getBounds()); + break; + } + } + + + /** + * Paints a border around a child of a <code>JSplitPane</code>, + * omitting some of the edges. + * + * @param g the graphics for painting. + * + * @param suppress a bit mask indicating the set of suppressed + * edges, for example <code>SUPPRESS_TOP | SUPPRESS_RIGHT</code>. + * + * @param x the x coordinate of the SplitPaneBorder. + * + * @param y the y coordinate of the SplitPaneBorder. + * + * @param shadeBottomLeftPixel <code>true</code> to paint the + * bottom left pixel in the shadow color, + * <code>false</code> for the highlight color. The Basic + * look and feel uses the highlight color for the bottom + * left pixel of the border of a JSplitPane whose + * orientation is VERTICAL_SPLIT, and the shadow color + * otherwise. While this might be a strange distinction, + * Classpath tries to look identical to the reference + * implementation. A bug report has been filed with Sun; + * its review ID is 188774. We currently replicate the + * Sun behavior. + * + * @param rect the bounds of the child of JSplitPane whose + * border is to be painted. + */ + private void paintRect(Graphics g, int suppress, + boolean shadeBottomLeftPixel, + int x, int y, + Rectangle rect) + { + if (rect == null) + return; + + /* On each edge, the border exceeds the enclosed child by one + * pixel. See the image "BasicBorders.SplitPaneBorder-1.png" in + * the directory "doc-files". + */ + x += rect.x - 1; + y += rect.y - 1; + int right = x + rect.width + 1; + int bottom = y + rect.height + 1; + + Color oldColor = g.getColor(); + try + { + g.setColor(shadow); + if ((suppress & SUPPRESS_TOP) == 0) + g.drawLine(x, y, right, y); + if ((suppress & SUPPRESS_LEFT) == 0) + g.drawLine(x, y, x, bottom); + else + g.drawLine(x, bottom, x, bottom); // one pixel + + g.setColor(highlight); + if ((suppress & SUPPRESS_BOTTOM) == 0) + g.drawLine(x + (shadeBottomLeftPixel ? 1 : 0), bottom, right, bottom); + else if (!shadeBottomLeftPixel) + g.drawLine(x, bottom, x, bottom); // one pixel + + if ((suppress & SUPPRESS_RIGHT) == 0) + g.drawLine(right, y, right, bottom); + } + finally + { + g.setColor(oldColor); + } + } + + + /** + * Measures the width of this border. + * + * @param c the component whose border is to be measured, usually + * an instance of {@link javax.swing.JSplitPane}. + * + * @return an Insets object whose <code>left</code>, + * <code>right</code>, <code>top</code> and + * <code>bottom</code> fields indicate the width of the + * border at the respective edge. + */ + public Insets getBorderInsets(Component c) + { + return new Insets(1, 1, 1, 1); + } + + + /** + * Determines whether this border fills every pixel in its area + * when painting. + * + * @return <code>false</code> because this border does not + * paint over the pixels where the divider joins + * the border. + */ + public boolean isBorderOpaque() + { + /* Strangely, the Sun implementation (tested with JDK 1.3.1 and + * 1.4.1_01) seems to always return true. It could be a bug, + * but without knowing the details of their implementation, it is + * hard to decide. + */ + return false; + } + } + + + /** + * A border for the divider inside a JSplitPane. + * + * <p><img src="doc-files/BasicBorders.SplitPaneDividerBorder-1.png" + * width="520" height="200" alt="[A screen shot of this border]" /> + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ + private static class SplitPaneDividerBorder + implements Border, UIResource, Serializable + { + /** + * The highlight color, which is drawn on the left or top edge + * depending on the orientation of the JSplitPanel. + */ + protected Color highlight; + + + /** + * The highlight color, which is drawn on the right or bottom edge + * depending on the orientation of the JSplitPanel. + */ + protected Color shadow; + + + /** + * Constructs a new border for drawing the divider of a JSplitPane + * in the Basic look and feel. The outer parts of the JSplitPane have + * their own border class, <code>SplitPaneBorder</code>. + * + * @param shadow the shadow color. + * @param highlight the highlight color. + */ + public SplitPaneDividerBorder(Color highlight, Color shadow) + { + this.highlight = (highlight != null) ? highlight : Color.white; + this.shadow = (shadow != null) ? shadow : Color.black; + } + + + /** + * Paints the border around the divider of a <code>JSplitPane</code>. + * + * <p><img src="doc-files/BasicBorders.SplitPaneDividerBorder-1.png" + * width="520" height="200" alt="[A picture that shows which pixels + * get painted in what color]" /> + * + * @param c the <code>JSplitPane</code> whose divider’s border + * is to be painted. + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the border. + * @param width the width of the available area for painting the border. + * @param height the height of the available area for painting the border. + */ + public void paintBorder(Component c, Graphics g, + int x, int y, int width, int height) + { + Color oldColor, dcol; + int x2, y2; + JSplitPane sp; + + sp = getSplitPane(c); + if (sp == null) + return; + + x2 = x + width - 1; + y2 = y + height - 1; + oldColor = g.getColor(); + dcol = c.getBackground(); + try + { + switch (sp.getOrientation()) + { + case JSplitPane.HORIZONTAL_SPLIT: + g.setColor(dcol); + g.drawLine(x + 1, y, x2 - 1, y); + g.drawLine(x + 1, y2, x2 - 1, y2); + g.setColor(sp.getLeftComponent() != null ? highlight : dcol); + g.drawLine(x, y, x, y2); + g.setColor(sp.getRightComponent() != null ? shadow : dcol); + g.drawLine(x2, y, x2, y2); + break; + + case JSplitPane.VERTICAL_SPLIT: + g.setColor(dcol); + g.drawLine(x, y + 1, x, y2 - 1); + g.drawLine(x2, y + 1, x2, y2 - 1); + g.setColor(sp.getTopComponent() != null ? highlight : dcol); + g.drawLine(x, y, x2, y); + g.setColor(sp.getBottomComponent() != null ? shadow : dcol); + g.drawLine(x, y2, x2, y2); + break; + } + } + finally + { + g.setColor(oldColor); + } + } + + + /** + * Measures the width of this border. + * + * @param c the component whose border is to be measured, usually + * an instance of {@link javax.swing.JSplitPane}. + * + * @return an Insets object whose <code>left</code>, + * <code>right</code>, <code>top</code> and + * <code>bottom</code> fields indicate the width of the + * border at the respective edge. + */ + public Insets getBorderInsets(Component c) + { + return new Insets(1, 1, 1, 1); + } + + + /** + * Determines whether this border fills every pixel in its area + * when painting. + * + * @return <code>true</code> if both highlight and shadow + * color are fully opaque. + */ + public boolean isBorderOpaque() + { + return (highlight.getAlpha() == 255) && (shadow.getAlpha() == 255); + } + + + /** + * Determines the JSplitPane whose divider is being painted. + * + * @param c an instance of BasicSplitPaneDivider. + * + * @return a <code>JSplitPane</code>, or <code>null</code> if + * <code>c</code> is not an instance of {@link + * javax.swing.plaf.basic.BasicSplitPaneDivider}. + */ + private JSplitPane getSplitPane(Component c) + { + if (c instanceof BasicSplitPaneDivider) + return (((BasicSplitPaneDivider) c).getBasicSplitPaneUI()) + .getSplitPane(); + else + return null; + } + } + + + /** + * A border for toggle buttons in the Basic look and feel. + * + * <p><img src="doc-files/BasicBorders.ToggleButtonBorder-1.png" + * width="270" height="135" alt="[A screen shot of this border]" /> + * + * <p>The Sun implementation always seems to draw exactly + * the same border, irrespective of the state of the button. + * This is rather surprising, but GNU Classpath emulates the + * observable behavior. + * + * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ + public static class ToggleButtonBorder + extends ButtonBorder + { + /** + * Determined using the <code>serialver</code> tool + * of Apple/Sun JDK 1.3.1 on MacOS X 10.1.5. + */ + static final long serialVersionUID = -3528666548001058394L; + + + /** + * Constructs a new border for drawing a JToggleButton in + * the Basic look and feel. + * + * @param shadow the shadow color. + * @param darkShadow a darker variant of the shadow color. + * @param highlight the highlight color. + * @param lightHighlight a brighter variant of the highlight color. + */ + public ToggleButtonBorder(Color shadow, Color darkShadow, + Color highlight, Color lightHighlight) + { + /* The superclass ButtonBorder substitutes null arguments + * with fallback colors. + */ + super(shadow, darkShadow, highlight, lightHighlight); + } + + + /** + * Paints the ToggleButtonBorder around a given component. + * + * <p>The Sun implementation always seems to draw exactly + * the same border, irrespective of the state of the button. + * This is rather surprising, but GNU Classpath emulates the + * observable behavior. + * + * @param c the component whose border is to be painted. + * @param g the graphics for painting. + * @param x the horizontal position for painting the border. + * @param y the vertical position for painting the border. + * @param width the width of the available area for painting the border. + * @param height the height of the available area for painting the border. + * + * @see javax.swing.plaf.basic.BasicGraphicsUtils#drawBezel + */ + public void paintBorder(Component c, Graphics g, + int x, int y, int width, int height) + { + /* The author of this code tried various variants for setting + * the state of the enclosed JToggleButton, but it seems that + * the drawn border is always identical. Weird, because this + * means that the user does not see whether the JToggleButton + * is selected or not. + */ + BasicGraphicsUtils.drawBezel(g, x, y, width, height, + /* pressed */ false, + /* default */ false, + shadow, darkShadow, + highlight, lightHighlight); + } + + + /** + * Measures the width of this border. + * + * @param c the component whose border is to be measured. + * + * @return an Insets object whose <code>left</code>, + * <code>right</code>, <code>top</code> and + * <code>bottom</code> fields indicate the width of the + * border at the respective edge. + * + * @see #getBorderInsets(java.awt.Component, java.awt.Insets) + */ + public Insets getBorderInsets(Component c) + { + /* There is no obvious reason for overriding this method, but we + * try to have exactly the same API as the Sun reference + * implementation. + */ + return getBorderInsets(c, null); + } + + + /** + * Measures the width of this border, storing the results into a + * pre-existing Insets object. + * + * @param insets an Insets object for holding the result values. + * After invoking this method, the <code>left</code>, + * <code>right</code>, <code>top</code> and + * <code>bottom</code> fields indicate the width of the + * border at the respective edge. + * + * @return the same object that was passed for <code>insets</code>. + * + * @see #getBorderInsets(Component) + */ + public Insets getBorderInsets(Component c, Insets insets) + { + /* The exact amount has been determined using a test program + * that was run on the Apple/Sun JDK 1.3.1 on MacOS X, and the + * Sun JDK 1.4.1_01 on GNU/Linux for x86. Both gave [2,2,2,2]. + */ + if (insets == null) + return new Insets(2, 2, 2, 2); + + insets.left = insets.right = insets.top = insets.bottom = 2; + return insets; + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicButtonListener.java b/libjava/classpath/javax/swing/plaf/basic/BasicButtonListener.java new file mode 100644 index 0000000..5349f52 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicButtonListener.java @@ -0,0 +1,231 @@ +/* BasicButtonListener.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.event.ActionEvent; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.InputEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.AbstractAction; +import javax.swing.AbstractButton; +import javax.swing.ButtonModel; +import javax.swing.JComponent; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; + +public class BasicButtonListener + implements MouseListener, MouseMotionListener, FocusListener, + ChangeListener, PropertyChangeListener +{ + public BasicButtonListener(AbstractButton b) + { + // Do nothing here. + } + + public void propertyChange(PropertyChangeEvent e) + { + } + + protected void checkOpacity(AbstractButton b) + { + } + + public void focusGained(FocusEvent e) + { + if (e.getSource() instanceof AbstractButton) + { + AbstractButton button = (AbstractButton) e.getSource(); + if (button.isFocusPainted()) + button.repaint(); + } + } + + public void focusLost(FocusEvent e) + { + if (e.getSource() instanceof AbstractButton) + { + AbstractButton button = (AbstractButton) e.getSource(); + if (button.isFocusPainted()) + button.repaint(); + } + } + + public void installKeyboardActions(JComponent c) + { + c.getActionMap().put("pressed", + new AbstractAction() + { + public void actionPerformed(ActionEvent e) + { + AbstractButton button = (AbstractButton) e.getSource(); + ButtonModel model = button.getModel(); + // It is important that these transitions happen in this order. + model.setArmed(true); + model.setPressed(true); + } + }); + + c.getActionMap().put("released", + new AbstractAction() + { + public void actionPerformed(ActionEvent e) + { + AbstractButton button = (AbstractButton) e.getSource(); + ButtonModel model = button.getModel(); + // It is important that these transitions happen in this order. + model.setPressed(false); + model.setArmed(false); + } + }); + } + + public void uninstallKeyboardActions(JComponent c) + { + c.getActionMap().put("pressed", null); + c.getActionMap().put("released", null); + } + + public void stateChanged(ChangeEvent e) + { + } + + public void mouseMoved(MouseEvent e) + { + } + + public void mouseDragged(MouseEvent e) + { + } + + public void mouseClicked(MouseEvent e) + { + } + + /** + * Accept a mouse press event and arm the button. + * + * @param e The mouse press event to accept + */ + public void mousePressed(MouseEvent e) + { + if (e.getSource() instanceof AbstractButton) + { + AbstractButton button = (AbstractButton) e.getSource(); + ButtonModel model = button.getModel(); + if (e.getButton() == MouseEvent.BUTTON1) + { + // It is important that these transitions happen in this order. + model.setArmed(true); + model.setPressed(true); + } + } + } + + /** + * Accept a mouse release event and set the button's + * "pressed" property to <code>true</code>, if the model + * is armed. If the model is not armed, ignore the event. + * + * @param e The mouse release event to accept + */ + public void mouseReleased(MouseEvent e) + { + if (e.getSource() instanceof AbstractButton) + { + AbstractButton button = (AbstractButton) e.getSource(); + ButtonModel model = button.getModel(); + if (e.getButton() == MouseEvent.BUTTON1) + { + // It is important that these transitions happen in this order. + model.setPressed(false); + model.setArmed(false); + } + } + } + + /** + * Accept a mouse enter event and set the button's "rollover" property to + * <code>true</code>, if the button's "rolloverEnabled" property is + * <code>true</code>. If the button is currently armed and the mouse + * button is not held down, this enter event will also disarm the model. + * + * @param e The mouse enter event to accept + */ + public void mouseEntered(MouseEvent e) + { + if (e.getSource() instanceof AbstractButton) + { + AbstractButton button = (AbstractButton) e.getSource(); + ButtonModel model = button.getModel(); + if (button.isRolloverEnabled()) + model.setRollover(true); + + if (model.isPressed() + && (e.getModifiersEx() & InputEvent.BUTTON1_DOWN_MASK) != 0) + model.setArmed(true); + else + model.setArmed(false); + } + } + + /** + * Accept a mouse exit event and set the button's model's "rollover" + * property to <code>false</code>, if it's "rolloverEnabled" property is + * <code>true</code>. Also disarm the button. + * + * @param e The mouse exit event to accept + */ + public void mouseExited(MouseEvent e) + { + if (e.getSource() instanceof AbstractButton) + { + AbstractButton button = (AbstractButton) e.getSource(); + ButtonModel model = button.getModel(); + if (button.isRolloverEnabled()) + model.setRollover(false); + model.setArmed(false); + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicButtonUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicButtonUI.java new file mode 100644 index 0000000..d893c5d --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicButtonUI.java @@ -0,0 +1,421 @@ +/* BasicButtonUI.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Rectangle; + +import javax.swing.AbstractButton; +import javax.swing.ButtonModel; +import javax.swing.Icon; +import javax.swing.InputMap; +import javax.swing.JComponent; +import javax.swing.SwingUtilities; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.ButtonUI; +import javax.swing.plaf.ComponentUI; + +public class BasicButtonUI extends ButtonUI +{ + /** + * A constant used to pad out elements in the button's layout and + * preferred size calculations. + */ + protected int defaultTextIconGap = 4; + + /** + * A constant added to the defaultTextIconGap to adjust the text + * within this particular button. + */ + protected int defaultTextShiftOffset = 0; + + private int textShiftOffset; + + private Color focusColor; + + /** + * Factory method to create an instance of BasicButtonUI for a given + * {@link JComponent}, which should be an {@link AbstractButton}. + * + * @param c The component to create a UI got + * + * @return A new UI capable of drawing the component + */ + public static ComponentUI createUI(final JComponent c) + { + return new BasicButtonUI(); + } + + public int getDefaultTextIconGap(AbstractButton b) + { + return defaultTextIconGap; + } + + protected void clearTextShiftOffset() + { + textShiftOffset = 0; + } + + protected int getTextShiftOffset() + { + return textShiftOffset; + } + + protected void setTextShiftOffset() + { + textShiftOffset = defaultTextShiftOffset; + } + + /** + * Returns the prefix for the UI defaults property for this UI class. + * This is 'Button' for this class. + * + * @return the prefix for the UI defaults property + */ + protected String getPropertyPrefix() + { + return "Button"; + } + + protected void installDefaults(AbstractButton b) + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + String prefix = getPropertyPrefix(); + focusColor = defaults.getColor(prefix + ".focus"); + b.setForeground(defaults.getColor(prefix + ".foreground")); + b.setBackground(defaults.getColor(prefix + ".background")); + b.setMargin(defaults.getInsets(prefix + ".margin")); + b.setBorder(defaults.getBorder(prefix + ".border")); + b.setIconTextGap(defaults.getInt(prefix + ".textIconGap")); + b.setInputMap(JComponent.WHEN_FOCUSED, + (InputMap) defaults.get(prefix + ".focusInputMap")); + b.setOpaque(true); + } + + protected void uninstallDefaults(AbstractButton b) + { + b.setForeground(null); + b.setBackground(null); + b.setBorder(null); + b.setIconTextGap(defaultTextIconGap); + b.setMargin(null); + } + + protected BasicButtonListener listener; + + protected BasicButtonListener createButtonListener(AbstractButton b) + { + return new BasicButtonListener(b); + } + + protected void installListeners(AbstractButton b) + { + listener = createButtonListener(b); + b.addChangeListener(listener); + b.addPropertyChangeListener(listener); + b.addFocusListener(listener); + b.addMouseListener(listener); + b.addMouseMotionListener(listener); + } + + protected void uninstallListeners(AbstractButton b) + { + b.removeChangeListener(listener); + b.removePropertyChangeListener(listener); + b.removeFocusListener(listener); + b.removeMouseListener(listener); + b.removeMouseMotionListener(listener); + } + + protected void installKeyboardActions(AbstractButton b) + { + listener.installKeyboardActions(b); + } + + protected void uninstallKeyboardActions(AbstractButton b) + { + listener.uninstallKeyboardActions(b); + } + + /** + * Install the BasicButtonUI as the UI for a particular component. + * This means registering all the UI's listeners with the component, + * and setting any properties of the button which are particular to + * this look and feel. + * + * @param c The component to install the UI into + */ + public void installUI(final JComponent c) + { + super.installUI(c); + if (c instanceof AbstractButton) + { + AbstractButton b = (AbstractButton) c; + installDefaults(b); + installListeners(b); + installKeyboardActions(b); + } + } + + /** + * Calculate the preferred size of this component, by delegating to + * {@link BasicGraphicsUtils#getPreferredButtonSize}. + * + * @param c The component to measure + * + * @return The preferred dimensions of the component + */ + public Dimension getPreferredSize(JComponent c) + { + AbstractButton b = (AbstractButton)c; + Dimension d = + BasicGraphicsUtils.getPreferredButtonSize + (b, defaultTextIconGap + defaultTextShiftOffset); + return d; + } + + private static Icon currentIcon(AbstractButton b) + { + Icon i = b.getIcon(); + ButtonModel model = b.getModel(); + + if (model.isPressed() && b.getPressedIcon() != null) + i = b.getPressedIcon(); + + else if (model.isRollover()) + { + if (b.isSelected() && b.getRolloverSelectedIcon() != null) + i = b.getRolloverSelectedIcon(); + else if (b.getRolloverIcon() != null) + i = b.getRolloverIcon(); + } + + else if (b.isSelected()) + { + if (b.isEnabled() && b.getSelectedIcon() != null) + i = b.getSelectedIcon(); + else if (b.getDisabledSelectedIcon() != null) + i = b.getDisabledSelectedIcon(); + } + + else if (! b.isEnabled() && b.getDisabledIcon() != null) + i = b.getDisabledIcon(); + + return i; + } + + /** + * Paint the component, which is an {@link AbstractButton}, according to + * its current state. + * + * @param g The graphics context to paint with + * @param c The component to paint the state of + */ + public void paint(Graphics g, JComponent c) + { + AbstractButton b = (AbstractButton) c; + + Rectangle tr = new Rectangle(); + Rectangle ir = new Rectangle(); + Rectangle vr = new Rectangle(); + + Font f = c.getFont(); + + g.setFont(f); + + SwingUtilities.calculateInnerArea(b, vr); + String text = SwingUtilities.layoutCompoundLabel(c, g.getFontMetrics(f), + b.getText(), + currentIcon(b), + b.getVerticalAlignment(), + b.getHorizontalAlignment(), + b.getVerticalTextPosition(), + b.getHorizontalTextPosition(), + vr, ir, tr, + b.getIconTextGap() + + defaultTextShiftOffset); + + if ((b.getModel().isArmed() && b.getModel().isPressed()) + || b.isSelected()) + paintButtonPressed(g, b); + else + paintButtonNormal(g, vr, c); + + paintIcon(g, c, ir); + if (text != null) + paintText(g, b, tr, text); + paintFocus(g, b, vr, tr, ir); + } + + /** + * Paint any focus decoration this {@link JComponent} might have. The + * component, which in this case will be an {@link AbstractButton}, + * should only have focus decoration painted if it has the focus, and its + * "focusPainted" property is <code>true</code>. + * + * @param g Graphics context to paint with + * @param b Button to paint the focus of + * @param vr Visible rectangle, the area in which to paint + * @param tr Text rectangle, contained in visible rectangle + * @param ir Icon rectangle, contained in visible rectangle + * + * @see AbstractButton#isFocusPainted() + * @see JComponent#hasFocus() + */ + protected void paintFocus(Graphics g, AbstractButton b, Rectangle vr, + Rectangle tr, Rectangle ir) + { + if (b.hasFocus() && b.isFocusPainted()) + { + Color saved_color = g.getColor(); + g.setColor(focusColor); + Rectangle focusRect = ir.union(tr); + g.drawRect(focusRect.x, focusRect.y, + focusRect.width, focusRect.height); + g.setColor(saved_color); + } + } + + /** + * Paint the icon for this component. Depending on the state of the + * component and the availability of the button's various icon + * properties, this might mean painting one of several different icons. + * + * @param g Graphics context to paint with + * @param c Component to paint the icon of + * @param iconRect Rectangle in which the icon should be painted + */ + protected void paintIcon(Graphics g, JComponent c, Rectangle iconRect) + { + AbstractButton b = (AbstractButton) c; + Icon i = currentIcon(b); + + if (i != null) + i.paintIcon(c, g, iconRect.x, iconRect.y); + } + + /** + * Paints the background area of an {@link AbstractButton} in the pressed + * state. This means filling the supplied area with the {@link + * pressedBackgroundColor}. + * + * @param g The graphics context to paint with + * @param b The button to paint the state of + */ + protected void paintButtonPressed(Graphics g, AbstractButton b) + { + if (b.isContentAreaFilled()) + { + Rectangle area = new Rectangle(); + SwingUtilities.calculateInnerArea(b, area); + g.setColor(b.getBackground().darker()); + g.fillRect(area.x, area.y, area.width, area.height); + } + } + + /** + * Paints the background area of an {@link AbstractButton} in the normal, + * non-pressed state. This means filling the supplied area with the + * {@link normalBackgroundColor}. + * + * @param g The graphics context to paint with + * @param area The area in which to paint + * @param b The component to paint the state of + */ + private void paintButtonNormal(Graphics g, Rectangle area, JComponent b) + { + if (((AbstractButton)b).isContentAreaFilled() && b.isOpaque()) + { + g.setColor(b.getBackground()); + g.fillRect(area.x, area.y, area.width, area.height); + } + } + + /** + * Paints the "text" property of an {@link AbstractButton}, using the + * {@link textColor} color. + * + * @param g The graphics context to paint with + * @param c The component to paint the state of + * @param textRect The area in which to paint the text + * @param text The text to paint + */ + protected void paintText(Graphics g, JComponent c, Rectangle textRect, + String text) + { + paintText(g, (AbstractButton) c, textRect, text); + } + + /** + * Paints the "text" property of an {@link AbstractButton}, using the + * {@link textColor} color. + * + * @param g The graphics context to paint with + * @param b The button to paint the state of + * @param textRect The area in which to paint the text + * @param text The text to paint + * + * @since 1.4 + */ + protected void paintText(Graphics g, AbstractButton b, Rectangle textRect, + String text) + { + Font f = b.getFont(); + g.setFont(f); + FontMetrics fm = g.getFontMetrics(f); + + if (b.isEnabled()) + { + g.setColor(b.getForeground()); + g.drawString(text, textRect.x, textRect.y + fm.getAscent()); + } + else + { + g.setColor(b.getBackground().brighter()); + g.drawString(text, textRect.x, textRect.y + fm.getAscent()); + g.setColor(b.getBackground().darker()); + g.drawString(text, textRect.x + 1, textRect.y + fm.getAscent() + 1); + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxMenuItemUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxMenuItemUI.java new file mode 100644 index 0000000..da11898 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxMenuItemUI.java @@ -0,0 +1,104 @@ +/* BasicCheckBoxMenuItemUI.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.event.MouseEvent; + +import javax.swing.JComponent; +import javax.swing.JMenuItem; +import javax.swing.MenuElement; +import javax.swing.MenuSelectionManager; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.ComponentUI; + +/** + * DOCUMENT ME! + */ +public class BasicCheckBoxMenuItemUI extends BasicMenuItemUI +{ + /** + * Factory method to create a BasicCheckBoxMenuItemUI for the given {@link + * JComponent}, which should be a JCheckBoxMenuItem + * + * @param c The {@link JComponent} a UI is being created for. + * + * @return A BasicCheckBoxMenuItemUI for the {@link JComponent}. + */ + public static ComponentUI createUI(final JComponent c) + { + return new BasicCheckBoxMenuItemUI(); + } + + /** + * DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ + protected String getPropertyPrefix() + { + return null; + } + + /** + * This method installs the defaults that are defined in the Basic look and + * feel for this JRadioButtonMenuItem + */ + protected void installDefaults() + { + super.installDefaults(); + + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + checkIcon = defaults.getIcon("CheckBoxMenuItem.checkIcon"); + } + + /** + * DOCUMENT ME! + * + * @param item DOCUMENT ME! + * @param e DOCUMENT ME! + * @param path DOCUMENT ME! + * @param manager DOCUMENT ME! + */ + public void processMouseEvent(JMenuItem item, MouseEvent e, + MenuElement[] path, + MenuSelectionManager manager) + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxUI.java new file mode 100644 index 0000000..e316732 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxUI.java @@ -0,0 +1,73 @@ +/* BasicCheckBoxUI.java + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.ComponentUI; + +public class BasicCheckBoxUI extends BasicRadioButtonUI +{ + + public static ComponentUI createUI(final JComponent c) { + return new BasicCheckBoxUI(); + } + + public Icon getDefaultIcon() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + return defaults.getIcon("CheckBox.icon"); + } + + public void installUI(final JComponent c) { + super.installUI(c); + } + + // Overridden to change method access. + public String getPropertyPrefix() + { + return super.getPropertyPrefix(); + } +} + + + + diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicColorChooserUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicColorChooserUI.java new file mode 100644 index 0000000..4e6d381 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicColorChooserUI.java @@ -0,0 +1,339 @@ +/* BasicColorChooserUI.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.BorderLayout; +import java.awt.Container; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.JColorChooser; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.colorchooser.AbstractColorChooserPanel; +import javax.swing.colorchooser.ColorChooserComponentFactory; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.plaf.ColorChooserUI; +import javax.swing.plaf.ComponentUI; + +/** + * This is the UI Class for the JColorChooser in the Basic Look and Feel. + */ +public class BasicColorChooserUI extends ColorChooserUI +{ + /** + * This helper class handles property changes from the JColorChooser. + */ + public class PropertyHandler implements PropertyChangeListener + { + /** + * This method is called when any of the properties of the JColorChooser + * change. + * + * @param e The PropertyChangeEvent. + */ + public void propertyChange(PropertyChangeEvent e) + { + if (e.getPropertyName() == JColorChooser.CHOOSER_PANELS_PROPERTY) + makeTabs(chooser.getChooserPanels()); + else if (e.getPropertyName() == JColorChooser.PREVIEW_PANEL_PROPERTY) + updatePreviewPanel(chooser.getPreviewPanel()); + else if (e.getPropertyName() == JColorChooser.SELECTION_MODEL_PROPERTY) + ((AbstractColorChooserPanel) pane.getSelectedComponent()) + .updateChooser(); + + chooser.repaint(); + } + } + + /** + * This is a helper class that listens to the Model of the JColorChooser for + * color change events so it can update the preview panel. + */ + private class PreviewListener implements ChangeListener + { + /** + * This method is called whenever the JColorChooser's color changes. + * + * @param e The ChangeEvent. + */ + public void stateChanged(ChangeEvent e) + { + if (pane != null) + { + AbstractColorChooserPanel panel = (AbstractColorChooserPanel) pane + .getSelectedComponent(); + if (panel != null) + panel.updateChooser(); + } + chooser.repaint(); + } + } + + /** + * This helper class listens to the JTabbedPane that is used for tab + * changes. + */ + private class TabPaneListener implements ChangeListener + { + /** + * This method is called whenever a different tab is selected in the + * JTabbedPane. + * + * @param e The ChangeEvent. + */ + public void stateChanged(ChangeEvent e) + { + // Need to do this because we don't update all the tabs when they're not + // visible, so they are not informed of new colors when they're hidden. + AbstractColorChooserPanel comp = (AbstractColorChooserPanel) pane + .getSelectedComponent(); + comp.updateChooser(); + } + } + + /** An array of default choosers to use in the JColorChooser. */ + protected AbstractColorChooserPanel[] defaultChoosers; + + /** The listener for the preview panel. */ + protected ChangeListener previewListener; + + /** The PropertyChangeListener for the JColorChooser. */ + protected PropertyChangeListener propertyChangeListener; + + /** + * The JColorChooser. + * This is package-private to avoid an accessor method. + */ + JColorChooser chooser; + + /** The JTabbedPane that is used. */ + JTabbedPane pane; + + /** The Container that holds the preview panel. */ + private Container prevContainer; + + /** + * Creates a new BasicColorChooserUI object. + */ + public BasicColorChooserUI() + { + super(); + } + + /** + * This method creates a new UI Component for the given JComponent. + * + * @param c The JComponent to create an UI for. + * + * @return A new BasicColorChooserUI. + */ + public static ComponentUI createUI(JComponent c) + { + return new BasicColorChooserUI(); + } + + /** + * This method creates the default chooser panels for the JColorChooser. + * + * @return The default chooser panels. + */ + protected AbstractColorChooserPanel[] createDefaultChoosers() + { + return ColorChooserComponentFactory.getDefaultChooserPanels(); + } + + /** + * This method installs the UI Component for the given JComponent. + * + * @param c The JComponent to install this UI for. + */ + public void installUI(JComponent c) + { + if (c instanceof JColorChooser) + { + chooser = (JColorChooser) c; + chooser.setLayout(new BorderLayout()); + + // Do this first, so we avoid doing work for property change events. + defaultChoosers = createDefaultChoosers(); + chooser.setChooserPanels(defaultChoosers); + pane = new JTabbedPane(); + + pane.addChangeListener(new ChangeListener() + { + public void stateChanged(ChangeEvent e) + { + pane.repaint(); + } + }); + + makeTabs(defaultChoosers); + + chooser.add(pane, BorderLayout.NORTH); + + installPreviewPanel(); + + installDefaults(); + installListeners(); + } + } + + /** + * This method adds tabs to the JTabbedPane for the chooserPanels defined in + * the JColorChooser. + * This is package-private to avoid an accessor method. + * + * @param panels The Panels that need tabs to be made for them. + */ + void makeTabs(AbstractColorChooserPanel[] panels) + { + pane.removeAll(); + for (int i = 0; i < panels.length; i++) + pane.addTab(panels[i].getDisplayName(), panels[i].getSmallDisplayIcon(), + panels[i]); + } + + /** + * This method uninstalls this UI for the given JComponent. + * + * @param c The JComponent that will have this UI removed. + */ + public void uninstallUI(JComponent c) + { + uninstallListeners(); + uninstallDefaults(); + + pane = null; + chooser = null; + } + + /** + * This method installs the preview panel for the JColorChooser. + */ + protected void installPreviewPanel() + { + updatePreviewPanel(ColorChooserComponentFactory.getPreviewPanel()); + } + + /** + * This is a helper method that swaps the existing preview panel with the + * given panel. + * This is package-private to avoid an accessor method. + * + * @param preview The new preview panel. + */ + void updatePreviewPanel(JComponent preview) + { + if (prevContainer == null) + { + prevContainer = new JPanel(); + prevContainer.setLayout(new BorderLayout()); + chooser.add(prevContainer, BorderLayout.CENTER); + } + prevContainer.removeAll(); + prevContainer.add(preview, BorderLayout.CENTER); + } + + /** + * This method installs the default properties given by the Basic Look and + * Feel. + */ + protected void installDefaults() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + chooser.setFont(defaults.getFont("ColorChooser.font")); + chooser.setForeground(defaults.getColor("ColorChooser.foreground")); + chooser.setBackground(defaults.getColor("ColorChooser.background")); + } + + /** + * This method uninstalls the default properties given by the Basic Look and + * Feel. + */ + protected void uninstallDefaults() + { + chooser.setBackground(null); + chooser.setForeground(null); + chooser.setFont(null); + } + + /** + * This method installs any listeners required for this UI to function. + */ + protected void installListeners() + { + propertyChangeListener = createPropertyChangeListener(); + previewListener = new PreviewListener(); + + chooser.addPropertyChangeListener(propertyChangeListener); + chooser.getSelectionModel().addChangeListener(previewListener); + + pane.addChangeListener(new TabPaneListener()); + } + + /** + * This method creates the PropertyChangeListener used for listening to the + * JColorChooser. + * + * @return A PropertyChangeListener. + */ + protected PropertyChangeListener createPropertyChangeListener() + { + return new PropertyHandler(); + } + + /** + * This method uninstalls any listeners that were previously installed by + * the UI. + */ + protected void uninstallListeners() + { + chooser.removePropertyChangeListener(propertyChangeListener); + chooser.getSelectionModel().removeChangeListener(previewListener); + + previewListener = null; + propertyChangeListener = null; + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxEditor.java b/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxEditor.java new file mode 100644 index 0000000..04296df --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxEditor.java @@ -0,0 +1,170 @@ +/* BasicComboBoxEditor.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Component; +import java.awt.event.ActionListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; + +import javax.swing.ComboBoxEditor; +import javax.swing.JTextField; +import javax.swing.border.EmptyBorder; + +/** + * This is a component that is responsible for displaying/editting selected + * item in comboBox. By default, the JTextField is returned as + * BasicComboBoxEditor. + * + * @author Olga Rodimina + */ +public class BasicComboBoxEditor extends Object implements ComboBoxEditor, + FocusListener +{ + protected JTextField editor; + + /** + * Creates a new BasicComboBoxEditor object. + */ + public BasicComboBoxEditor() + { + editor = new JTextField(); + editor.setBorder(new EmptyBorder(1, 1, 1, 1)); + } + + /** + * This method returns textfield that will be used by the combo box to + * display/edit currently selected item in the combo box. + * + * @return textfield that will be used by the combo box to display/edit + * currently selected item + */ + public Component getEditorComponent() + { + return editor; + } + + /** + * Sets item that should be edited when any editing operation is performed + * by the user. The value is always equal to the currently selected value + * in the combo box. Thus whenever a different value is selected from the + * combo box list then this method should be called to change editing + * item to the new selected item. + * + * @param item item that is currently selected in the combo box + */ + public void setItem(Object item) + { + editor.setText(item.toString()); + } + + /** + * This method returns item that is currently editable. + * + * @return item in the combo box that is currently editable + */ + public Object getItem() + { + return editor.getText(); + } + + public void selectAll() + { + editor.selectAll(); + } + + /** + * This method is called when textfield gains focus. This will enable + * editing of the selected item. + * + * @param e the FocusEvent describing change in focus. + */ + public void focusGained(FocusEvent e) + { + // FIXME: Need to implement + } + + /** + * This method is called when textfield loses focus. If during this time any + * editting operation was performed by the user, then it will be cancelled + * and selected item will not be changed. + * + * @param e the FocusEvent describing change in focus + */ + public void focusLost(FocusEvent e) + { + // FIXME: Need to implement + } + + /** + * This method adds actionListener to the editor. If the user will edit + * currently selected item in the textfield and pressEnter, then action + * will be performed. The actionPerformed of this ActionListener should + * change the selected item of the comboBox to the newly editted selected + * item. + * + * @param l the ActionListener responsible for changing selected item of the + * combo box when it is editted by the user. + */ + public void addActionListener(ActionListener l) + { + // FIXME: Need to implement + } + + /** + * This method removes actionListener from the textfield. + * + * @param l the ActionListener to remove from the textfield. + */ + public void removeActionListener(ActionListener l) + { + // FIXME: Need to implement + } + + public static class UIResource extends BasicComboBoxEditor + implements javax.swing.plaf.UIResource + { + /** + * Creates a new UIResource object. + */ + public UIResource() + { + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxRenderer.java b/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxRenderer.java new file mode 100644 index 0000000..e4fbb83 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxRenderer.java @@ -0,0 +1,142 @@ +/* BasicComboBoxRenderer.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Component; +import java.awt.Dimension; +import java.io.Serializable; + +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.ListCellRenderer; +import javax.swing.SwingConstants; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.border.Border; +import javax.swing.border.EmptyBorder; + +/** + * This class is renderer for the combo box. + * + * @author Olga Rodimina + */ +public class BasicComboBoxRenderer extends JLabel implements ListCellRenderer, + Serializable +{ + /** + * This border is used whenever renderer doesn't have a focus. + */ + protected static Border noFocusBorder = new EmptyBorder(0, 0, 0, 0); + + /** + * Creates a new BasicComboBoxRenderer object. + */ + public BasicComboBoxRenderer() + { + setHorizontalAlignment(SwingConstants.LEFT); + } + + /** + * Returns preferredSize of the renderer + * + * @return preferredSize of the renderer + */ + public Dimension getPreferredSize() + { + return super.getPreferredSize(); + } + + /** + * getListCellRendererComponent + * + * @param list List of items for which to the background and foreground + * colors + * @param value object that should be rendered in the cell + * @param index index of the cell in the list of items. + * @param isSelected draw cell highlighted if isSelected is true + * @param cellHasFocus draw focus rectangle around cell if the cell has + * focus + * + * @return Component that will be used to draw the desired cell. + */ + public Component getListCellRendererComponent(JList list, Object value, + int index, boolean isSelected, + boolean cellHasFocus) + { + String s = value.toString(); + setText(s); + setOpaque(true); + + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + if (isSelected) + { + setBackground(list.getSelectionBackground()); + setForeground(list.getSelectionForeground()); + } + else + { + setBackground(list.getBackground()); + setForeground(list.getForeground()); + } + + setEnabled(list.isEnabled()); + setFont(list.getFont()); + + // Use focusCellHighlightBorder when renderer has focus and + // noFocusBorder otherwise + if (cellHasFocus) + setBorder(UIManager.getBorder("List.focusCellHighlightBorder")); + else + setBorder(noFocusBorder); + + return this; + } + + public static class UIResource extends BasicComboBoxRenderer + implements javax.swing.plaf.UIResource + { + /** + * Creates a new UIResource object. + */ + public UIResource() + { + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxUI.java new file mode 100644 index 0000000..68e18a6 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxUI.java @@ -0,0 +1,1243 @@ +/* BasicComboBoxUI.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.LayoutManager; +import java.awt.Rectangle; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.accessibility.Accessible; +import javax.swing.CellRendererPane; +import javax.swing.ComboBoxEditor; +import javax.swing.ComboBoxModel; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JList; +import javax.swing.ListCellRenderer; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; +import javax.swing.plaf.ComboBoxUI; +import javax.swing.plaf.ComponentUI; + +/** + * UI Delegate for JComboBox + * + * @author Olga Rodimina + * @author Robert Schuster + */ +public class BasicComboBoxUI extends ComboBoxUI +{ + /** + * This arrow button that is displayed in the rigth side of JComboBox. This + * button is used to hide and show combo box's list of items + */ + protected JButton arrowButton; + + /** + * The combo box for which this UI delegate is for + */ + protected JComboBox comboBox; + + /** + * Component that is responsible for displaying/editting selected item of + * the combo box. By default JTextField is used as an editor for the + * JComboBox + */ + protected Component editor; + + /** + * Listener listening to focus events occuring in the JComboBox + */ + protected FocusListener focusListener; + + /** + * tells whether JComboBox currently has focus + */ + protected boolean hasFocus; + + /** + * Listener listening to item events fired by the JComboBox + */ + protected ItemListener itemListener; + + /** + * KeyListener listening to key events that occur while JComboBox has focus + */ + protected KeyListener keyListener; + + /** + * MouseListener listening to mouse events occuring in the combo box + */ + private MouseListener mouseListener; + + /** + * List used when rendering selected item of the combo box. The selection + * and foreground colors for combo box renderer are configured from this + * list + */ + protected JList listBox; + + /** + * ListDataListener listening to JComboBox model + */ + protected ListDataListener listDataListener; + + /** + * Popup list containing combo box's menu items + */ + protected ComboPopup popup; + protected KeyListener popupKeyListener; + protected MouseListener popupMouseListener; + protected MouseMotionListener popupMouseMotionListener; + + /** + * Listener listening to changes in the bound properties of JComboBox + */ + protected PropertyChangeListener propertyChangeListener; + + /** + * Colors that are used to render selected item in the combo box. + */ + private Color shadow; + private Color darkShadow; + private Color highlight; + private Color lightHighlight; + + /* Size of the largest item in the comboBox + * This is package-private to avoid an accessor method. + */ + Dimension largestItemSize; + + // It seems that JComboBox doesn't have a border set explicitely. So we just + // paint the border everytime combo box is displayed. + + /* border insets for this JComboBox + * This is package-private to avoid an accessor method. */ + static final Insets borderInsets = new Insets(2, 2, 2, 2); + + // Width of the arrow button + // This is package-private to avoid an accessor method. + // FIXME: has wrong name for a constant. + static final int arrowButtonWidth = 15; + + // FIXME: This fields aren't used anywhere at this moment. + protected Dimension cachedMinimumSize; + protected CellRendererPane currentValuePane; + protected boolean isMinimumSizeDirty; + + /** + * Creates a new BasicComboBoxUI object. + */ + public BasicComboBoxUI() + { + } + + /** + * Factory method to create a BasicComboBoxUI for the given {@link + * JComponent}, which should be a {@link JComboBox}. + * + * @param c The {@link JComponent} a UI is being created for. + * + * @return A BasicComboBoxUI for the {@link JComponent}. + */ + public static ComponentUI createUI(JComponent c) + { + return new BasicComboBoxUI(); + } + + /** + * This method installs the UI for the given JComponent. + * + * @param c The JComponent to install a UI for. + */ + public void installUI(JComponent c) + { + super.installUI(c); + + if (c instanceof JComboBox) + { + comboBox = (JComboBox) c; + comboBox.setOpaque(true); + comboBox.setLayout(createLayoutManager()); + installDefaults(); + installComponents(); + installListeners(); + installKeyboardActions(); + } + } + + /** + * This method uninstalls the UI. + * + * @param c The JComponent that is having this UI removed. + */ + public void uninstallUI(JComponent c) + { + uninstallKeyboardActions(); + uninstallListeners(); + uninstallComponents(); + uninstallDefaults(); + comboBox = null; + } + + /** + * This method installs the defaults that are defined in the Basic look and + * feel for this {@link JComboBox}. + */ + protected void installDefaults() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + comboBox.setBackground(defaults.getColor("ComboBox.background")); + comboBox.setFont(defaults.getFont("ComboBox.font")); + comboBox.setForeground(defaults.getColor("ComboBox.foreground")); + + // Set default color that should be used to to render selected item + // of the combo box. + shadow = defaults.getColor("Button.shadow"); + darkShadow = defaults.getColor("Button.darkShadow"); + lightHighlight = defaults.getColor("Button.light"); + highlight = defaults.getColor("Button.highlight"); + } + + /** + * This method creates and installs the listeners for this UI. + */ + protected void installListeners() + { + // install combo box's listeners + propertyChangeListener = createPropertyChangeListener(); + comboBox.addPropertyChangeListener(propertyChangeListener); + + focusListener = createFocusListener(); + comboBox.addFocusListener(focusListener); + + itemListener = createItemListener(); + comboBox.addItemListener(itemListener); + + keyListener = createKeyListener(); + comboBox.addKeyListener(keyListener); + + mouseListener = createMouseListener(); + comboBox.addMouseListener(mouseListener); + + // install listeners that listen to combo box model + listDataListener = createListDataListener(); + comboBox.getModel().addListDataListener(listDataListener); + + configureArrowButton(); + } + + /** + * This method uninstalls the defaults and sets any objects created during + * install to null + */ + protected void uninstallDefaults() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + comboBox.setBackground(null); + comboBox.setFont(null); + comboBox.setForeground(null); + + shadow = null; + darkShadow = null; + lightHighlight = null; + highlight = null; + } + + /** + * Detaches all the listeners we attached in {@link #installListeners}. + */ + protected void uninstallListeners() + { + comboBox.removePropertyChangeListener(propertyChangeListener); + propertyChangeListener = null; + + comboBox.removeFocusListener(focusListener); + focusListener = null; + + comboBox.removeItemListener(itemListener); + itemListener = null; + + comboBox.removeKeyListener(keyListener); + keyListener = null; + + comboBox.removeMouseListener(mouseListener); + mouseListener = null; + + comboBox.getModel().removeListDataListener(listDataListener); + listDataListener = null; + + unconfigureArrowButton(); + } + + /** + * This method creates popup that will contain list of combo box's items + * + * @return popup containing list of combo box's items + */ + protected ComboPopup createPopup() + { + return new BasicComboPopup(comboBox); + } + + /** + * Creates KeyListener to listen to key events. + * + * @return KeyListener that listens to key events. + */ + protected KeyListener createKeyListener() + { + return new KeyHandler(); + } + + /** + * This method create MouseListener that will listen to mouse event occuring + * in combo box. + * + * @return the MouseListener + */ + private MouseListener createMouseListener() + { + return new MouseHandler(); + } + + /** + * This method create FocusListener that will listen to changes in this + * JComboBox's focus. + * + * @return theFocusListener + */ + protected FocusListener createFocusListener() + { + return new FocusHandler(); + } + + /** + * This method create ListDataListener to listen to ComboBox's data model + * + * @return ListDataListener + */ + protected ListDataListener createListDataListener() + { + return new ListDataHandler(); + } + + /** + * This method creates ItemListener that will listen to to the changes in + * the JComboBox's selection. + * + * @return the ItemListener + */ + protected ItemListener createItemListener() + { + return new ItemHandler(); + } + + /** + * This method creates PropertyChangeListener to listen to the changes in + * the JComboBox's bound properties. + * + * @return the PropertyChangeListener + */ + protected PropertyChangeListener createPropertyChangeListener() + { + return new PropertyChangeHandler(); + } + + /** + * This method returns layout manager for the combo box. + * + * @return layout manager for the combo box + */ + protected LayoutManager createLayoutManager() + { + return new ComboBoxLayoutManager(); + } + + /** + * This method creates component that will be responsible for rendering the + * selected component in the combo box. + * + * @return render for the combo box + */ + protected ListCellRenderer createRenderer() + { + return new BasicComboBoxRenderer(); + } + + /** + * Creates component that will be responsible for displaying/editting + * selected item in the combo box. This editor is used only when combo box + * is editable. + * + * @return component that will be responsible for displaying/editting + * selected item in the combo box. + */ + protected ComboBoxEditor createEditor() + { + return new BasicComboBoxEditor(); + } + + /** + * This method installs components for this JComboBox. ArrowButton, main + * part of combo box (upper part) and popup list of items are created and + * configured here. + */ + protected void installComponents() + { + // create and install arrow button + arrowButton = createArrowButton(); + + comboBox.add(arrowButton); + + // Set list that will be used by BasicComboBoxRender + // in order to determine the right colors when rendering + listBox = new JList(); + + Color background = arrowButton.getBackground(); + listBox.setBackground(background); + listBox.setSelectionBackground(background.darker()); + + Color foreground = arrowButton.getForeground(); + listBox.setForeground(foreground); + listBox.setSelectionForeground(foreground); + + // set editor and renderer for the combo box. Editor is used + // only if combo box becomes editable, otherwise renderer is used + // to paint the selected item; combobox is not editable by default. + comboBox.setRenderer(createRenderer()); + + comboBox.setEditor(createEditor()); + editor = comboBox.getEditor().getEditorComponent(); + + // create drop down list of items + popup = createPopup(); + + comboBox.revalidate(); + } + + /** + * This method uninstalls components from this JComboBox + */ + protected void uninstallComponents() + { + // uninstall arrow button + unconfigureArrowButton(); + comboBox.remove(arrowButton); + arrowButton = null; + + listBox = null; + popup = null; + + comboBox.setRenderer(null); + + comboBox.setEditor(null); + editor = null; + } + + /** + * This method adds editor to the combo box + */ + public void addEditor() + { + comboBox.add(editor); + } + + /** + * This method removes editor from the combo box + */ + public void removeEditor() + { + comboBox.remove(editor); + } + + /** + * This method configures editor for this combo box. + */ + protected void configureEditor() + { + // FIXME: Need to implement. Set font and add listeners. + } + + /** + * This method removes all the listeners for the editor. + */ + protected void unconfigureEditor() + { + // FIXME: Need to implement + } + + /** + * This method adds listeners to the arrow button part of the combo box. + */ + public void configureArrowButton() + { + arrowButton.addMouseListener(mouseListener); + } + + /** + * This method removes listeners from the arrow button part of the combo + * box. + */ + public void unconfigureArrowButton() + { + arrowButton.removeMouseListener(mouseListener); + } + + /** + * This method create arrow button for this JComboBox. Arrow button is + * responsible for displaying / hiding drop down list of items when it is + * clicked. + * + * @return JButton arrow button for this JComboBox. + */ + protected JButton createArrowButton() + { + return new BasicArrowButton(BasicArrowButton.SOUTH); + } + + /** + * This method checks if popup part of the combo box is visible on the + * screen + * + * @param c The JComboBox to check + * + * @return true if popup part of the JComboBox is visible and false + * otherwise. + */ + public boolean isPopupVisible(JComboBox c) + { + return popup.isVisible(); + } + + /** + * Displays/Hides JComboBox's list of items on the screen. + * + * @param c The combo box, for which list of items should be + * displayed/hidden + * @param v true if show popup part of the jcomboBox and false to hide. + */ + public void setPopupVisible(JComboBox c, boolean v) + { + if (v) + popup.show(); + else + popup.hide(); + } + + /** + * JComboBox is focus traversable if it is editable and not otherwise. + * + * @param c combo box for which to check whether it is focus traversable + * + * @return true if focus tranversable and false otherwise + */ + public boolean isFocusTraversable(JComboBox c) + { + if (comboBox.isEditable()) + return true; + + return false; + } + + /** + * Paints given menu item using specified graphics context + * + * @param g The graphics context used to paint this combo box + * @param c comboBox which needs to be painted. + */ + public void paint(Graphics g, JComponent c) + { + if (c instanceof JComboBox) + { + JComboBox cb = (JComboBox) c; + + paintBorder(g, comboBox.getBounds(), hasFocus); + + Rectangle rect = rectangleForCurrentValue(); + paintCurrentValueBackground(g, rect, hasFocus); + paintCurrentValue(g, rect, hasFocus); + } + } + + private void paintBorder(Graphics g, Rectangle bounds, boolean hasFocus) + { + int x = 0; + int y = 0; + int width = bounds.width; + int height = bounds.height; + + Color oldColor = g.getColor(); + + if (! arrowButton.getModel().isPressed()) + BasicGraphicsUtils.drawEtchedRect(g, x, y, width, height, Color.gray, + Color.white, Color.gray, Color.white); + else + { + g.setColor(darkShadow); + g.drawRect(x, y, width, height); + g.setColor(shadow); + g.drawRect(x + 1, y + 1, width - 3, height - 3); + } + g.setColor(oldColor); + } + + /** + * Returns preferred size for the given menu item. + * + * @param c comboBox for which to get preferred size + * + * @return $Dimension$ preferred size for the given combo box + */ + public Dimension getPreferredSize(JComponent c) + { + // return null to indicate that combo box's layout will determin its + // preferred size + return null; + } + + /** + * This method returns the minimum size for this {@link JComboBox} for this + * look and feel. + * + * @param c The {@link JComponent} to find the minimum size for. + * + * @return The dimensions of the minimum size. + */ + public Dimension getMinimumSize(JComponent c) + { + return null; + } + + /** + * This method returns the maximum size for this {@link JComboBox} for this + * look and feel. + * + * @param c The {@link JComponent} to find the maximum size for + * + * @return The dimensions of the minimum size. + */ + public Dimension getMaximumSize(JComponent c) + { + return null; + } + + public int getAccessibleChildrenCount(JComponent c) + { + // FIXME: Need to implement + return 0; + } + + public Accessible getAccessibleChild(JComponent c, int i) + { + // FIXME: Need to implement + return null; + } + + /** + * Returns true if the specified key is a navigation key and false otherwise + * + * @param keyCode a key for which to check whether it is navigation key or + * not. + * + * @return true if the specified key is a navigation key and false otherwis + */ + protected boolean isNavigationKey(int keyCode) + { + return false; + } + + /** + * This method selects next possible item relative to the current selection + * to be next selected item in the combo box. + */ + protected void selectNextPossibleValue() + { + int index = comboBox.getSelectedIndex(); + if (index != comboBox.getItemCount() - 1) + comboBox.setSelectedIndex(index + 1); + } + + /** + * This method selects previous item relative to current selection to be + * next selected item. + */ + protected void selectPreviousPossibleValue() + { + int index = comboBox.getSelectedIndex(); + if (index != 0) + comboBox.setSelectedIndex(index - 1); + } + + /** + * This method displays combo box popup if the popup is not currently shown + * on the screen and hides it if it is currently shown + */ + protected void toggleOpenClose() + { + setPopupVisible(comboBox, ! isPopupVisible(comboBox)); + } + + /** + * This method returns bounds in which comboBox's selected Item will be + * displayed + * + * @return rectangle bounds in which comboBox's selected Item will be + * displayed + */ + protected Rectangle rectangleForCurrentValue() + { + Rectangle cbBounds = comboBox.getBounds(); + + // Subtract width or the arrow button and border insets + Rectangle rectForCurrentValue = new Rectangle(cbBounds.x + + borderInsets.left, + cbBounds.y + + borderInsets.top, + cbBounds.width + - arrowButtonWidth + - borderInsets.left + - borderInsets.right, + cbBounds.height + - borderInsets.top + - borderInsets.bottom); + + return rectForCurrentValue; + } + + /** + * This method returns insets of the current border. + * + * @return Insets representing space between combo box and its border + */ + protected Insets getInsets() + { + return new Insets(0, 0, 0, 0); + } + + /** + * This method paints currently selected value in the main part of the combo + * box (part without popup). + * + * @param g graphics context + * @param bounds Rectangle representing the size of the area in which + * selected item should be drawn + * @param hasFocus true if combo box has focus and false otherwise + */ + public void paintCurrentValue(Graphics g, Rectangle bounds, boolean hasFocus) + { + if (! comboBox.isEditable()) + { + Object currentValue = comboBox.getSelectedItem(); + boolean isPressed = arrowButton.getModel().isPressed(); + + /* Gets the component to be drawn for the current value. + * If there is currently no selected item we will take an empty + * String as replacement. + */ + Component comp = comboBox.getRenderer() + .getListCellRendererComponent(listBox, + (currentValue != null ? currentValue : ""), + -1, + isPressed, + hasFocus); + if (! comboBox.isEnabled()) + comp.setEnabled(false); + + g.translate(borderInsets.left, borderInsets.top); + comp.setBounds(0, 0, bounds.width, bounds.height); + comp.paint(g); + g.translate(-borderInsets.left, -borderInsets.top); + + comboBox.revalidate(); + } + else + comboBox.getEditor().setItem(comboBox.getSelectedItem()); + } + + /** + * This method paints background of part of the combo box, where currently + * selected value is displayed. If the combo box has focus this method + * should also paint focus rectangle around the combo box. + * + * @param g graphics context + * @param bounds Rectangle representing the size of the largest item in the + * comboBox + * @param hasFocus true if combo box has fox and false otherwise + */ + public void paintCurrentValueBackground(Graphics g, Rectangle bounds, + boolean hasFocus) + { + // background is painted by renderer, so it seems that nothing + // should be done here. + } + + /** + * Returns default size for the combo box that doesn't contain any elements + * in it + * + * @return Default size of the combo box with no elements in it. + */ + protected Dimension getDefaultSize() + { + return new Dimension(6, 17); + } + + /** + * Returns size of the largest item in the combo box. This size will be the + * size of the combo box, not including the arrowButton. + * + * @return dimensions of the largest item in the combo box. + */ + protected Dimension getLargestItemSize() + { + ComboBoxModel model = comboBox.getModel(); + int numItems = model.getSize(); + + // if combo box doesn't have any items then simply + // return its default size + if (numItems == 0) + { + largestItemSize = getDefaultSize(); + return largestItemSize; + } + + Dimension size = new Dimension(0, 0); + + // ComboBox's display size should be equal to the + // size of the largest item in the combo box. + ListCellRenderer renderer = comboBox.getRenderer(); + + for (int i = 0; i < numItems; i++) + { + Object item = model.getElementAt(i); + String s = item.toString(); + Component comp = renderer.getListCellRendererComponent(listBox, item, + -1, false, false); + + if (comp.getPreferredSize().getWidth() > size.getWidth()) + size = comp.getPreferredSize(); + } + + largestItemSize = size; + return largestItemSize; + } + + /** + * This method installs the keyboard actions for the JComboBox as specified + * by the look and feel. + */ + protected void installKeyboardActions() + { + // FIXME: Need to implement. + } + + /** + * This method uninstalls the keyboard actions for the JComboBox there were + * installed by in {@link #installListeners}. + */ + protected void uninstallKeyboardActions() + { + // FIXME: Need to implement. + } + + /** + * This class is Layout Manager for this combo box. + */ + public class ComboBoxLayoutManager extends Object implements LayoutManager + { + /** + * Creates a new ComboBoxLayoutManager object. + */ + public ComboBoxLayoutManager() + { + } + + public void addLayoutComponent(String name, Component comp) + { + // Do nothing + } + + public void removeLayoutComponent(Component comp) + { + // Do nothing + } + + /** + * Returns preferred layout size of the JComboBox. + * + * @param parent Container for which preferred size should be calculated + * + * @return preferred size for the given container + */ + public Dimension preferredLayoutSize(Container parent) + { + Dimension d = new Dimension(0, 0); + + if (largestItemSize == null) + largestItemSize = getLargestItemSize(); + + // add size for the area that will display selected item + d.width += largestItemSize.getWidth(); + d.height += largestItemSize.getHeight(); + + // add size of the arrow button + d.width += arrowButtonWidth; + + // add width and height of the border + d.width += borderInsets.left + borderInsets.right; + d.height += borderInsets.left + borderInsets.right; + + // Add combo box's insets + Insets insets = parent.getInsets(); + d.width += insets.left + insets.right; + d.width += insets.left + insets.right; + + return d; + } + + public Dimension minimumLayoutSize(Container parent) + { + return preferredLayoutSize(parent); + } + + /** + * This method layouts out the components in the container. It puts arrow + * button right end part of the comboBox. If the comboBox is editable + * then editor is placed to the left of arrow button, starting from the + * beginning. + * + * @param parent Container that should be layed out. + */ + public void layoutContainer(Container parent) + { + // Position editor component to the left of arrow button if combo box is + // editable + int editorWidth = comboBox.getBounds().width - arrowButtonWidth - 2; + + if (comboBox.isEditable()) + editor.setBounds(borderInsets.left, borderInsets.top, editorWidth, + comboBox.getBounds().height - borderInsets.left + - borderInsets.top); + + arrowButton.setBounds(editorWidth, 2, arrowButtonWidth, + comboBox.getBounds().height - 4); + comboBox.revalidate(); + } + } + + /** + * This class handles focus changes occuring in the combo box. This class is + * responsible for repainting combo box whenever focus is gained or lost + * and also for hiding popup list of items whenever combo box loses its + * focus. + */ + public class FocusHandler extends Object implements FocusListener + { + /** + * Creates a new FocusHandler object. + */ + public FocusHandler() + { + } + + /** + * This mehtod is invoked when combo box gains focus. It repaints main + * part of combo box accordingally. + * + * @param e the FocusEvent + */ + public void focusGained(FocusEvent e) + { + hasFocus = true; + comboBox.repaint(); + } + + /** + * This method is invoked when combo box loses focus It repaint main part + * of combo box accordingally and hides popup list of items. + * + * @param e the FocusEvent + */ + public void focusLost(FocusEvent e) + { + hasFocus = false; + comboBox.repaint(); + popup.hide(); + } + } + + /** + * This class handles ItemEvent fired by the JComboBox when its selected + * item changes. + */ + public class ItemHandler extends Object implements ItemListener + { + /** + * Creates a new ItemHandler object. + */ + public ItemHandler() + { + } + + /** + * This method is invoked when selected item becomes deselected or when + * new item becomes selected. + * + * @param e the ItemEvent representing item's state change. + */ + public void itemStateChanged(ItemEvent e) + { + comboBox.repaint(); + } + } + + /** + * KeyHandler handles key events occuring while JComboBox has focus. + */ + public class KeyHandler extends KeyAdapter + { + public KeyHandler() + { + } + + /* + * This method is invoked whenever key is pressed while JComboBox is in + * focus. + */ + public void keyPressed(KeyEvent e) + { + // FIXME: This method calls JComboBox.selectWithKeyChar if the key that was + // pressed is not a navigation key. + } + } + + /** + * This class handles to the changes occuring in the JComboBox's data model + */ + public class ListDataHandler extends Object implements ListDataListener + { + /** + * Creates a new ListDataHandler object. + */ + public ListDataHandler() + { + } + + /** + * This method is invoked content's of JComboBox's data model are changed + * + * @param e ListDataEvent describing the change. + */ + public void contentsChanged(ListDataEvent e) + { + // if the item is selected or deselected + } + + /** + * This method is invoked when items were added to the JComboBox's data + * model. + * + * @param e ListDataEvent describing the change. + */ + public void intervalAdded(ListDataEvent e) + { + // must determine if the size of the combo box should change + int start = e.getIndex0(); + int end = e.getIndex1(); + + ComboBoxModel model = comboBox.getModel(); + ListCellRenderer renderer = comboBox.getRenderer(); + + if (largestItemSize == null) + largestItemSize = new Dimension(0, 0); + + for (int i = start; i < end; i++) + { + Object item = model.getElementAt(i); + Component comp = renderer.getListCellRendererComponent(new JList(), + item, -1, + false, false); + if (comp.getPreferredSize().getWidth() > largestItemSize.getWidth()) + largestItemSize = comp.getPreferredSize(); + } + } + + /** + * This method is invoked when items were removed from the JComboBox's + * data model. + * + * @param e ListDataEvent describing the change. + */ + public void intervalRemoved(ListDataEvent e) + { + // recalculate display size of the JComboBox. + largestItemSize = getLargestItemSize(); + comboBox.repaint(); + } + } + + /** + * This class handles PropertyChangeEvents fired by JComboBox. + */ + public class PropertyChangeHandler extends Object + implements PropertyChangeListener + { + public PropertyChangeHandler() + { + } + + /** + * This method is invoked whenever bound property of JComboBox changes. + */ + public void propertyChange(PropertyChangeEvent e) + { + if (e.getPropertyName().equals("enabled")) + { + arrowButton.setEnabled(comboBox.isEnabled()); + + if (comboBox.isEditable()) + comboBox.getEditor().getEditorComponent().setEnabled(comboBox + .isEnabled()); + } + else if (e.getPropertyName().equals("editable")) + { + if (comboBox.isEditable()) + { + configureEditor(); + addEditor(); + } + else + { + unconfigureEditor(); + removeEditor(); + } + + comboBox.revalidate(); + comboBox.repaint(); + } + else if (e.getPropertyName().equals("dataModel")) + { + // remove ListDataListener from old model and add it to new model + ComboBoxModel oldModel = (ComboBoxModel) e.getOldValue(); + if (oldModel != null) + oldModel.removeListDataListener(listDataListener); + + if ((ComboBoxModel) e.getNewValue() != null) + comboBox.getModel().addListDataListener(listDataListener); + } + + // FIXME: Need to handle changes in other bound properties. + } + } + + /** + * MouseHandler listens to mouse events occuring in the combo box. This + * class is responsible for repainting this JComboBox whenever the mouse is + * being pressed or released over it. + */ + private class MouseHandler extends MouseAdapter + { + /** + * This method is invoked when mouse is pressed over the combo box. It + * repaints the combo box accordinglly + * + * @param e the MouseEvent + */ + public void mousePressed(MouseEvent e) + { + if (comboBox.isEnabled()) + { + if (e.getSource() instanceof JComboBox) + { + arrowButton.getModel().setPressed(true); + arrowButton.getModel().setArmed(true); + } + + comboBox.repaint(); + + if (e.getSource() instanceof BasicArrowButton) + toggleOpenClose(); + } + } + + /** + * This method is invoked when mouse is released over the combo box. It + * repaints the combo box accordinglly + * + * @param e the MouseEvent + */ + public void mouseReleased(MouseEvent e) + { + if (comboBox.isEnabled()) + { + if (e.getSource() instanceof JComboBox) + { + arrowButton.getModel().setPressed(false); + arrowButton.getModel().setArmed(false); + } + + comboBox.repaint(); + } + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicComboPopup.java b/libjava/classpath/javax/swing/plaf/basic/BasicComboPopup.java new file mode 100644 index 0000000..73aac8d --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicComboPopup.java @@ -0,0 +1,1055 @@ +/* BasicComboPopup.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionAdapter; +import java.awt.event.MouseMotionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.ComboBoxModel; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPopupMenu; +import javax.swing.JScrollBar; +import javax.swing.JScrollPane; +import javax.swing.ListCellRenderer; +import javax.swing.ListSelectionModel; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.Timer; +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; + +/** + * UI Delegate for ComboPopup + * + * @author Olga Rodimina + */ +public class BasicComboPopup extends JPopupMenu implements ComboPopup +{ + /* Timer for autoscrolling */ + protected Timer autoscrollTimer; + + /** ComboBox associated with this popup */ + protected JComboBox comboBox; + + /** FIXME: Need to document */ + protected boolean hasEntered; + + /** + * Indicates whether the scroll bar located in popup menu with comboBox's + * list of items is currently autoscrolling. This happens when mouse event + * originated in the combo box and is dragged outside of its bounds + */ + protected boolean isAutoScrolling; + + /** ItemListener listening to the selection changes in the combo box */ + protected ItemListener itemListener; + + /** This listener is not used */ + protected KeyListener keyListener; + + /** JList which is used to display item is the combo box */ + protected JList list; + + /** This listener is not used */ + protected ListDataListener listDataListener; + + /** + * MouseListener listening to mouse events occuring in the combo box's + * list. + */ + protected MouseListener listMouseListener; + + /** + * MouseMotionListener listening to mouse motion events occuring in the + * combo box's list + */ + protected MouseMotionListener listMouseMotionListener; + + /** This listener is not used */ + protected ListSelectionListener listSelectionListener; + + /** MouseListener listening to mouse events occuring in the combo box */ + protected MouseListener mouseListener; + + /** + * MouseMotionListener listening to mouse motion events occuring in the + * combo box + */ + protected MouseMotionListener mouseMotionListener; + + /** + * PropertyChangeListener listening to changes occuring in the bound + * properties of the combo box + */ + protected PropertyChangeListener propertyChangeListener; + + /** direction for scrolling down list of combo box's items */ + protected static final int SCROLL_DOWN = 1; + + /** direction for scrolling up list of combo box's items */ + protected static final int SCROLL_UP = 0; + + /** Indicates auto scrolling direction */ + protected int scrollDirection; + + /** JScrollPane that contains list portion of the combo box */ + protected JScrollPane scroller; + + /** This field is not used */ + protected boolean valueIsAdjusting; + + /** + * Creates a new BasicComboPopup object. + * + * @param comboBox the combo box with which this popup should be associated + */ + public BasicComboPopup(JComboBox comboBox) + { + this.comboBox = comboBox; + installComboBoxListeners(); + configurePopup(); + setLightWeightPopupEnabled(comboBox.isLightWeightPopupEnabled()); + } + + /** + * This method displays drow down list of combo box items on the screen. + */ + public void show() + { + Rectangle cbBounds = comboBox.getBounds(); + + // popup should have same width as the comboBox and should be hight anough + // to display number of rows equal to 'maximumRowCount' property + int popupHeight = getPopupHeightForRowCount(comboBox.getMaximumRowCount()); + + list.setPreferredSize(new Dimension(cbBounds.width, popupHeight)); + super.setPopupSize(cbBounds.width, popupHeight); + + // Highlight selected item in the combo box's drop down list + if (comboBox.getSelectedIndex() != -1) + list.setSelectedIndex(comboBox.getSelectedIndex()); + + //scroll scrollbar s.t. selected item is visible + JScrollBar scrollbar = scroller.getVerticalScrollBar(); + int selectedIndex = comboBox.getSelectedIndex(); + if (selectedIndex > comboBox.getMaximumRowCount()) + scrollbar.setValue(getPopupHeightForRowCount(selectedIndex)); + + // location specified is relative to comboBox + super.show(comboBox, 0, cbBounds.height); + } + + /** + * This method hides drop down list of items + */ + public void hide() + { + super.setVisible(false); + } + + /** + * Return list cointaining JComboBox's items + * + * @return list cointaining JComboBox's items + */ + public JList getList() + { + return list; + } + + /** + * Returns MouseListener that is listening to mouse events occuring in the + * combo box. + * + * @return MouseListener + */ + public MouseListener getMouseListener() + { + return mouseListener; + } + + /** + * Returns MouseMotionListener that is listening to mouse motion events + * occuring in the combo box. + * + * @return MouseMotionListener + */ + public MouseMotionListener getMouseMotionListener() + { + return mouseMotionListener; + } + + /** + * Returns KeyListener listening to key events occuring in the combo box. + * This method returns null because KeyHandler is not longer used. + * + * @return KeyListener + */ + public KeyListener getKeyListener() + { + return keyListener; + } + + /** + * This method uninstalls the UI for the given JComponent. + */ + public void uninstallingUI() + { + uninstallComboBoxModelListeners(comboBox.getModel()); + + uninstallListeners(); + uninstallKeyboardActions(); + } + + /** + * This method uninstalls listeners that were listening to changes occuring + * in the comb box's data model + * + * @param model data model for the combo box from which to uninstall + * listeners + */ + protected void uninstallComboBoxModelListeners(ComboBoxModel model) + { + model.removeListDataListener(listDataListener); + } + + /** + * This method uninstalls keyboard actions installed by the UI. + */ + protected void uninstallKeyboardActions() + { + // FIXME: Need to implement + } + + /** + * This method fires PopupMenuEvent indicating that combo box's popup list + * of items will become visible + */ + protected void firePopupMenuWillBecomeVisible() + { + PopupMenuListener[] ll = comboBox.getPopupMenuListeners(); + + for (int i = 0; i < ll.length; i++) + ll[i].popupMenuWillBecomeVisible(new PopupMenuEvent(comboBox)); + } + + /** + * This method fires PopupMenuEvent indicating that combo box's popup list + * of items will become invisible. + */ + protected void firePopupMenuWillBecomeInvisible() + { + PopupMenuListener[] ll = comboBox.getPopupMenuListeners(); + + for (int i = 0; i < ll.length; i++) + ll[i].popupMenuWillBecomeInvisible(new PopupMenuEvent(comboBox)); + } + + /** + * This method fires PopupMenuEvent indicating that combo box's popup list + * of items was closed without selection. + */ + protected void firePopupMenuCanceled() + { + PopupMenuListener[] ll = comboBox.getPopupMenuListeners(); + + for (int i = 0; i < ll.length; i++) + ll[i].popupMenuCanceled(new PopupMenuEvent(comboBox)); + } + + /** + * Creates MouseListener to listen to mouse events occuring in the combo + * box. Note that this listener doesn't listen to mouse events occuring in + * the popup portion of the combo box, it only listens to main combo box + * part. + * + * @return new MouseMotionListener that listens to mouse events occuring in + * the combo box + */ + protected MouseListener createMouseListener() + { + return new InvocationMouseHandler(); + } + + /** + * Create Mouse listener that listens to mouse dragging events occuring in + * the combo box. This listener is responsible for changing the selection + * in the combo box list to the component over which mouse is being + * currently dragged + * + * @return new MouseMotionListener that listens to mouse dragging events + * occuring in the combo box + */ + protected MouseMotionListener createMouseMotionListener() + { + return new InvocationMouseMotionHandler(); + } + + /** + * KeyListener created in this method is not used anymore. + * + * @return KeyListener that does nothing + */ + protected KeyListener createKeyListener() + { + return new InvocationKeyHandler(); + } + + /** + * ListSelectionListener created in this method is not used anymore + * + * @return ListSelectionListener that does nothing + */ + protected ListSelectionListener createListSelectionListener() + { + return new ListSelectionHandler(); + } + + /** + * Creates ListDataListener. This method returns null, because + * ListDataHandler class is obsolete and is no longer used. + * + * @return null + */ + protected ListDataListener createListDataListener() + { + return null; + } + + /** + * This method creates ListMouseListener to listen to mouse events occuring + * in the combo box's item list. + * + * @return MouseListener to listen to mouse events occuring in the combo + * box's items list. + */ + protected MouseListener createListMouseListener() + { + return new ListMouseHandler(); + } + + /** + * Creates ListMouseMotionlistener to listen to mouse motion events occuring + * in the combo box's list. This listener is responsible for highlighting + * items in the list when mouse is moved over them. + * + * @return MouseMotionListener that handles mouse motion events occuring in + * the list of the combo box. + */ + protected MouseMotionListener createListMouseMotionListener() + { + return new ListMouseMotionHandler(); + } + + /** + * Creates PropertyChangeListener to handle changes in the JComboBox's bound + * properties. + * + * @return PropertyChangeListener to handle changes in the JComboBox's bound + * properties. + */ + protected PropertyChangeListener createPropertyChangeListener() + { + return new PropertyChangeHandler(); + } + + /** + * Creates new ItemListener that will listen to ItemEvents occuring in the + * combo box. + * + * @return ItemListener to listen to ItemEvents occuring in the combo box. + */ + protected ItemListener createItemListener() + { + return new ItemHandler(); + } + + /** + * Creates JList that will be used to display items in the combo box. + * + * @return JList that will be used to display items in the combo box. + */ + protected JList createList() + { + JList l = new JList(comboBox.getModel()); + l.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION); + return l; + } + + /** + * This method configures the list of comboBox's items by setting default + * properties and installing listeners. + */ + protected void configureList() + { + list.setModel(comboBox.getModel()); + list.setVisibleRowCount(comboBox.getMaximumRowCount()); + installListListeners(); + } + + /** + * This method installs list listeners. + */ + protected void installListListeners() + { + // mouse listener listening to mouse events occuring in the + // combo box's list of items. + listMouseListener = createListMouseListener(); + list.addMouseListener(listMouseListener); + + // mouse listener listening to mouse motion events occuring in the + // combo box's list of items + listMouseMotionListener = createListMouseMotionListener(); + list.addMouseMotionListener(listMouseMotionListener); + + listSelectionListener = createListSelectionListener(); + list.addListSelectionListener(listSelectionListener); + } + + /** + * This method creates scroll pane that will contain the list of comboBox's + * items inside of it. + * + * @return JScrollPane + */ + protected JScrollPane createScroller() + { + return new JScrollPane(); + } + + /** + * This method configures scroll pane to contain list of comboBox's items + */ + protected void configureScroller() + { + scroller.getViewport().setView(list); + scroller.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + } + + /** + * This method configures popup menu that will be used to display Scrollpane + * with list of items inside of it. + */ + protected void configurePopup() + { + // initialize list that will be used to display combo box's items + this.list = createList(); + ((JLabel) list.getCellRenderer()).setHorizontalAlignment(SwingConstants.LEFT); + configureList(); + + // initialize scroller. Add list to the scroller. + scroller = createScroller(); + configureScroller(); + + // add scroller with list inside of it to JPopupMenu + super.add(scroller); + } + + /* + * This method installs listeners that will listen to changes occuring + * in the combo box. + */ + protected void installComboBoxListeners() + { + // mouse listener that listens to mouse event in combo box + mouseListener = createMouseListener(); + comboBox.addMouseListener(mouseListener); + + // mouse listener that listens to mouse dragging events in the combo box + mouseMotionListener = createMouseMotionListener(); + comboBox.addMouseMotionListener(mouseMotionListener); + + // item listener listenening to selection events in the combo box + itemListener = createItemListener(); + comboBox.addItemListener(itemListener); + + propertyChangeListener = createPropertyChangeListener(); + comboBox.addPropertyChangeListener(propertyChangeListener); + } + + /** + * This method installs listeners that will listen to changes occuring in + * the comb box's data model + * + * @param model data model for the combo box for which to install listeners + */ + protected void installComboBoxModelListeners(ComboBoxModel model) + { + // list data listener to listen for ListDataEvents in combo box. + // This listener is now obsolete and nothing is done here + listDataListener = createListDataListener(); + comboBox.getModel().addListDataListener(listDataListener); + } + + /** + * DOCUMENT ME! + */ + protected void installKeyboardActions() + { + // FIXME: Need to implement + } + + /** + * This method always returns false to indicate that items in the combo box + * list are not focus traversable. + * + * @return false + */ + public boolean isFocusTraversable() + { + return false; + } + + /** + * This method start scrolling combo box's list of items either up or down + * depending on the specified 'direction' + * + * @param direction of the scrolling. + */ + protected void startAutoScrolling(int direction) + { + // FIXME: add timer + isAutoScrolling = true; + + if (direction == SCROLL_UP) + autoScrollUp(); + else + autoScrollDown(); + } + + /** + * This method stops scrolling the combo box's list of items + */ + protected void stopAutoScrolling() + { + // FIXME: add timer + isAutoScrolling = false; + } + + /** + * This method scrolls up list of combo box's items up and highlights that + * just became visible. + */ + protected void autoScrollUp() + { + // scroll up the scroll bar to make the item above visible + JScrollBar scrollbar = scroller.getVerticalScrollBar(); + int scrollToNext = list.getScrollableUnitIncrement(super.getBounds(), + SwingConstants.VERTICAL, + SCROLL_UP); + + scrollbar.setValue(scrollbar.getValue() - scrollToNext); + + // If we haven't reached the begging of the combo box's list of items, + // then highlight next element above currently highlighted element + if (list.getSelectedIndex() != 0) + list.setSelectedIndex(list.getSelectedIndex() - 1); + } + + /** + * This method scrolls down list of combo box's and highlights item in the + * list that just became visible. + */ + protected void autoScrollDown() + { + // scroll scrollbar down to make next item visible + JScrollBar scrollbar = scroller.getVerticalScrollBar(); + int scrollToNext = list.getScrollableUnitIncrement(super.getBounds(), + SwingConstants.VERTICAL, + SCROLL_DOWN); + scrollbar.setValue(scrollbar.getValue() + scrollToNext); + + // If we haven't reached the end of the combo box's list of items + // then highlight next element below currently highlighted element + if (list.getSelectedIndex() + 1 != comboBox.getItemCount()) + list.setSelectedIndex(list.getSelectedIndex() + 1); + } + + /** + * This method helps to delegate focus to the right component in the + * JComboBox. If the comboBox is editable then focus is sent to + * ComboBoxEditor, otherwise it is delegated to JComboBox. + * + * @param e MouseEvent + */ + protected void delegateFocus(MouseEvent e) + { + // FIXME: Need to implement + } + + /** + * This method displays combo box popup if the popup is not currently shown + * on the screen and hides it if it is currently visible + */ + protected void togglePopup() + { + if (BasicComboPopup.this.isVisible()) + hide(); + else + show(); + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected MouseEvent convertMouseEvent(MouseEvent e) + { + return null; + } + + /** + * Returns required height of the popup such that number of items visible in + * it are equal to the maximum row count. By default + * comboBox.maximumRowCount=8 + * + * @param maxRowCount number of maximum visible rows in the combo box's + * popup list of items + * + * @return height of the popup required to fit number of items equal to + * JComboBox.maximumRowCount. + */ + protected int getPopupHeightForRowCount(int maxRowCount) + { + int totalHeight = 0; + ListCellRenderer rend = list.getCellRenderer(); + + if (comboBox.getItemCount() < maxRowCount) + maxRowCount = comboBox.getItemCount(); + + for (int i = 0; i < maxRowCount; i++) + { + Component comp = rend.getListCellRendererComponent(list, + comboBox.getModel() + .getElementAt(i), + -1, false, false); + Dimension dim = comp.getPreferredSize(); + totalHeight += dim.height; + } + + return totalHeight; + } + + /** + * DOCUMENT ME! + * + * @param px DOCUMENT ME! + * @param py DOCUMENT ME! + * @param pw DOCUMENT ME! + * @param ph DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected Rectangle computePopupBounds(int px, int py, int pw, int ph) + { + return new Rectangle(px, py, pw, ph); + } + + /** + * This method changes the selection in the list to the item over which the + * mouse is currently located. + * + * @param anEvent MouseEvent + * @param shouldScroll DOCUMENT ME! + */ + protected void updateListBoxSelectionForEvent(MouseEvent anEvent, + boolean shouldScroll) + { + // FIXME: Need to implement + } + + /** + * InvocationMouseHandler is a listener that listens to mouse events + * occuring in the combo box. Note that this listener doesn't listen to + * mouse events occuring in the popup portion of the combo box, it only + * listens to main combo box part(area that displays selected item). This + * listener is responsible for showing and hiding popup portion of the + * combo box. + */ + protected class InvocationMouseHandler extends MouseAdapter + { + /** + * Creates a new InvocationMouseHandler object. + */ + protected InvocationMouseHandler() + { + } + + /** + * This method is invoked whenever mouse is being pressed over the main + * part of the combo box. This method will show popup if the popup is + * not shown on the screen right now, and it will hide popup otherwise. + * + * @param e MouseEvent that should be handled + */ + public void mousePressed(MouseEvent e) + { + if (comboBox.isEnabled()) + togglePopup(); + } + + /** + * This method is invoked whenever mouse event was originated in the combo + * box and released either in the combBox list of items or in the combo + * box itself. + * + * @param e MouseEvent that should be handled + */ + public void mouseReleased(MouseEvent e) + { + // Get component over which mouse was released + Component src = (Component) e.getSource(); + int x = e.getX(); + int y = e.getY(); + Component releasedComponent = SwingUtilities.getDeepestComponentAt(src, + x, y); + + // if mouse was released inside the bounds of combo box then do nothing, + // Otherwise if mouse was released inside the list of combo box items + // then change selection and close popup + if (! (releasedComponent instanceof JComboBox)) + { + // List model contains the item over which mouse is released, + // since it is updated every time the mouse is moved over a different + // item in the list. Now that the mouse is released we need to + // update model of the combo box as well. + comboBox.setSelectedIndex(list.getSelectedIndex()); + + if (isAutoScrolling) + stopAutoScrolling(); + hide(); + } + } + } + + /** + * InvocationMouseMotionListener is a mouse listener that listens to mouse + * dragging events occuring in the combo box. + */ + protected class InvocationMouseMotionHandler extends MouseMotionAdapter + { + /** + * Creates a new InvocationMouseMotionHandler object. + */ + protected InvocationMouseMotionHandler() + { + } + + /** + * This method is responsible for highlighting item in the drop down list + * over which the mouse is currently being dragged. + */ + public void mouseDragged(MouseEvent e) + { + // convert point of the drag event relative to combo box list component + // figure out over which list cell the mouse is currently being dragged + // and highlight the cell. The list model is changed but the change has + // no effect on combo box's data model. The list model is changed so + // that the appropriate item would be highlighted in the combo box's + // list. + if (BasicComboPopup.this.isVisible()) + { + int cbHeight = (int) comboBox.getPreferredSize().getHeight(); + int popupHeight = BasicComboPopup.this.getSize().height; + + // if mouse is dragged inside the the combo box's items list. + if (e.getY() > cbHeight && ! (e.getY() - cbHeight >= popupHeight)) + { + int index = list.locationToIndex(new Point(e.getX(), + (int) (e.getY() + - cbHeight))); + + int firstVisibleIndex = list.getFirstVisibleIndex(); + + // list.locationToIndex returns item's index that would + // be located at the specified point if the first item that + // is visible is item 0. However in the JComboBox it is not + // necessarily the case since list is contained in the + // JScrollPane so we need to adjust the index returned. + if (firstVisibleIndex != 0) + // FIXME: adjusted index here is off by one. I am adding one + // here to compensate for that. This should be + // index += firstVisibleIndex. Remove +1 once the bug is fixed. + index += firstVisibleIndex + 1; + + list.setSelectedIndex(index); + } + else + { + // if mouse is being dragged at the bottom of combo box's list + // of items or at the very top then scroll the list in the + // desired direction. + boolean movingUP = e.getY() < cbHeight; + boolean movingDown = e.getY() > cbHeight; + + if (movingUP) + { + scrollDirection = SCROLL_UP; + startAutoScrolling(SCROLL_UP); + } + else if (movingDown) + { + scrollDirection = SCROLL_DOWN; + startAutoScrolling(SCROLL_DOWN); + } + } + } + } + } + + /** + * ItemHandler is an item listener that listens to selection events occuring + * in the combo box. FIXME: should specify here what it does when item is + * selected or deselected in the combo box list. + */ + protected class ItemHandler extends Object implements ItemListener + { + /** + * Creates a new ItemHandler object. + */ + protected ItemHandler() + { + } + + /** + * This method responds to the selection events occuring in the combo box. + * + * @param e ItemEvent specifying the combo box's selection + */ + public void itemStateChanged(ItemEvent e) + { + } + } + + /** + * ListMouseHandler is a listener that listens to mouse events occuring in + * the combo box's list of items. This class is responsible for hiding + * popup portion of the combo box if the mouse is released inside the combo + * box's list. + */ + protected class ListMouseHandler extends MouseAdapter + { + protected ListMouseHandler() + { + } + + public void mousePressed(MouseEvent e) + { + } + + public void mouseReleased(MouseEvent anEvent) + { + int index = list.locationToIndex(anEvent.getPoint()); + comboBox.setSelectedIndex(index); + hide(); + } + } + + /** + * ListMouseMotionHandler listens to mouse motion events occuring in the + * combo box's list. This class is responsible for highlighting items in + * the list when mouse is moved over them + */ + protected class ListMouseMotionHandler extends MouseMotionAdapter + { + protected ListMouseMotionHandler() + { + } + + public void mouseMoved(MouseEvent anEvent) + { + // Highlight list cells over which the mouse is located. + // This changes list model, but has no effect on combo box's data model + int index = list.locationToIndex(anEvent.getPoint()); + list.setSelectedIndex(index); + list.repaint(); + } + } + + /** + * This class listens to changes occuring in the bound properties of the + * combo box + */ + protected class PropertyChangeHandler extends Object + implements PropertyChangeListener + { + protected PropertyChangeHandler() + { + } + + public void propertyChange(PropertyChangeEvent e) + { + if (e.getPropertyName().equals("renderer")) + { + list.setCellRenderer((ListCellRenderer) e.getNewValue()); + revalidate(); + repaint(); + } + if (e.getPropertyName().equals("dataModel")) + { + list.setModel((ComboBoxModel) e.getNewValue()); + revalidate(); + repaint(); + } + } + } + + // ------ private helper methods -------------------- + + /** + * This method uninstalls listeners installed by the UI + */ + private void uninstallListeners() + { + uninstallListListeners(); + uninstallComboBoxListeners(); + uninstallComboBoxModelListeners(comboBox.getModel()); + } + + /** + * This method uninstalls Listeners registered with combo boxes list of + * items + */ + private void uninstallListListeners() + { + list.removeMouseListener(listMouseListener); + listMouseListener = null; + + list.removeMouseMotionListener(listMouseMotionListener); + listMouseMotionListener = null; + } + + /** + * This method uninstalls listeners listening to combo box associated with + * this popup menu + */ + private void uninstallComboBoxListeners() + { + comboBox.removeMouseListener(mouseListener); + mouseListener = null; + + comboBox.removeMouseMotionListener(mouseMotionListener); + mouseMotionListener = null; + + comboBox.removeItemListener(itemListener); + itemListener = null; + + comboBox.removePropertyChangeListener(propertyChangeListener); + propertyChangeListener = null; + } + + // -------------------------------------------------------------------- + // The following classes are here only for backwards API compatibility + // They aren't used. + // -------------------------------------------------------------------- + + /** + * This class is not used any more. + */ + public class ListDataHandler extends Object implements ListDataListener + { + public ListDataHandler() + { + } + + public void contentsChanged(ListDataEvent e) + { + } + + public void intervalAdded(ListDataEvent e) + { + } + + public void intervalRemoved(ListDataEvent e) + { + } + } + + /** + * This class is not used anymore + */ + protected class ListSelectionHandler extends Object + implements ListSelectionListener + { + protected ListSelectionHandler() + { + } + + public void valueChanged(ListSelectionEvent e) + { + } + } + + /** + * This class is not used anymore + */ + public class InvocationKeyHandler extends KeyAdapter + { + public InvocationKeyHandler() + { + } + + public void keyReleased(KeyEvent e) + { + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicDesktopIconUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicDesktopIconUI.java new file mode 100644 index 0000000..561b497 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicDesktopIconUI.java @@ -0,0 +1,590 @@ +/* BasicDesktopIconUI.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyVetoException; + +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JDesktopPane; +import javax.swing.JInternalFrame; +import javax.swing.JInternalFrame.JDesktopIcon; +import javax.swing.SwingConstants; +import javax.swing.border.Border; +import javax.swing.event.MouseInputAdapter; +import javax.swing.event.MouseInputListener; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.DesktopIconUI; + +/** + * This class acts as the UI delegate for JDesktopIcons for the Basic look and feel. + */ +public class BasicDesktopIconUI extends DesktopIconUI +{ + /** + * This helper class handles mouse events that occur on the JDesktopIcon. + */ + public class MouseInputHandler extends MouseInputAdapter + { + /** The x offset from the MouseEvent coordinates to the top left corner. */ + private transient int xOffset; + + /** The y offset fromt he MouseEvent coordinates to the top left corner. */ + private transient int yOffset; + + /** A cached value of the JDesktopPane that parents this JDesktopIcon. */ + private transient JDesktopPane pane; + + /** + * This method is called when the mouse is dragged in the JDesktopIcon. + * + * @param e The MouseEvent. + */ + public void mouseDragged(MouseEvent e) + { + Rectangle b = desktopIcon.getBounds(); + + moveAndRepaint(desktopIcon, b.x + e.getX() - xOffset, + b.y + e.getY() - yOffset, b.width, b.height); + } + + /** + * This method is called when the mouse is moved in the JDesktopIcon. + * + * @param e The MouseEvent. + */ + public void mouseMoved(MouseEvent e) + { + // Nothing to do. + } + + /** + * This method is called when the mouse is pressed in the JDesktopIcon. + * + * @param e The MouseEvent. + */ + public void mousePressed(MouseEvent e) + { + xOffset = e.getX(); + yOffset = e.getY(); + pane = frame.getDesktopPane(); + if (pane != null) + pane.getDesktopManager().beginDraggingFrame(desktopIcon); + } + + /** + * This method is called when the mouse is released in the JDesktopIcon. + * + * @param e The MouseEvent. + */ + public void mouseReleased(MouseEvent e) + { + if (pane != null) + pane.getDesktopManager().endDraggingFrame(desktopIcon); + xOffset = 0; + yOffset = 0; + } + + /** + * This method moves and repaints the JDesktopIcon to the given bounds. + * + * @param f The JComponent to move and repaint. + * @param newX The new x coordinate. + * @param newY The new y coordinate. + * @param newWidth The new width. + * @param newHeight The new height. + */ + public void moveAndRepaint(JComponent f, int newX, int newY, int newWidth, + int newHeight) + { + if (pane != null) + pane.getDesktopManager().dragFrame(f, newX, newY); + else + desktopIcon.setBounds(newX, newY, newWidth, newHeight); + } + } + + /** + * This class acts as the border for the JDesktopIcon. + */ + private class DesktopIconBorder implements Border + { + /** The left inset value. */ + int left = 10; + + /** The top inset value. */ + int top = 4; + + /** The right inset value. */ + int right = top; + + /** The bottom inset value. */ + int bottom = top; + + /** + * This method returns the insets of the border. + * + * @param c The Component to find border insets for. + * + * @return The border insets. + */ + public Insets getBorderInsets(Component c) + { + return new Insets(top, left, bottom, right); + } + + /** + * This method returns whether the border is opaque. + * + * @return Whether the border is opaque. + */ + public boolean isBorderOpaque() + { + return true; + } + + /** + * This method paints the border. + * + * @param c The Component the border is in. + * @param g The Graphics object to paint with. + * @param x The x coordinate of the Component. + * @param y The y coordinate of the Component. + * @param width The width of the Component. + * @param height The height of the Component. + */ + public void paintBorder(Component c, Graphics g, int x, int y, int width, + int height) + { + g.translate(x, y); + Color saved = g.getColor(); + + g.setColor(Color.LIGHT_GRAY); + + g.fillRect(0, 0, left, height); + g.fillRect(0, 0, width, top); + g.fillRect(0, height - bottom, width, bottom); + g.fillRect(width - right, 0, right, height); + + g.setColor(Color.BLACK); + g.drawRect(0, 0, width - 1, height - 1); + + int fHeight = height / 4; + int hLeft = left / 2; + + g.setColor(Color.BLACK); + g.fillRect(hLeft, fHeight, 2, 2); + g.fillRect(hLeft, fHeight * 2, 2, 2); + g.fillRect(hLeft, fHeight * 3, 2, 2); + + g.setColor(saved); + g.translate(-x, -y); + } + } + + /** The static width and height of the iconSize. */ + private static final int iconSize = 16; + + /** + * This class represents the default frame icon when none + * is supplied by the JInternalFrame. + */ + static class InternalFrameDefaultMenuIcon implements Icon + { + /** + * This returns the icon height. + * + * @return The icon height. + */ + public int getIconHeight() + { + return iconSize; + } + + /** + * This returns the icon width. + * + * @return The icon width. + */ + public int getIconWidth() + { + return iconSize; + } + + /** + * This method paints the icon. + * + * @param c The Component this icon belongs to. + * @param g The Graphics object to paint with. + * @param x The x coordinate to paint at. + * @param y The y coordinate to paint at. + */ + public void paintIcon(Component c, Graphics g, int x, int y) + { + g.translate(x, y); + Color saved = g.getColor(); + + g.setColor(Color.BLUE); + g.fillRect(0, 0, iconSize, (int) ((double) iconSize / 3) + 1); + + g.setColor(Color.WHITE); + g.fillRect(0, (int) ((double) iconSize / 3), iconSize, iconSize * 5 / 6); + + g.setColor(Color.GRAY); + g.drawRect(0, 0, iconSize, iconSize); + + g.setColor(saved); + g.translate(-x, -y); + } + } + + /** The default JDesktopIcon width. */ + private static final int iconWidth = 160; + + /** The default JDesktopIcon height */ + private static final int iconHeight = 35; + + /** The JDesktopIcon this UI delegate represents. */ + protected JDesktopIcon desktopIcon; + + /** The JInternalFrame associated with the JDesktopIcon. */ + protected JInternalFrame frame; + + /** The MouseListener responsible for reacting to MouseEvents on the JDesktopIcon. */ + private transient MouseInputListener mouseHandler; + + /** The Button in the JDesktopIcon responsible for deiconifying it. + * This is package-private to avoid an accessor method. */ + transient BoundButton button; + + /** The PropertyChangeListener listening to the JDesktopIcon. */ + private transient PropertyChangeListener propertyHandler; + + /** The default icon used when no frame icon is given by the JInternalFrame. */ + static Icon defaultIcon = new InternalFrameDefaultMenuIcon(); + + /** + * This is a helper class that is used in JDesktopIcon and gives the Button a predetermined size. + */ + private class BoundButton extends JButton + { + /** + * Creates a new BoundButton object. + * + * @param title The title of the button. + */ + public BoundButton(String title) + { + super(title); + } + + /** + * This method returns a standard size (based on the defaults of the JDesktopIcon) and the insets. + * + * @return The preferred size of the JDesktopIcon. + */ + public Dimension getPreferredSize() + { + Insets insets = desktopIcon.getInsets(); + return new Dimension(iconWidth - insets.left - insets.right, + iconHeight - insets.top - insets.bottom); + } + + /** + * This method returns the minimum size of the button. + * + * @return The minimum size of the button. + */ + public Dimension getMinimumSize() + { + return getPreferredSize(); + } + + /** + * This method returns the maximum size of the button. + * + * @return The maximum size of the button. + */ + public Dimension getMaximumSize() + { + return getPreferredSize(); + } + } + + /** + * Creates a new BasicDesktopIconUI object. + */ + public BasicDesktopIconUI() + { + } + + /** + * This method creates a new BasicDesktopIconUI for the given JComponent. + * + * @param c The JComponent to create a UI for. + * + * @return A new BasicDesktopIconUI. + */ + public static ComponentUI createUI(JComponent c) + { + return new BasicDesktopIconUI(); + } + + /** + * This method installs the UI for the given JComponent. + * + * @param c The JComponent to install this UI for. + */ + public void installUI(JComponent c) + { + if (c instanceof JDesktopIcon) + { + desktopIcon = (JDesktopIcon) c; + desktopIcon.setLayout(new BorderLayout()); + frame = desktopIcon.getInternalFrame(); + + installDefaults(); + installComponents(); + installListeners(); + + desktopIcon.setOpaque(true); + } + } + + /** + * This method uninstalls the UI for the given JComponent. + * + * @param c The JComponent to uninstall this UI for. + */ + public void uninstallUI(JComponent c) + { + desktopIcon.setOpaque(false); + + uninstallListeners(); + uninstallComponents(); + uninstallDefaults(); + + frame = null; + desktopIcon.setLayout(null); + desktopIcon = null; + } + + /** + * This method installs the necessary sub components for the JDesktopIcon. + */ + protected void installComponents() + { + // Try to create a button based on what the frame's + // state is currently + button = new BoundButton(frame.getTitle()); + button.setHorizontalAlignment(SwingConstants.LEFT); + button.setHorizontalTextPosition(SwingConstants.TRAILING); + + Icon use = frame.getFrameIcon(); + if (use == null) + use = defaultIcon; + button.setIcon(use); + + desktopIcon.add(button, SwingConstants.CENTER); + } + + /** + * This method uninstalls the sub components for the JDesktopIcon. + */ + protected void uninstallComponents() + { + desktopIcon.remove(button); + + button = null; + } + + /** + * This method installs the listeners needed by this UI. + */ + protected void installListeners() + { + mouseHandler = createMouseInputListener(); + + desktopIcon.addMouseMotionListener(mouseHandler); + desktopIcon.addMouseListener(mouseHandler); + + propertyHandler = new PropertyChangeListener() + { + public void propertyChange(PropertyChangeEvent e) + { + if (e.getPropertyName().equals(JInternalFrame.TITLE_PROPERTY)) + button.setText(desktopIcon.getInternalFrame().getTitle()); + else if (e.getPropertyName().equals(JInternalFrame.FRAME_ICON_PROPERTY)) + { + Icon use = desktopIcon.getInternalFrame().getFrameIcon(); + if (use == null) + use = defaultIcon; + button.setIcon(use); + } + desktopIcon.revalidate(); + desktopIcon.repaint(); + } + }; + frame.addPropertyChangeListener(propertyHandler); + + button.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + deiconize(); + } + }); + } + + /** + * This method uninstalls the listeners needed by the UI. + */ + protected void uninstallListeners() + { + // button is nulled so no need to remove it. + + frame.removePropertyChangeListener(propertyHandler); + propertyHandler = null; + + desktopIcon.removeMouseMotionListener(mouseHandler); + desktopIcon.removeMouseListener(mouseHandler); + } + + /** + * This method installs the defaults for the JDesktopIcon. + */ + protected void installDefaults() + { + // FIXME: Move border to defaults. + desktopIcon.setBorder(new DesktopIconBorder()); + } + + /** + * This method uninstalls the defaults for the JDesktopIcon. + */ + protected void uninstallDefaults() + { + desktopIcon.setBorder(null); + } + + /** + * This method creates a new MouseInputListener for the JDesktopIcon. + * + * @return A new MouseInputListener. + */ + protected MouseInputListener createMouseInputListener() + { + return new MouseInputHandler(); + } + + /** + * This method returns the preferred size for the given JComponent. + * + * @param c The JComponent to find a preferred size for. + * + * @return The preferred size. + */ + public Dimension getPreferredSize(JComponent c) + { + return new Dimension(iconWidth, iconHeight); + } + + /** + * This method returns the minimum size for the given JComponent. + * + * @param c The JComponent to find a minimum size for. + * + * @return The minimum size. + */ + public Dimension getMinimumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the maximum size for the given JComponent. + * + * @param c The JComponent to find a maximum size for. + * + * @return The maximum size. + */ + public Dimension getMaximumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the insets of the given JComponent. + * + * @param c The JComponent to find insets for. + * + * @return The insets of the given JComponent. + */ + public Insets getInsets(JComponent c) + { + return c.getInsets(); + } + + /** + * This method deiconizes the JInternalFrame associated with the JDesktopIcon. + */ + public void deiconize() + { + try + { + frame.setIcon(false); + } + catch (PropertyVetoException pve) + { + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicDesktopPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicDesktopPaneUI.java new file mode 100644 index 0000000..b15700d --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicDesktopPaneUI.java @@ -0,0 +1,464 @@ +/* BasicDesktopPaneUI.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.beans.PropertyVetoException; + +import javax.swing.AbstractAction; +import javax.swing.DefaultDesktopManager; +import javax.swing.DesktopManager; +import javax.swing.JComponent; +import javax.swing.JDesktopPane; +import javax.swing.JInternalFrame; +import javax.swing.KeyStroke; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.DesktopPaneUI; + +/** + * This class is the UI delegate for JDesktopPane for the Basic look and feel. + */ +public class BasicDesktopPaneUI extends DesktopPaneUI +{ + /** + * This helper class is used to handle key events that cause JInternalFrames + * to be closed. + */ + protected class CloseAction extends AbstractAction + { + /** + * This method is called when the action is performed. + * + * @param e The ActionEvent. + */ + public void actionPerformed(ActionEvent e) + { + if (desktop.getSelectedFrame() != null) + { + try + { + desktop.getSelectedFrame().setClosed(true); + } + catch (PropertyVetoException pve) + { + } + } + } + + /** + * This method returns whether the action is enabled. + * + * @return Whether the action is enabled. + */ + public boolean isEnabled() + { + if (desktop.getSelectedFrame() != null) + return desktop.getSelectedFrame().isClosable(); + return false; + } + } + + /** + * This helper class is used to handle key events that cause JInternalFrames + * to be maximized. + */ + protected class MaximizeAction extends AbstractAction + { + /** + * This method is called when the action is performed. + * + * @param e The ActionEvent. + */ + public void actionPerformed(ActionEvent e) + { + if (desktop.getSelectedFrame() != null) + { + try + { + desktop.getSelectedFrame().setMaximum(true); + } + catch (PropertyVetoException pve) + { + } + } + } + + /** + * This method returns whether the action is enabled. + * + * @return Whether the action is enabled. + */ + public boolean isEnabled() + { + if (desktop.getSelectedFrame() != null) + return desktop.getSelectedFrame().isMaximizable(); + return false; + } + } + + /** + * This helper class is used to handle key events that cause JInternalFrames + * to be minimized. + */ + protected class MinimizeAction extends AbstractAction + { + /** + * This method is called when the action is performed. + * + * @param e The ActionEvent. + */ + public void actionPerformed(ActionEvent e) + { + if (desktop.getSelectedFrame() != null) + { + try + { + desktop.getSelectedFrame().setIcon(true); + } + catch (PropertyVetoException pve) + { + } + } + } + + /** + * This method returns whether the action is enabled. + * + * @return Whether the action is enabled. + */ + public boolean isEnabled() + { + if (desktop.getSelectedFrame() != null) + return desktop.getSelectedFrame().isIconifiable(); + return false; + } + } + + /** + * This helper class is used to handle key events that pass the SELECTED + * property to the next JInternalFrame in the JDesktopPane's list of + * children. + */ + protected class NavigateAction extends AbstractAction + { + /** + * This method is called when the action is performed. + * + * @param e The ActionEvent. + */ + public void actionPerformed(ActionEvent e) + { + // This is supposed to set the next selected frame. + JInternalFrame[] frames = desktop.getAllFrames(); + if (frames.length == 0) + return; + + JInternalFrame sFrame = frames[0]; + if (desktop.getSelectedFrame() != null) + sFrame = desktop.getSelectedFrame(); + + int i = 0; + for (; i < frames.length; i++) + if (frames[i] == sFrame) + break; + + // FIXME: Navigate actions go reverse too. + if (i == frames.length) + i = 0; + + desktop.setSelectedFrame(frames[i]); + } + + /** + * This method returns whether the action is enabled. + * + * @return Whether this action is enabled. + */ + public boolean isEnabled() + { + // Always true. + return true; + } + } + + /** + * This helper class is used to restore the JInternalFrame to its original + * size before maximizing or iconifying. + */ + protected class OpenAction extends AbstractAction + { + /** + * This method is called when the action is performed. + * + * @param e The ActionEvent. + */ + public void actionPerformed(ActionEvent e) + { + JInternalFrame frame = desktop.getSelectedFrame(); + if (frame != null) + { + try + { + if (frame.isIcon()) + frame.setIcon(false); + else if (frame.isMaximum()) + frame.setMaximum(false); + } + catch (PropertyVetoException pve) + { + } + } + } + + /** + * This method returns whether the action is enabled. + * + * @return Whether this action is enabled. + */ + public boolean isEnabled() + { + // JInternalFrames are always restorable. + return true; + } + } + + /** + * The KeyStroke associated with closing JInternalFrames. + * @deprecated + */ + protected KeyStroke closeKey; + + /** + * The KeyStroke associated with maximizing JInternalFrames. + * @deprecated + */ + protected KeyStroke maximizeKey; + + /** + * The KeyStroke associated with minimizing JInternalFrames. + * @deprecated + */ + protected KeyStroke minimizeKey; + + /** + * The KeyStroke associated with navigating (forward?) through + * JInternalFrames. + * @deprecated + */ + protected KeyStroke navigateKey; + + /** + * The KeyStroke associated with navigating (backward?) through + * JInternalFrames. + * @deprecated + */ + protected KeyStroke navigateKey2; + + /** The default desktop manager used with JDesktopPane. */ + protected DesktopManager desktopManager; + + /** The JDesktopPane this UI is used with. */ + protected JDesktopPane desktop; + + /** + * Creates a new BasicDesktopPaneUI object. + */ + public BasicDesktopPaneUI() + { + } + + /** + * This method creates a BasicDesktopPaneUI for the given JComponent. + * + * @param c The JComponent to create a UI for. + * + * @return A new BasicDesktopPaneUI. + */ + public static ComponentUI createUI(JComponent c) + { + return new BasicDesktopPaneUI(); + } + + /** + * This method returns the maximum size for the given JComponent. + * + * @param c The JComponent to find a maximum size for. + * + * @return The maximum size for the given JComponent. + */ + public Dimension getMaximumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the minimum size for the given JComponent. + * + * @param c The JComponent to find a minimum size for. + * + * @return The minimum size for the given JComponent. + */ + public Dimension getMinimumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the preferred size for the given JComponent. + * + * @param c The JComponent to find a preferred size for. + * + * @return The preferred size for the given JComponent. + */ + public Dimension getPreferredSize(JComponent c) + { + // return null because JDesktopPanes don't have preferred sizes. + return null; + } + + /** + * This method installs the defaults for the JDesktopPane provided by the + * current look and feel. + */ + protected void installDefaults() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + desktop.setBackground(defaults.getColor("Desktop.background")); + } + + /** + * This method installs the desktop manager for the JDesktopPane. + */ + protected void installDesktopManager() + { + desktopManager = new DefaultDesktopManager(); + desktop.setDesktopManager(desktopManager); + } + + /** + * This method installs the keyboard actions for the JDesktopPane. + */ + protected void installKeyboardActions() + { + // FIXME: create actions and keystrokes. + registerKeyboardAction(); + } + + /** + * This method installs the UI for the given JComponent. + * + * @param c The JComponent to install this UI for. + */ + public void installUI(JComponent c) + { + if (c instanceof JDesktopPane) + { + desktop = (JDesktopPane) c; + + installDefaults(); + installDesktopManager(); + installKeyboardActions(); + } + } + + /** + * This method registers the actions to the appropriate Action and Input + * maps. + */ + protected void registerKeyboardAction() + { + // FIXME: Do the binding. + // XXX: the gtk windows tend to intercept a lot of the + // key events for themselves. must figure a way past that + // before binding + } + + /** + * This method reverses the work done by the installDefaults method. + */ + protected void uninstallDefaults() + { + desktop.setBackground(null); + } + + /** + * This method reverses the work done by the installDesktopManager method. + */ + protected void uninstallDesktopManager() + { + desktopManager = null; + desktop.setDesktopManager(null); + } + + /** + * This method reverses the work done by the installKeyboardActions method. + */ + protected void uninstallKeyboardActions() + { + unregisterKeyboardActions(); + // FIXME: null the actions and keystrokes. + } + + /** + * This method reverses the work done by the registerKeyboardActions method. + */ + protected void unregisterKeyboardActions() + { + // FIXME: unmap the keystrokes + } + + /** + * This method uninstalls the UI for the given JComponent. It should reverse + * all the work done by the installUI method. + * + * @param c The JComponent to uninstall this UI for. + */ + public void uninstallUI(JComponent c) + { + uninstallKeyboardActions(); + uninstallDesktopManager(); + uninstallDefaults(); + + desktop = null; + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicDirectoryModel.java b/libjava/classpath/javax/swing/plaf/basic/BasicDirectoryModel.java new file mode 100644 index 0000000..a694f32 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicDirectoryModel.java @@ -0,0 +1,313 @@ +/* BasicDirectoryModel.java -- + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf.basic; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.File; +import java.util.Collections; +import java.util.Comparator; +import java.util.Enumeration; +import java.util.Vector; +import javax.swing.AbstractListModel; +import javax.swing.JFileChooser; +import javax.swing.event.ListDataEvent; +import javax.swing.filechooser.FileSystemView; + + +/** + * DOCUMENT ME! + */ +public class BasicDirectoryModel extends AbstractListModel + implements PropertyChangeListener +{ + /** DOCUMENT ME! */ + private Vector contents; + + /** DOCUMENT ME! */ + private int directories; + + /** DOCUMENT ME! */ + private int listingMode; + + /** DOCUMENT ME! */ + private JFileChooser filechooser; + + /** DOCUMENT ME! */ + private Comparator comparator = new Comparator() + { + public int compare(Object o1, Object o2) + { + if (lt((File) o1, (File) o2)) + return -1; + else + return 1; + } + }; + + /** + * Creates a new BasicDirectoryModel object. + * + * @param filechooser DOCUMENT ME! + */ + public BasicDirectoryModel(JFileChooser filechooser) + { + this.filechooser = filechooser; + filechooser.addPropertyChangeListener(this); + listingMode = filechooser.getFileSelectionMode(); + contents = new Vector(); + } + + /** + * DOCUMENT ME! + * + * @param o DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean contains(Object o) + { + return contents.contains(o); + } + + /** + * DOCUMENT ME! + */ + public void fireContentsChanged() + { + fireContentsChanged(this, 0, getSize() - 1); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Vector getDirectories() + { + Vector tmp = new Vector(); + for (int i = 0; i < directories; i++) + tmp.add(contents.get(i)); + return tmp; + } + + /** + * DOCUMENT ME! + * + * @param index DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Object getElementAt(int index) + { + if (index > getSize() - 1) + return null; + if (listingMode == JFileChooser.FILES_ONLY) + return contents.get(directories + index); + else + return contents.elementAt(index); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Vector getFiles() + { + Vector tmp = new Vector(); + for (int i = directories; i < getSize(); i++) + tmp.add(contents.get(i)); + return tmp; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public int getSize() + { + if (listingMode == JFileChooser.DIRECTORIES_ONLY) + return directories; + else if (listingMode == JFileChooser.FILES_ONLY) + return contents.size() - directories; + return contents.size(); + } + + /** + * DOCUMENT ME! + * + * @param o DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public int indexOf(Object o) + { + if (listingMode == JFileChooser.FILES_ONLY) + return contents.indexOf(o) - directories; + return contents.indexOf(o); + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void intervalAdded(ListDataEvent e) + { + // obsoleted + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void intervalRemoved(ListDataEvent e) + { + // obsoleted + } + + /** + * DOCUMENT ME! + */ + public void invalidateFileCache() + { + // obsoleted + } + + /** + * DOCUMENT ME! + * + * @param a DOCUMENT ME! + * @param b DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected boolean lt(File a, File b) + { + boolean aTrav = filechooser.isTraversable(a); + boolean bTrav = filechooser.isTraversable(b); + + if (aTrav == bTrav) + { + String aname = a.getName().toLowerCase(); + String bname = b.getName().toLowerCase(); + return ((aname.compareTo(bname) < 0) ? true : false); + } + else + { + if (aTrav) + return true; + else + return false; + } + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void propertyChange(PropertyChangeEvent e) + { + if (e.getPropertyName().equals(JFileChooser.FILE_SELECTION_MODE_CHANGED_PROPERTY)) + listingMode = filechooser.getFileSelectionMode(); + } + + /** + * DOCUMENT ME! + * + * @param oldFile DOCUMENT ME! + * @param newFile DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean renameFile(File oldFile, File newFile) + { + // FIXME: implement + return false; + } + + /** + * DOCUMENT ME! + * + * @param v DOCUMENT ME! + */ + protected void sort(Vector v) + { + Collections.sort(v, comparator); + Enumeration e = Collections.enumeration(v); + Vector tmp = new Vector(); + for (; e.hasMoreElements();) + tmp.add(e.nextElement()); + + contents = tmp; + } + + /** + * DOCUMENT ME! + */ + public void validateFileCache() + { + contents.clear(); + directories = 0; + FileSystemView fsv = filechooser.getFileSystemView(); + File[] list = fsv.getFiles(filechooser.getCurrentDirectory(), + filechooser.isFileHidingEnabled()); + + if (list == null) + return; + + for (int i = 0; i < list.length; i++) + { + if (list[i] == null) + continue; + if (filechooser.accept(list[i])) + { + contents.add(list[i]); + if (filechooser.isTraversable(list[i])) + directories++; + } + } + sort(contents); + filechooser.revalidate(); + filechooser.repaint(); + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicEditorPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicEditorPaneUI.java new file mode 100644 index 0000000..6dd15a8 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicEditorPaneUI.java @@ -0,0 +1,68 @@ +/* BasicEditorPaneUI.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.text.Element; +import javax.swing.text.PlainView; +import javax.swing.text.View; + +public class BasicEditorPaneUI extends BasicTextUI +{ + public static ComponentUI createUI(JComponent comp) + { + return new BasicEditorPaneUI(); + } + + public BasicEditorPaneUI() + { + // Do nothing here. + } + + public View create(Element elem) + { + return new PlainView(elem); + } + + protected String getPropertyPrefix() + { + return "EditorPane"; + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicFileChooserUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicFileChooserUI.java new file mode 100644 index 0000000..fd34fbd --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicFileChooserUI.java @@ -0,0 +1,1921 @@ +/* BasicFileChooserUI.java -- + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf.basic; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Point; +import java.awt.Polygon; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Hashtable; +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.BoxLayout; +import javax.swing.ButtonGroup; +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JFileChooser; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextField; +import javax.swing.JToggleButton; +import javax.swing.ListCellRenderer; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.Timer; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.filechooser.FileFilter; +import javax.swing.filechooser.FileSystemView; +import javax.swing.filechooser.FileView; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.FileChooserUI; + + +/** + * DOCUMENT ME! + */ +public class BasicFileChooserUI extends FileChooserUI +{ + /** + * DOCUMENT ME! + */ + protected class AcceptAllFileFilter extends FileFilter + { + public AcceptAllFileFilter() + { + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public boolean accept(File f) + { + return true; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getDescription() + { + return acceptAllFileFilterText; + } + } + + /** + * DOCUMENT ME! + */ + protected class ApproveSelectionAction extends AbstractAction + { + /** + * Creates a new ApproveSelectionAction object. + */ + protected ApproveSelectionAction() + { + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void actionPerformed(ActionEvent e) + { + Object obj = filelist.getSelectedValue(); + if (obj != null) + { + File f = filechooser.getFileSystemView().createFileObject(obj + .toString()); + if (filechooser.isTraversable(f) && + filechooser.getFileSelectionMode() == JFileChooser.FILES_ONLY) + filechooser.setCurrentDirectory(f); + else + { + filechooser.setSelectedFile(f); + filechooser.approveSelection(); + closeDialog(); + } + } + } + } + + /** + * DOCUMENT ME! + */ + protected class BasicFileView extends FileView + { + /** DOCUMENT ME! */ + protected Hashtable iconCache = new Hashtable(); + + public BasicFileView() + { + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * @param i DOCUMENT ME! + */ + public void cacheIcon(File f, Icon i) + { + iconCache.put(f, i); + } + + /** + * DOCUMENT ME! + */ + public void clearIconCache() + { + iconCache.clear(); + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Icon getCachedIcon(File f) + { + return (Icon) iconCache.get(f); + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getDescription(File f) + { + return getName(f); + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Icon getIcon(File f) + { + Icon val = getCachedIcon(f); + if (val != null) + return val; + if (filechooser.isTraversable(f)) + val = directoryIcon; + else + val = fileIcon; + cacheIcon(f, val); + return val; + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getName(File f) + { + return f.getName(); + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getTypeDescription(File f) + { + if (filechooser.isTraversable(f)) + return dirDescText; + else + return fileDescText; + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Boolean isHidden(File f) + { + return new Boolean(filechooser.getFileSystemView().isHiddenFile(f)); + } + } + + /** + * DOCUMENT ME! + */ + protected class CancelSelectionAction extends AbstractAction + { + /** + * Creates a new CancelSelectionAction object. + */ + protected CancelSelectionAction() + { + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void actionPerformed(ActionEvent e) + { + filechooser.cancelSelection(); + closeDialog(); + } + } + + /** + * DOCUMENT ME! + */ + protected class ChangeToParentDirectoryAction extends AbstractAction + { + /** + * Creates a new ChangeToParentDirectoryAction object. + */ + protected ChangeToParentDirectoryAction() + { + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void actionPerformed(ActionEvent e) + { + filechooser.changeToParentDirectory(); + filechooser.revalidate(); + filechooser.repaint(); + } + } + + /** + * DOCUMENT ME! + */ + protected class DoubleClickListener extends MouseAdapter + { + /** DOCUMENT ME! */ + private Timer timer = null; + + /** DOCUMENT ME! */ + private Object lastSelected = null; + + /** DOCUMENT ME! */ + private JList list = null; + + /** + * Creates a new DoubleClickListener object. + * + * @param list DOCUMENT ME! + */ + public DoubleClickListener(JList list) + { + this.list = list; + timer = new Timer(1000, null); + timer.setRepeats(false); + lastSelected = list.getSelectedValue(); + setDirectorySelected(false); + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void mouseClicked(MouseEvent e) + { + if (list.getSelectedValue() == null) + return; + FileSystemView fsv = filechooser.getFileSystemView(); + if (timer.isRunning() + && list.getSelectedValue().toString().equals(lastSelected.toString())) + { + File f = fsv.createFileObject(lastSelected.toString()); + timer.stop(); + if (filechooser.isTraversable(f)) + { + filechooser.setCurrentDirectory(f); + filechooser.rescanCurrentDirectory(); + } + else + { + filechooser.setSelectedFile(f); + filechooser.approveSelection(); + closeDialog(); + } + } + else + { + File f = fsv.createFileObject(list.getSelectedValue().toString()); + if (filechooser.isTraversable(f)) + { + setDirectorySelected(true); + setDirectory(f); + } + else + { + setDirectorySelected(false); + setDirectory(null); + } + lastSelected = list.getSelectedValue().toString(); + timer.restart(); + } + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void mouseEntered(MouseEvent e) + { + // FIXME: Implement + } + } + + /** + * DOCUMENT ME! + */ + protected class GoHomeAction extends AbstractAction + { + /** + * Creates a new GoHomeAction object. + */ + protected GoHomeAction() + { + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void actionPerformed(ActionEvent e) + { + filechooser.setCurrentDirectory(filechooser.getFileSystemView() + .getHomeDirectory()); + filechooser.revalidate(); + filechooser.repaint(); + } + } + + /** + * DOCUMENT ME! + */ + protected class NewFolderAction extends AbstractAction + { + /** + * Creates a new NewFolderAction object. + */ + protected NewFolderAction() + { + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void actionPerformed(ActionEvent e) + { + try + { + filechooser.getFileSystemView().createNewFolder(filechooser + .getCurrentDirectory()); + } + catch (IOException ioe) + { + return; + } + filechooser.rescanCurrentDirectory(); + filechooser.repaint(); + } + } + + /** + * DOCUMENT ME! + */ + protected class SelectionListener implements ListSelectionListener + { + /** + * Creates a new SelectionListener object. + */ + protected SelectionListener() + { + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void valueChanged(ListSelectionEvent e) + { + Object f = filelist.getSelectedValue(); + if (f == null) + return; + File file = filechooser.getFileSystemView().createFileObject(f.toString()); + if (! filechooser.isTraversable(file)) + filechooser.setSelectedFile(file); + else + filechooser.setSelectedFile(null); + } + } + + /** + * DOCUMENT ME! + */ + protected class UpdateAction extends AbstractAction + { + /** + * Creates a new UpdateAction object. + */ + protected UpdateAction() + { + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void actionPerformed(ActionEvent e) + { + } + } + + /** DOCUMENT ME! */ + protected int cancelButtonMnemonic; + + /** DOCUMENT ME! */ + protected String cancelButtonText; + + /** DOCUMENT ME! */ + protected String cancelButtonToolTipText; + + /** DOCUMENT ME! */ + protected Icon computerIcon = new Icon() + { + public int getIconHeight() + { + return ICON_SIZE; + } + + public int getIconWidth() + { + return ICON_SIZE; + } + + public void paintIcon(Component c, Graphics g, int x, int y) + { + } + }; + + /** DOCUMENT ME! */ + protected Icon detailsViewIcon = new Icon() + { + public int getIconHeight() + { + return ICON_SIZE; + } + + public int getIconWidth() + { + return ICON_SIZE; + } + + public void paintIcon(Component c, Graphics g, int x, int y) + { + Color saved = g.getColor(); + g.translate(x, y); + + g.setColor(Color.GRAY); + g.drawRect(1, 1, 15, 20); + g.drawLine(17, 6, 23, 6); + g.drawLine(17, 12, 23, 12); + g.drawLine(17, 18, 23, 18); + + g.setColor(saved); + g.translate(-x, -y); + } + }; + + /** DOCUMENT ME! */ + protected Icon directoryIcon = new Icon() + { + public int getIconHeight() + { + return ICON_SIZE; + } + + public int getIconWidth() + { + return ICON_SIZE; + } + + public void paintIcon(Component c, Graphics g, int x, int y) + { + Color saved = g.getColor(); + g.translate(x, y); + + Point ap = new Point(3, 7); + Point bp = new Point(3, 21); + Point cp = new Point(21, 21); + Point dp = new Point(21, 12); + Point ep = new Point(16, 12); + Point fp = new Point(13, 7); + + Polygon dir = new Polygon(new int[] { ap.x, bp.x, cp.x, dp.x, ep.x, fp.x }, + new int[] { ap.y, bp.y, cp.y, dp.y, ep.y, fp.y }, + 6); + + g.setColor(new Color(153, 204, 255)); + g.fillPolygon(dir); + g.setColor(Color.BLACK); + g.drawPolygon(dir); + + g.translate(-x, -y); + g.setColor(saved); + } + }; + + /** DOCUMENT ME! */ + protected int directoryOpenButtonMnemonic; + + /** DOCUMENT ME! */ + protected String directoryOpenButtonText; + + /** DOCUMENT ME! */ + protected String directoryOpenButtonToolTipText; + + /** DOCUMENT ME! */ + protected Icon fileIcon = new Icon() + { + public int getIconHeight() + { + return ICON_SIZE; + } + + public int getIconWidth() + { + return ICON_SIZE; + } + + public void paintIcon(Component c, Graphics g, int x, int y) + { + Color saved = g.getColor(); + g.translate(x, y); + + Point a = new Point(5, 4); + Point b = new Point(5, 20); + Point d = new Point(19, 20); + Point e = new Point(19, 7); + Point f = new Point(16, 4); + + Polygon p = new Polygon(new int[] { a.x, b.x, d.x, e.x, f.x, }, + new int[] { a.y, b.y, d.y, e.y, f.y }, 5); + + g.setColor(Color.WHITE); + g.fillPolygon(p); + g.setColor(Color.BLACK); + g.drawPolygon(p); + + g.drawLine(16, 4, 14, 6); + g.drawLine(14, 6, 19, 7); + + g.setColor(saved); + g.translate(-x, -y); + } + }; + + /** DOCUMENT ME! */ + protected Icon floppyDriveIcon = new Icon() + { + public int getIconHeight() + { + return ICON_SIZE; + } + + public int getIconWidth() + { + return ICON_SIZE; + } + + public void paintIcon(Component c, Graphics g, int x, int y) + { + } + }; + + /** DOCUMENT ME! */ + protected Icon hardDriveIcon = new Icon() + { + public int getIconHeight() + { + return ICON_SIZE; + } + + public int getIconWidth() + { + return ICON_SIZE; + } + + public void paintIcon(Component c, Graphics g, int x, int y) + { + } + }; + + /** DOCUMENT ME! */ + protected int helpButtonMnemonic; + + /** DOCUMENT ME! */ + protected String helpButtonText; + + /** DOCUMENT ME! */ + protected String helpButtonToolTipText; + + /** DOCUMENT ME! */ + protected Icon homeFolderIcon = new Icon() + { + public int getIconHeight() + { + return ICON_SIZE; + } + + public int getIconWidth() + { + return ICON_SIZE; + } + + public void paintIcon(Component c, Graphics g, int x, int y) + { + Color saved = g.getColor(); + g.translate(x, y); + + Point a = new Point(12, 3); + Point b = new Point(4, 10); + Point d = new Point(20, 10); + + Polygon p = new Polygon(new int[] { a.x, b.x, d.x }, + new int[] { a.y, b.y, d.y }, 3); + + g.setColor(new Color(104, 51, 0)); + g.fillPolygon(p); + g.setColor(Color.BLACK); + g.drawPolygon(p); + + g.setColor(Color.WHITE); + g.fillRect(8, 10, 8, 10); + g.setColor(Color.BLACK); + g.drawRect(8, 10, 8, 10); + + g.setColor(saved); + g.translate(-x, -y); + } + }; + + /** DOCUMENT ME! */ + protected Icon listViewIcon = new Icon() + { + public int getIconHeight() + { + return ICON_SIZE; + } + + public int getIconWidth() + { + return ICON_SIZE; + } + + // Not needed. Only simplifies things until we get real icons. + private void paintPartial(Graphics g, int x, int y) + { + Color saved = g.getColor(); + g.translate(x, y); + + g.setColor(Color.GRAY); + g.drawRect(1, 1, 7, 10); + g.drawLine(8, 6, 11, 6); + + g.setColor(saved); + g.translate(-x, -y); + } + + public void paintIcon(Component c, Graphics g, int x, int y) + { + Color saved = g.getColor(); + g.translate(x, y); + + paintPartial(g, 0, 0); + paintPartial(g, 12, 0); + paintPartial(g, 0, 12); + paintPartial(g, 12, 12); + + g.setColor(saved); + g.translate(-x, -y); + } + }; + + /** DOCUMENT ME! */ + protected Icon newFolderIcon = directoryIcon; + + /** DOCUMENT ME! */ + protected int openButtonMnemonic; + + /** DOCUMENT ME! */ + protected String openButtonText; + + /** DOCUMENT ME! */ + protected String openButtonToolTipText; + + /** DOCUMENT ME! */ + protected int saveButtonMnemonic; + + /** DOCUMENT ME! */ + protected String saveButtonText; + + /** DOCUMENT ME! */ + protected String saveButtonToolTipText; + + /** DOCUMENT ME! */ + protected int updateButtonMnemonic; + + /** DOCUMENT ME! */ + protected String updateButtonText; + + /** DOCUMENT ME! */ + protected String updateButtonToolTipText; + + /** DOCUMENT ME! */ + protected Icon upFolderIcon = new Icon() + { + public int getIconHeight() + { + return ICON_SIZE; + } + + public int getIconWidth() + { + return ICON_SIZE; + } + + public void paintIcon(Component comp, Graphics g, int x, int y) + { + Color saved = g.getColor(); + g.translate(x, y); + + Point a = new Point(3, 7); + Point b = new Point(3, 21); + Point c = new Point(21, 21); + Point d = new Point(21, 12); + Point e = new Point(16, 12); + Point f = new Point(13, 7); + + Polygon dir = new Polygon(new int[] { a.x, b.x, c.x, d.x, e.x, f.x }, + new int[] { a.y, b.y, c.y, d.y, e.y, f.y }, 6); + + g.setColor(new Color(153, 204, 255)); + g.fillPolygon(dir); + g.setColor(Color.BLACK); + g.drawPolygon(dir); + + a = new Point(12, 15); + b = new Point(9, 18); + c = new Point(15, 18); + + Polygon arrow = new Polygon(new int[] { a.x, b.x, c.x }, + new int[] { a.y, b.y, c.y }, 3); + + g.fillPolygon(arrow); + + g.drawLine(12, 15, 12, 22); + + g.translate(-x, -y); + g.setColor(saved); + } + }; + + // -- begin private, but package local since used in inner classes -- + + JFileChooser filechooser; + + /** DOCUMENT ME! */ + JList filelist; + + /** DOCUMENT ME! */ + JComboBox filters; + + /** DOCUMENT ME! */ + BasicDirectoryModel model; + + /** DOCUMENT ME! */ + FileFilter acceptAll = new AcceptAllFileFilter(); + + /** DOCUMENT ME! */ + FileView fv = new BasicFileView(); + + /** DOCUMENT ME! */ + static final int ICON_SIZE = 24; + + /** DOCUMENT ME! */ + JComboBox parents; + + /** DOCUMENT ME! */ + String filename; + + /** DOCUMENT ME! */ + JButton accept; + + /** DOCUMENT ME! */ + JButton cancel; + + /** DOCUMENT ME! */ + JButton upFolderButton; + + /** DOCUMENT ME! */ + JButton newFolderButton; + + /** DOCUMENT ME! */ + JButton homeFolderButton; + + /** DOCUMENT ME! */ + JPanel accessoryPanel; + + /** DOCUMENT ME! */ + PropertyChangeListener propertyChangeListener; + + /** DOCUMENT ME! */ + String acceptAllFileFilterText; + + /** DOCUMENT ME! */ + String dirDescText; + + /** DOCUMENT ME! */ + String fileDescText; + + /** DOCUMENT ME! */ + boolean dirSelected = false; + + /** DOCUMENT ME! */ + File currDir = null; + + JPanel bottomPanel; + + /** DOCUMENT ME! */ + JPanel closePanel; + + // -- end private -- + private class ListLabelRenderer + extends JLabel + implements ListCellRenderer + { + /** DOCUMENT ME! */ + final Color selected = new Color(153, 204, 255); + + /** + * Creates a new ListLabelRenderer object. + */ + public ListLabelRenderer() + { + super(); + setOpaque(true); + } + + /** + * DOCUMENT ME! + * + * @param list DOCUMENT ME! + * @param value DOCUMENT ME! + * @param index DOCUMENT ME! + * @param isSelected DOCUMENT ME! + * @param cellHasFocus DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Component getListCellRendererComponent(JList list, Object value, + int index, + boolean isSelected, + boolean cellHasFocus) + { + setHorizontalAlignment(SwingConstants.LEFT); + File file = (File) value; + setText(filechooser.getName(file)); + setIcon(filechooser.getIcon(file)); + setBackground(isSelected ? selected : Color.WHITE); + setForeground(Color.BLACK); + + return this; + } + } + + /** + * DOCUMENT ME! + */ + public class CBLabelRenderer extends JLabel implements ListCellRenderer + { + /** + * Creates a new CBLabelRenderer object. + */ + public CBLabelRenderer() + { + super(); + setOpaque(true); + } + + /** + * DOCUMENT ME! + * + * @param list DOCUMENT ME! + * @param value DOCUMENT ME! + * @param index DOCUMENT ME! + * @param isSelected DOCUMENT ME! + * @param cellHasFocus DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Component getListCellRendererComponent(JList list, Object value, + int index, + boolean isSelected, + boolean cellHasFocus) + { + setHorizontalAlignment(SwingConstants.LEFT); + setIcon(directoryIcon); + setText(value.toString()); + setForeground(Color.BLACK); + setBackground(Color.WHITE); + + return this; + } + } + + void closeDialog() + { + Window owner = SwingUtilities.windowForComponent(filechooser); + if (owner instanceof JDialog) + ((JDialog) owner).dispose(); + } + + /** + * Creates a new BasicFileChooserUI object. + * + * @param b DOCUMENT ME! + */ + public BasicFileChooserUI(JFileChooser b) + { + this.filechooser = b; + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public static ComponentUI createUI(JComponent c) + { + return new BasicFileChooserUI((JFileChooser) c); + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + */ + public void installUI(JComponent c) + { + if (c instanceof JFileChooser) + { + JFileChooser fc = (JFileChooser) c; + fc.resetChoosableFileFilters(); + createModel(); + clearIconCache(); + installDefaults(fc); + installComponents(fc); + installListeners(fc); + } + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + */ + public void uninstallUI(JComponent c) + { + model = null; + uninstallListeners(filechooser); + uninstallComponents(filechooser); + uninstallDefaults(filechooser); + filechooser = null; + } + + // FIXME: Indent the entries in the combobox + private void boxEntries() + { + ArrayList parentFiles = new ArrayList(); + File parent = filechooser.getCurrentDirectory(); + if (parent == null) + parent = filechooser.getFileSystemView().getDefaultDirectory(); + while (parent != null) + { + String name = parent.getName(); + if (name.equals("")) + name = parent.getAbsolutePath(); + + parentFiles.add(parentFiles.size(), name); + parent = parent.getParentFile(); + } + + if (parentFiles.size() == 0) + return; + + if (parents.getItemCount() > 0) + parents.removeAllItems(); + for (int i = parentFiles.size() - 1; i >= 0; i--) + parents.addItem(parentFiles.get(i)); + parents.setSelectedIndex(parentFiles.size() - 1); + parents.revalidate(); + parents.repaint(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + private ItemListener createBoxListener() + { + return new ItemListener() + { + public void itemStateChanged(ItemEvent e) + { + if (parents.getItemCount() - 1 == parents.getSelectedIndex()) + return; + StringBuffer dir = new StringBuffer(); + for (int i = 0; i <= parents.getSelectedIndex(); i++) + { + dir.append(parents.getItemAt(i)); + dir.append(File.separatorChar); + } + filechooser.setCurrentDirectory(filechooser.getFileSystemView() + .createFileObject(dir + .toString())); + } + }; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + private ItemListener createFilterListener() + { + return new ItemListener() + { + public void itemStateChanged(ItemEvent e) + { + int index = filters.getSelectedIndex(); + if (index == -1) + return; + filechooser.setFileFilter(filechooser.getChoosableFileFilters()[index]); + } + }; + } + + void filterEntries() + { + FileFilter[] list = filechooser.getChoosableFileFilters(); + if (filters.getItemCount() > 0) + filters.removeAllItems(); + + int index = -1; + String selected = filechooser.getFileFilter().getDescription(); + for (int i = 0; i < list.length; i++) + { + if (selected.equals(list[i].getDescription())) + index = i; + filters.addItem(list[i].getDescription()); + } + filters.setSelectedIndex(index); + filters.revalidate(); + filters.repaint(); + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + */ + public void installComponents(JFileChooser fc) + { + JLabel look = new JLabel("Look In:"); + + parents = new JComboBox(); + parents.setRenderer(new CBLabelRenderer()); + boxEntries(); + look.setLabelFor(parents); + JPanel parentsPanel = new JPanel(); + parentsPanel.add(look); + parentsPanel.add(parents); + JPanel buttonPanel = new JPanel(); + + upFolderButton = new JButton(); + upFolderButton.setIcon(upFolderIcon); + buttonPanel.add(upFolderButton); + + homeFolderButton = new JButton(); + homeFolderButton = new JButton(homeFolderIcon); + buttonPanel.add(homeFolderButton); + + newFolderButton = new JButton(); + newFolderButton.setIcon(newFolderIcon); + buttonPanel.add(newFolderButton); + + ButtonGroup toggles = new ButtonGroup(); + JToggleButton listViewButton = new JToggleButton(); + listViewButton.setIcon(listViewIcon); + toggles.add(listViewButton); + buttonPanel.add(listViewButton); + + JToggleButton detailsViewButton = new JToggleButton(); + detailsViewButton.setIcon(detailsViewIcon); + toggles.add(detailsViewButton); + buttonPanel.add(detailsViewButton); + + JPanel topPanel = new JPanel(); + topPanel.setLayout(new java.awt.FlowLayout()); + topPanel.add(parentsPanel); + topPanel.add(buttonPanel); + + accessoryPanel = new JPanel(); + if (filechooser.getAccessory() != null) + accessoryPanel.add(filechooser.getAccessory(), BorderLayout.CENTER); + + filelist = new JList(model); + filelist.setVisibleRowCount(6); + JScrollPane scrollp = new JScrollPane(filelist); + scrollp.setPreferredSize(new Dimension(400, 175)); + filelist.setBackground(Color.WHITE); + + filelist.setLayoutOrientation(JList.VERTICAL_WRAP); + filelist.setCellRenderer(new ListLabelRenderer()); + + GridBagConstraints c = new GridBagConstraints(); + c.gridx = 0; + c.gridy = 0; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + c.weighty = 1; + + JPanel centrePanel = new JPanel(); + centrePanel.setLayout(new GridBagLayout()); + centrePanel.add(scrollp, c); + + c.gridx = 1; + centrePanel.add(accessoryPanel, c); + + JLabel fileNameLabel = new JLabel("File Name:"); + JLabel fileTypesLabel = new JLabel("Files of Type:"); + + JTextField entry = new JTextField(); + filters = new JComboBox(); + filterEntries(); + + fileNameLabel.setLabelFor(entry); + fileNameLabel.setHorizontalTextPosition(SwingConstants.LEFT); + fileTypesLabel.setLabelFor(filters); + fileTypesLabel.setHorizontalTextPosition(SwingConstants.LEFT); + + closePanel = new JPanel(); + accept = getApproveButton(filechooser); + cancel = new JButton(cancelButtonText); + cancel.setMnemonic(cancelButtonMnemonic); + cancel.setToolTipText(cancelButtonToolTipText); + closePanel.add(accept); + closePanel.add(cancel); + + c.anchor = GridBagConstraints.WEST; + c.weighty = 0; + c.weightx = 0; + c.gridx = 0; + + bottomPanel = new JPanel(); + bottomPanel.setLayout(new GridBagLayout()); + bottomPanel.add(fileNameLabel, c); + + c.gridy = 1; + bottomPanel.add(fileTypesLabel, c); + c.gridx = 1; + c.gridy = 0; + c.weightx = 1; + c.weighty = 1; + bottomPanel.add(entry, c); + + c.gridy = 1; + bottomPanel.add(filters, c); + + c.fill = GridBagConstraints.NONE; + c.gridy = 2; + c.anchor = GridBagConstraints.EAST; + bottomPanel.add(closePanel, c); + + filechooser.setLayout(new BorderLayout()); + filechooser.add(topPanel, BorderLayout.NORTH); + filechooser.add(centrePanel, BorderLayout.CENTER); + filechooser.add(bottomPanel, BorderLayout.SOUTH); + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + */ + public void uninstallComponents(JFileChooser fc) + { + parents = null; + + accept = null; + cancel = null; + upFolderButton = null; + homeFolderButton = null; + newFolderButton = null; + + filelist = null; + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + */ + protected void installListeners(JFileChooser fc) + { + propertyChangeListener = createPropertyChangeListener(filechooser); + filechooser.addPropertyChangeListener(propertyChangeListener); + + //parents.addItemListener(createBoxListener()); + accept.addActionListener(getApproveSelectionAction()); + cancel.addActionListener(getCancelSelectionAction()); + upFolderButton.addActionListener(getChangeToParentDirectoryAction()); + homeFolderButton.addActionListener(getGoHomeAction()); + newFolderButton.addActionListener(getNewFolderAction()); + filters.addItemListener(createFilterListener()); + + filelist.addMouseListener(createDoubleClickListener(filechooser, filelist)); + filelist.addListSelectionListener(createListSelectionListener(filechooser)); + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + */ + protected void uninstallListeners(JFileChooser fc) + { + filechooser.removePropertyChangeListener(propertyChangeListener); + propertyChangeListener = null; + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + */ + protected void installDefaults(JFileChooser fc) + { + installIcons(fc); + installStrings(fc); + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + */ + protected void uninstallDefaults(JFileChooser fc) + { + uninstallStrings(fc); + uninstallIcons(fc); + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + */ + protected void installIcons(JFileChooser fc) + { + // FIXME: Implement. + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + */ + protected void uninstallIcons(JFileChooser fc) + { + // FIXME: Implement. + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + */ + protected void installStrings(JFileChooser fc) + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + acceptAllFileFilterText = defaults.getString("FileChooser.acceptAllFileFilterText"); + cancelButtonMnemonic = defaults.getInt("FileChooser.cancelButtonMnemonic"); + cancelButtonText = defaults.getString("FileChooser.cancelButtonText"); + cancelButtonToolTipText = defaults.getString("FileChooser.cancelButtonToolTipText"); + + dirDescText = defaults.getString("FileChooser.directoryDescriptionText"); + fileDescText = defaults.getString("FileChooser.fileDescriptionText"); + + helpButtonMnemonic = defaults.getInt("FileChooser.helpButtonMnemonic"); + helpButtonText = defaults.getString("FileChooser.helpButtonText"); + helpButtonToolTipText = defaults.getString("FileChooser.helpButtonToolTipText"); + + openButtonMnemonic = defaults.getInt("FileChooser.openButtonMnemonic"); + openButtonText = defaults.getString("FileChooser.openButtonText"); + openButtonToolTipText = defaults.getString("FileChooser.openButtonToolTipText"); + + saveButtonMnemonic = defaults.getInt("FileChooser.saveButtonMnemonic"); + saveButtonText = defaults.getString("FileChooser.saveButtonText"); + saveButtonToolTipText = defaults.getString("FileChooser.saveButtonToolTipText"); + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + */ + protected void uninstallStrings(JFileChooser fc) + { + acceptAllFileFilterText = null; + cancelButtonMnemonic = 0; + cancelButtonText = null; + cancelButtonToolTipText = null; + + dirDescText = null; + fileDescText = null; + + helpButtonMnemonic = 0; + helpButtonText = null; + helpButtonToolTipText = null; + + openButtonMnemonic = 0; + openButtonText = null; + openButtonToolTipText = null; + + saveButtonMnemonic = 0; + saveButtonText = null; + saveButtonToolTipText = null; + } + + /** + * DOCUMENT ME! + */ + protected void createModel() + { + model = new BasicDirectoryModel(filechooser); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public BasicDirectoryModel getModel() + { + return model; + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public PropertyChangeListener createPropertyChangeListener(JFileChooser fc) + { + return new PropertyChangeListener() + { + public void propertyChange(PropertyChangeEvent e) + { + // FIXME: Multiple file selection waiting on JList multiple selection bug. + if (e.getPropertyName().equals(JFileChooser.SELECTED_FILE_CHANGED_PROPERTY)) + { + if (filechooser.getSelectedFile() == null) + setFileName(null); + else + setFileName(filechooser.getSelectedFile().toString()); + int index = -1; + File file = filechooser.getSelectedFile(); + for (index = 0; index < model.getSize(); index++) + if (((File) model.getElementAt(index)).equals(file)) + break; + if (index == -1) + return; + filelist.setSelectedIndex(index); + filelist.ensureIndexIsVisible(index); + filelist.revalidate(); + filelist.repaint(); + } + else if (e.getPropertyName().equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY)) + { + //boxEntries(); + filelist.clearSelection(); + filelist.revalidate(); + filelist.repaint(); + setDirectorySelected(false); + setDirectory(filechooser.getCurrentDirectory()); + } + else if (e.getPropertyName().equals(JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY) + || e.getPropertyName().equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY)) + filterEntries(); + else if (e.getPropertyName().equals(JFileChooser.DIALOG_TYPE_CHANGED_PROPERTY) + || e.getPropertyName().equals(JFileChooser.DIALOG_TITLE_CHANGED_PROPERTY)) + { + Window owner = SwingUtilities.windowForComponent(filechooser); + if (owner instanceof JDialog) + ((JDialog) owner).setTitle(getDialogTitle(filechooser)); + accept.setText(getApproveButtonText(filechooser)); + accept.setToolTipText(getApproveButtonToolTipText(filechooser)); + accept.setMnemonic(getApproveButtonMnemonic(filechooser)); + } + else if (e.getPropertyName().equals(JFileChooser.APPROVE_BUTTON_TEXT_CHANGED_PROPERTY)) + accept.setText(getApproveButtonText(filechooser)); + else if (e.getPropertyName().equals(JFileChooser.APPROVE_BUTTON_TOOL_TIP_TEXT_CHANGED_PROPERTY)) + accept.setToolTipText(getApproveButtonToolTipText(filechooser)); + else if (e.getPropertyName().equals(JFileChooser.APPROVE_BUTTON_MNEMONIC_CHANGED_PROPERTY)) + accept.setMnemonic(getApproveButtonMnemonic(filechooser)); + else if (e.getPropertyName().equals(JFileChooser.CONTROL_BUTTONS_ARE_SHOWN_CHANGED_PROPERTY)) + { + if (filechooser.getControlButtonsAreShown()) + { + GridBagConstraints c = new GridBagConstraints(); + c.gridy = 1; + bottomPanel.add(filters, c); + + c.fill = GridBagConstraints.BOTH; + c.gridy = 2; + c.anchor = GridBagConstraints.EAST; + bottomPanel.add(closePanel, c); + bottomPanel.revalidate(); + bottomPanel.repaint(); + bottomPanel.doLayout(); + } + else + bottomPanel.remove(closePanel); + } + else if (e.getPropertyName().equals(JFileChooser.ACCEPT_ALL_FILE_FILTER_USED_CHANGED_PROPERTY)) + { + if (filechooser.isAcceptAllFileFilterUsed()) + filechooser.addChoosableFileFilter(getAcceptAllFileFilter(filechooser)); + else + filechooser.removeChoosableFileFilter(getAcceptAllFileFilter(filechooser)); + } + else if (e.getPropertyName().equals(JFileChooser.ACCESSORY_CHANGED_PROPERTY)) + { + JComponent old = (JComponent) e.getOldValue(); + if (old != null) + getAccessoryPanel().remove(old); + JComponent newval = (JComponent) e.getNewValue(); + if (newval != null) + getAccessoryPanel().add(newval); + } + if (e.getPropertyName().equals(JFileChooser.DIRECTORY_CHANGED_PROPERTY) + || e.getPropertyName().equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY) + || e.getPropertyName().equals(JFileChooser.FILE_HIDING_CHANGED_PROPERTY)) + rescanCurrentDirectory(filechooser); + + filechooser.revalidate(); + filechooser.repaint(); + } + }; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getFileName() + { + return filename; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getDirectoryName() + { + // XXX: I don't see a case where the thing returns something non-null.. + return null; + } + + /** + * DOCUMENT ME! + * + * @param filename DOCUMENT ME! + */ + public void setFileName(String filename) + { + this.filename = filename; + } + + /** + * DOCUMENT ME! + * + * @param dirname DOCUMENT ME! + */ + public void setDirectoryName(String dirname) + { + // FIXME: Implement + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + */ + public void rescanCurrentDirectory(JFileChooser fc) + { + getModel().validateFileCache(); + filelist.revalidate(); + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + * @param f DOCUMENT ME! + */ + public void ensureFileIsVisible(JFileChooser fc, File f) + { + // XXX: Not sure what this does. + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public JFileChooser getFileChooser() + { + return filechooser; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public JPanel getAccessoryPanel() + { + return accessoryPanel; + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public JButton getApproveButton(JFileChooser fc) + { + accept = new JButton(getApproveButtonText(fc)); + accept.setMnemonic(getApproveButtonMnemonic(fc)); + accept.setToolTipText(getApproveButtonToolTipText(fc)); + return accept; + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getApproveButtonToolTipText(JFileChooser fc) + { + if (fc.getApproveButtonToolTipText() != null) + return fc.getApproveButtonToolTipText(); + else if (fc.getDialogType() == JFileChooser.SAVE_DIALOG) + return saveButtonToolTipText; + else + return openButtonToolTipText; + } + + /** + * DOCUMENT ME! + */ + public void clearIconCache() + { + if (fv instanceof BasicFileView) + ((BasicFileView) fv).clearIconCache(); + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public ListSelectionListener createListSelectionListener(JFileChooser fc) + { + return new SelectionListener(); + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + * @param list DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected MouseListener createDoubleClickListener(JFileChooser fc, JList list) + { + return new DoubleClickListener(list); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected boolean isDirectorySelected() + { + return dirSelected; + } + + /** + * DOCUMENT ME! + * + * @param selected DOCUMENT ME! + */ + protected void setDirectorySelected(boolean selected) + { + dirSelected = selected; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected File getDirectory() + { + return currDir; + } + + /** + * DOCUMENT ME! + * + * @param f DOCUMENT ME! + */ + protected void setDirectory(File f) + { + currDir = f; + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public FileFilter getAcceptAllFileFilter(JFileChooser fc) + { + return acceptAll; + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public FileView getFileView(JFileChooser fc) + { + if (fc.getFileView() != null) + return fc.getFileView(); + return fv; + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getDialogTitle(JFileChooser fc) + { + String ret = fc.getDialogTitle(); + if (ret != null) + return ret; + switch (fc.getDialogType()) + { + case JFileChooser.OPEN_DIALOG: + ret = openButtonText; + break; + case JFileChooser.SAVE_DIALOG: + ret = saveButtonText; + break; + default: + ret = fc.getApproveButtonText(); + break; + } + if (ret == null) + ret = openButtonText; + return ret; + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public int getApproveButtonMnemonic(JFileChooser fc) + { + if (fc.getApproveButtonMnemonic() != 0) + return fc.getApproveButtonMnemonic(); + else if (fc.getDialogType() == JFileChooser.SAVE_DIALOG) + return saveButtonMnemonic; + else + return openButtonMnemonic; + } + + /** + * DOCUMENT ME! + * + * @param fc DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public String getApproveButtonText(JFileChooser fc) + { + if (fc.getApproveButtonText() != null) + return fc.getApproveButtonText(); + else if (fc.getDialogType() == JFileChooser.SAVE_DIALOG) + return saveButtonText; + else + return openButtonText; + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Action getNewFolderAction() + { + return new NewFolderAction(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Action getGoHomeAction() + { + return new GoHomeAction(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Action getChangeToParentDirectoryAction() + { + return new ChangeToParentDirectoryAction(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Action getApproveSelectionAction() + { + return new ApproveSelectionAction(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Action getCancelSelectionAction() + { + return new CancelSelectionAction(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Action getUpdateAction() + { + return new UpdateAction(); + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicFormattedTextFieldUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicFormattedTextFieldUI.java new file mode 100644 index 0000000..3abd76f --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicFormattedTextFieldUI.java @@ -0,0 +1,62 @@ +/* BasicFormattedTextFieldUI.java + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; + +/** + * @since 1.4 + */ +public class BasicFormattedTextFieldUI extends BasicTextFieldUI +{ + public BasicFormattedTextFieldUI() + { + } + + public static ComponentUI createUI(JComponent c) + { + return new BasicFormattedTextFieldUI(); + } + + protected String getPropertyPrefix() + { + return "FormattedTextField"; + } +}
\ No newline at end of file diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicGraphicsUtils.java b/libjava/classpath/javax/swing/plaf/basic/BasicGraphicsUtils.java new file mode 100644 index 0000000..78ee62f --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicGraphicsUtils.java @@ -0,0 +1,641 @@ +/* BasicGraphicsUtils.java + Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.font.FontRenderContext; +import java.awt.font.LineMetrics; +import java.awt.font.TextLayout; +import java.awt.geom.Rectangle2D; + +import javax.swing.AbstractButton; +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.SwingUtilities; + + +/** + * A utility class providing commonly used drawing and measurement + * routines. + * + * @author Sascha Brawer (brawer@dandelis.ch) + */ +public class BasicGraphicsUtils +{ + /** + * Constructor. It is utterly unclear why this class should + * be constructable, but this is what the API specification + * says. + */ + public BasicGraphicsUtils() + { + } + + + /** + * Draws a rectangle that appears etched into the surface, given + * four colors that are used for drawing. + * + * <p><img src="doc-files/BasicGraphicsUtils-1.png" width="360" + * height="200" alt="[An illustration that shows which pixels + * get painted in what color]" /> + * + * @param g the graphics into which the rectangle is drawn. + * @param x the x coordinate of the rectangle. + * @param y the y coordinate of the rectangle. + * @param width the width of the rectangle in pixels. + * @param height the height of the rectangle in pixels. + * + * @param shadow the color that will be used for painting + * the outer side of the top and left edges. + * + * @param darkShadow the color that will be used for painting + * the inner side of the top and left edges. + * + * @param highlight the color that will be used for painting + * the inner side of the bottom and right edges. + * + * @param lightHighlight the color that will be used for painting + * the outer side of the bottom and right edges. + * + * @see #getEtchedInsets() + * @see javax.swing.border.EtchedBorder + */ + public static void drawEtchedRect(Graphics g, + int x, int y, int width, int height, + Color shadow, Color darkShadow, + Color highlight, Color lightHighlight) + { + Color oldColor; + int x2, y2; + + oldColor = g.getColor(); + x2 = x + width - 1; + y2 = y + height - 1; + + try + { + /* To understand this code, it might be helpful to look at the + * image "BasicGraphicsUtils-1.png" that is included with the + * JavaDoc. The file is located in the "doc-files" subdirectory. + * + * (x2, y2) is the coordinate of the most right and bottom pixel + * to be painted. + */ + g.setColor(shadow); + g.drawLine(x, y, x2 - 1, y); // top, outer + g.drawLine(x, y + 1, x, y2 - 1); // left, outer + + g.setColor(darkShadow); + g.drawLine(x + 1, y + 1, x2 - 2, y + 1); // top, inner + g.drawLine(x + 1, y + 2, x + 1, y2 - 2); // left, inner + + g.setColor(highlight); + g.drawLine(x + 1, y2 - 1, x2 - 1, y2 - 1); // bottom, inner + g.drawLine(x2 - 1, y + 1, x2 - 1, y2 - 2); // right, inner + + g.setColor(lightHighlight); + g.drawLine(x, y2, x2, y2); // bottom, outer + g.drawLine(x2, y, x2, y2 - 1); // right, outer + } + finally + { + g.setColor(oldColor); + } + } + + + /** + * Determines the width of the border that gets painted by + * {@link #drawEtchedRect}. + * + * @return an <code>Insets</code> object whose <code>top</code>, + * <code>left</code>, <code>bottom</code> and + * <code>right</code> field contain the border width at the + * respective edge in pixels. + */ + public static Insets getEtchedInsets() + { + return new Insets(2, 2, 2, 2); + } + + + /** + * Draws a rectangle that appears etched into the surface, given + * two colors that are used for drawing. + * + * <p><img src="doc-files/BasicGraphicsUtils-2.png" width="360" + * height="200" alt="[An illustration that shows which pixels + * get painted in what color]" /> + * + * @param g the graphics into which the rectangle is drawn. + * @param x the x coordinate of the rectangle. + * @param y the y coordinate of the rectangle. + * @param width the width of the rectangle in pixels. + * @param height the height of the rectangle in pixels. + * + * @param shadow the color that will be used for painting the outer + * side of the top and left edges, and for the inner side of + * the bottom and right ones. + * + * @param highlight the color that will be used for painting the + * inner side of the top and left edges, and for the outer + * side of the bottom and right ones. + * + * @see #getGrooveInsets() + * @see javax.swing.border.EtchedBorder + */ + public static void drawGroove(Graphics g, + int x, int y, int width, int height, + Color shadow, Color highlight) + { + /* To understand this, it might be helpful to look at the image + * "BasicGraphicsUtils-2.png" that is included with the JavaDoc, + * and to compare it with "BasicGraphicsUtils-1.png" which shows + * the pixels painted by drawEtchedRect. These image files are + * located in the "doc-files" subdirectory. + */ + drawEtchedRect(g, x, y, width, height, + /* outer topLeft */ shadow, + /* inner topLeft */ highlight, + /* inner bottomRight */ shadow, + /* outer bottomRight */ highlight); + } + + + /** + * Determines the width of the border that gets painted by + * {@link #drawGroove}. + * + * @return an <code>Insets</code> object whose <code>top</code>, + * <code>left</code>, <code>bottom</code> and + * <code>right</code> field contain the border width at the + * respective edge in pixels. + */ + public static Insets getGrooveInsets() + { + return new Insets(2, 2, 2, 2); + } + + + /** + * Draws a border that is suitable for buttons of the Basic look and + * feel. + * + * <p><img src="doc-files/BasicGraphicsUtils-3.png" width="500" + * height="300" alt="[An illustration that shows which pixels + * get painted in what color]" /> + * + * @param g the graphics into which the rectangle is drawn. + * @param x the x coordinate of the rectangle. + * @param y the y coordinate of the rectangle. + * @param width the width of the rectangle in pixels. + * @param height the height of the rectangle in pixels. + * + * @param isPressed <code>true</code> to draw the button border + * with a pressed-in appearance; <code>false</code> for + * normal (unpressed) appearance. + * + * @param isDefault <code>true</code> to draw the border with + * the appearance it has when hitting the enter key in a + * dialog will simulate a click to this button; + * <code>false</code> for normal appearance. + * + * @param shadow the shadow color. + * @param darkShadow a darker variant of the shadow color. + * @param highlight the highlight color. + * @param lightHighlight a brighter variant of the highlight color. + */ + public static void drawBezel(Graphics g, + int x, int y, int width, int height, + boolean isPressed, boolean isDefault, + Color shadow, Color darkShadow, + Color highlight, Color lightHighlight) + { + Color oldColor = g.getColor(); + + /* To understand this, it might be helpful to look at the image + * "BasicGraphicsUtils-3.png" that is included with the JavaDoc, + * and to compare it with "BasicGraphicsUtils-1.png" which shows + * the pixels painted by drawEtchedRect. These image files are + * located in the "doc-files" subdirectory. + */ + try + { + if ((isPressed == false) && (isDefault == false)) + { + drawEtchedRect(g, x, y, width, height, + lightHighlight, highlight, + shadow, darkShadow); + } + + if ((isPressed == true) && (isDefault == false)) + { + g.setColor(shadow); + g.drawRect(x + 1, y + 1, width - 2, height - 2); + } + + if ((isPressed == false) && (isDefault == true)) + { + g.setColor(darkShadow); + g.drawRect(x, y, width - 1, height - 1); + drawEtchedRect(g, x + 1, y + 1, width - 2, height - 2, + lightHighlight, highlight, + shadow, darkShadow); + } + + if ((isPressed == true) && (isDefault == true)) + { + g.setColor(darkShadow); + g.drawRect(x, y, width - 1, height - 1); + g.setColor(shadow); + g.drawRect(x + 1, y + 1, width - 3, height - 3); + } + } + finally + { + g.setColor(oldColor); + } + } + + + /** + * Draws a rectangle that appears lowered into the surface, given + * four colors that are used for drawing. + * + * <p><img src="doc-files/BasicGraphicsUtils-4.png" width="360" + * height="200" alt="[An illustration that shows which pixels + * get painted in what color]" /> + * + * <p><strong>Compatibility with the Sun reference + * implementation:</strong> The Sun reference implementation seems + * to ignore the <code>x</code> and <code>y</code> arguments, at + * least in JDK 1.3.1 and 1.4.1_01. The method always draws the + * rectangular area at location (0, 0). A bug report has been filed + * with Sun; its “bug ID” is 4880003. The GNU Classpath + * implementation behaves correctly, thus not replicating this bug. + * + * @param g the graphics into which the rectangle is drawn. + * @param x the x coordinate of the rectangle. + * @param y the y coordinate of the rectangle. + * @param width the width of the rectangle in pixels. + * @param height the height of the rectangle in pixels. + * + * @param shadow the color that will be used for painting + * the inner side of the top and left edges. + * + * @param darkShadow the color that will be used for painting + * the outer side of the top and left edges. + * + * @param highlight the color that will be used for painting + * the inner side of the bottom and right edges. + * + * @param lightHighlight the color that will be used for painting + * the outer side of the bottom and right edges. + */ + public static void drawLoweredBezel(Graphics g, + int x, int y, int width, int height, + Color shadow, Color darkShadow, + Color highlight, Color lightHighlight) + { + /* Like drawEtchedRect, but swapping darkShadow and shadow. + * + * To understand this, it might be helpful to look at the image + * "BasicGraphicsUtils-4.png" that is included with the JavaDoc, + * and to compare it with "BasicGraphicsUtils-1.png" which shows + * the pixels painted by drawEtchedRect. These image files are + * located in the "doc-files" subdirectory. + */ + drawEtchedRect(g, x, y, width, height, + darkShadow, shadow, + highlight, lightHighlight); + } + + + /** + * Draws a String at the given location, underlining the first + * occurence of a specified character. The algorithm for determining + * the underlined position is not sensitive to case. If the + * character is not part of <code>text</code>, the text will be + * drawn without underlining. Drawing is performed in the current + * color and font of <code>g</code>. + * + * <p><img src="doc-files/BasicGraphicsUtils-5.png" width="500" + * height="100" alt="[An illustration showing how to use the + * method]" /> + * + * @param g the graphics into which the String is drawn. + * + * @param text the String to draw. + * + * @param underlinedChar the character whose first occurence in + * <code>text</code> will be underlined. It is not clear + * why the API specification declares this argument to be + * of type <code>int</code> instead of <code>char</code>. + * While this would allow to pass Unicode characters outside + * Basic Multilingual Plane 0 (U+0000 .. U+FFFE), at least + * the GNU Classpath implementation does not underline + * anything if <code>underlinedChar</code> is outside + * the range of <code>char</code>. + * + * @param x the x coordinate of the text, as it would be passed to + * {@link java.awt.Graphics#drawString(java.lang.String, + * int, int)}. + * + * @param y the y coordinate of the text, as it would be passed to + * {@link java.awt.Graphics#drawString(java.lang.String, + * int, int)}. + */ + public static void drawString(Graphics g, String text, + int underlinedChar, int x, int y) + { + int index = -1; + + /* It is intentional that lower case is used. In some languages, + * the set of lowercase characters is larger than the set of + * uppercase ones. Therefore, it is good practice to use lowercase + * for such comparisons (which really means that the author of this + * code can vaguely remember having read some Unicode techreport + * with this recommendation, but is too lazy to look for the URL). + */ + if ((underlinedChar >= 0) || (underlinedChar <= 0xffff)) + index = text.toLowerCase().indexOf( + Character.toLowerCase((char) underlinedChar)); + + drawStringUnderlineCharAt(g, text, index, x, y); + } + + + /** + * Draws a String at the given location, underlining the character + * at the specified index. Drawing is performed in the current color + * and font of <code>g</code>. + * + * <p><img src="doc-files/BasicGraphicsUtils-5.png" width="500" + * height="100" alt="[An illustration showing how to use the + * method]" /> + * + * @param g the graphics into which the String is drawn. + * + * @param text the String to draw. + * + * @param underlinedIndex the index of the underlined character in + * <code>text</code>. If <code>underlinedIndex</code> falls + * outside the range <code>[0, text.length() - 1]</code>, the + * text will be drawn without underlining anything. + * + * @param x the x coordinate of the text, as it would be passed to + * {@link java.awt.Graphics#drawString(java.lang.String, + * int, int)}. + * + * @param y the y coordinate of the text, as it would be passed to + * {@link java.awt.Graphics#drawString(java.lang.String, + * int, int)}. + * + * @since 1.4 + */ + public static void drawStringUnderlineCharAt(Graphics g, String text, + int underlinedIndex, + int x, int y) + { + Graphics2D g2; + Rectangle2D.Double underline; + FontRenderContext frc; + FontMetrics fmet; + LineMetrics lineMetrics; + Font font; + TextLayout layout; + double underlineX1, underlineX2; + boolean drawUnderline; + int textLength; + + textLength = text.length(); + if (textLength == 0) + return; + + drawUnderline = (underlinedIndex >= 0) && (underlinedIndex < textLength); + + // FIXME: unfortunately pango and cairo can't agree on metrics + // so for the time being we continue to *not* use TextLayouts. + if (true || !(g instanceof Graphics2D)) + { + /* Fall-back. This is likely to produce garbage for any text + * containing right-to-left (Hebrew or Arabic) characters, even + * if the underlined character is left-to-right. + */ + g.drawString(text, x, y); + if (drawUnderline) + { + fmet = g.getFontMetrics(); + g.fillRect( + /* x */ x + fmet.stringWidth(text.substring(0, underlinedIndex)), + /* y */ y + fmet.getDescent() - 1, + /* width */ fmet.charWidth(text.charAt(underlinedIndex)), + /* height */ 1); + } + + return; + } + + g2 = (Graphics2D) g; + font = g2.getFont(); + frc = g2.getFontRenderContext(); + lineMetrics = font.getLineMetrics(text, frc); + layout = new TextLayout(text, font, frc); + + /* Draw the text. */ + layout.draw(g2, x, y); + if (!drawUnderline) + return; + + underlineX1 = x + layout.getLogicalHighlightShape( + underlinedIndex, underlinedIndex).getBounds2D().getX(); + underlineX2 = x + layout.getLogicalHighlightShape( + underlinedIndex + 1, underlinedIndex + 1).getBounds2D().getX(); + + underline = new Rectangle2D.Double(); + if (underlineX1 < underlineX2) + { + underline.x = underlineX1; + underline.width = underlineX2 - underlineX1; + } + else + { + underline.x = underlineX2; + underline.width = underlineX1 - underlineX2; + } + + + underline.height = lineMetrics.getUnderlineThickness(); + underline.y = lineMetrics.getUnderlineOffset(); + if (underline.y == 0) + { + /* Some fonts do not specify an underline offset, although they + * actually should do so. In that case, the result of calling + * lineMetrics.getUnderlineOffset() will be zero. Since it would + * look very ugly if the underline was be positioned immediately + * below the baseline, we check for this and move the underline + * below the descent, as shown in the following ASCII picture: + * + * ##### ##### # + * # # # # + * # # # # + * # # # # + * ##### ###### ---- baseline (0) + * # + * # + * ------------------###----------- lineMetrics.getDescent() + */ + underline.y = lineMetrics.getDescent(); + } + + underline.y += y; + g2.fill(underline); + } + + + /** + * Draws a rectangle, simulating a dotted stroke by painting only + * every second pixel along the one-pixel thick edge. The color of + * those pixels is the current color of the Graphics <code>g</code>. + * Any other pixels are left unchanged. + * + * <p><img src="doc-files/BasicGraphicsUtils-7.png" width="360" + * height="200" alt="[An illustration that shows which pixels + * get painted]" /> + * + * @param g the graphics into which the rectangle is drawn. + * @param x the x coordinate of the rectangle. + * @param y the y coordinate of the rectangle. + * @param width the width of the rectangle in pixels. + * @param height the height of the rectangle in pixels. + */ + public static void drawDashedRect(Graphics g, + int x, int y, int width, int height) + { + int right = x + width - 1; + int bottom = y + height - 1; + + /* Draw the top and bottom edge of the dotted rectangle. */ + for (int i = x; i <= right; i += 2) + { + g.drawLine(i, y, i, y); + g.drawLine(i, bottom, i, bottom); + } + + /* Draw the left and right edge of the dotted rectangle. */ + for (int i = y; i <= bottom; i += 2) + { + g.drawLine(x, i, x, i); + g.drawLine(right, i, right, i); + } + } + + + /** + * Determines the preferred width and height of an AbstractButton, + * given the gap between the button’s text and icon. + * + * @param b the button whose preferred size is determined. + * + * @param textIconGap the gap between the button’s text and + * icon. + * + * @return a <code>Dimension</code> object whose <code>width</code> + * and <code>height</code> fields indicate the preferred + * extent in pixels. + * + * @see javax.swing.SwingUtilities#layoutCompoundLabel(JComponent, + * FontMetrics, String, Icon, int, int, int, int, Rectangle, Rectangle, + * Rectangle, int) + */ + public static Dimension getPreferredButtonSize(AbstractButton b, + int textIconGap) + { + Rectangle contentRect; + Rectangle viewRect; + Rectangle iconRect = new Rectangle(); + Rectangle textRect = new Rectangle(); + Insets insets = b.getInsets(); + + viewRect = new Rectangle(); + + /* java.awt.Toolkit.getFontMetrics is deprecated. However, it + * seems not obvious how to get to the correct FontMetrics object + * otherwise. The real problem probably is that the method + * javax.swing.SwingUtilities.layoutCompundLabel should take a + * LineMetrics, not a FontMetrics argument. But fixing this that + * would change the public API. + */ + SwingUtilities.layoutCompoundLabel( + b, // for the component orientation + b.getToolkit().getFontMetrics(b.getFont()), // see comment above + b.getText(), + b.getIcon(), + b.getVerticalAlignment(), + b.getHorizontalAlignment(), + b.getVerticalTextPosition(), + b.getHorizontalTextPosition(), + viewRect, iconRect, textRect, + textIconGap); + + /* +------------------------+ +------------------------+ + * | | | | + * | ICON | | CONTENTCONTENTCONTENT | + * | TEXTTEXTTEXT | --> | CONTENTCONTENTCONTENT | + * | TEXTTEXTTEXT | | CONTENTCONTENTCONTENT | + * +------------------------+ +------------------------+ + */ + + contentRect = textRect.union(iconRect); + + return new Dimension(insets.left + + contentRect.width + + insets.right, + insets.top + + contentRect.height + + insets.bottom); + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicIconFactory.java b/libjava/classpath/javax/swing/plaf/basic/BasicIconFactory.java new file mode 100644 index 0000000..e7aad89 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicIconFactory.java @@ -0,0 +1,238 @@ +/* BasicIconFactory.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Polygon; +import java.io.Serializable; + +import javax.swing.AbstractButton; +import javax.swing.Icon; +import javax.swing.UIDefaults; +import javax.swing.UIManager; + +/** + * STUBBED + */ +public class BasicIconFactory implements Serializable +{ + static final long serialVersionUID = 5605588811185324383L; + + private static class DummyIcon + implements Icon + { + public int getIconHeight() { return 10; } + public int getIconWidth() { return 10; } + public void paintIcon(Component c, Graphics g, int x, int y) + { + Color save = g.getColor(); + g.setColor(c.getForeground()); + g.drawRect(x, y, 10, 10); + g.setColor(save); + } + } + + + public BasicIconFactory() + { + } + public static Icon getMenuItemCheckIcon() + { + return new DummyIcon(); + } + public static Icon getMenuItemArrowIcon() + { + return new DummyIcon(); + } + public static Icon getMenuArrowIcon() + { + return new Icon() + { + public int getIconHeight() + { + return 12; + } + + public int getIconWidth() + { + return 12; + } + + public void paintIcon(Component c, Graphics g, int x, int y) + { + g.translate(x, y); + + Color saved = g.getColor(); + + g.setColor(Color.BLACK); + + g.fillPolygon(new Polygon(new int[] { 3, 9, 3 }, + new int[] { 2, 6, 10 }, + 3)); + + g.setColor(saved); + g.translate(-x, -y); + } + }; + } + + public static Icon getCheckBoxIcon() + { + return new Icon() + { + public int getIconHeight() + { + return 10; + } + public int getIconWidth() + { + return 10; + } + public void paintIcon(Component c, Graphics g, int x, int y) + { + if (c instanceof AbstractButton) + { + UIDefaults defaults; + defaults = UIManager.getLookAndFeelDefaults(); + Color hi = defaults.getColor("CheckBox.highlight"); + Color low = defaults.getColor("CheckBox.darkShadow"); + Color sel = defaults.getColor("CheckBox.foreground"); + Color dim = defaults.getColor("CheckBox.shadow"); + Polygon check = new Polygon(new int[] {x+3, x+3, x+8}, + new int[] {y+5, y+9, y+3}, 3); + AbstractButton b = (AbstractButton) c; + Color saved = g.getColor(); + if (b.isEnabled()) + { + g.setColor(low); + g.drawRect(x, y, 10, 10); + g.setColor(hi); + g.drawRect(x+1, y+1, 10, 10); + if (b.isSelected()) + { + g.setColor(sel); + if (b.isSelected()) + { + g.drawLine(x+3, y+5, x+3, y+8); + g.drawLine(x+4, y+5, x+4, y+8); + g.drawLine(x+3, y+8, x+8, y+3); + g.drawLine(x+4, y+8, x+8, y+3); + } + } + } + else + { + g.setColor(hi); + g.drawRect(x, y, 10, 10); + if (b.isSelected()) + { + g.drawLine(x+3, y+5, x+3, y+9); + g.drawLine(x+3, y+9, x+8, y+3); + } + } + g.setColor(saved); + } + } + }; + } + + public static Icon getRadioButtonIcon() + { + return new Icon() + { + public int getIconHeight() + { + return 12; + } + public int getIconWidth() + { + return 12; + } + public void paintIcon(Component c, Graphics g, int x, int y) + { + UIDefaults defaults; + defaults = UIManager.getLookAndFeelDefaults(); + Color hi = defaults.getColor("RadioButton.highlight"); + Color low = defaults.getColor("RadioButton.darkShadow"); + Color sel = defaults.getColor("RadioButton.foreground"); + Color dim = defaults.getColor("RadioButton.shadow"); + + if (c instanceof AbstractButton) + { + AbstractButton b = (AbstractButton) c; + Color saved = g.getColor(); + if (b.isEnabled()) + { + g.setColor(low); + g.drawOval(x, y, 12, 12); + g.setColor(hi); + g.drawOval(x+1, y+1, 12, 12); + if (b.isSelected()) + { + g.setColor(sel); + g.fillOval(x+4, y+4, 6, 6); + } + } + else + { + g.setColor(hi); + g.drawOval(x, y, 12, 12); + if (b.isSelected()) + g.fillOval(x+4, y+4, 6, 6); + } + g.setColor(saved); + } + } + }; + } + public static Icon getCheckBoxMenuItemIcon() + { + return getCheckBoxIcon(); + } + public static Icon getRadioButtonMenuItemIcon() + { + return getRadioButtonIcon(); + } + public static Icon createEmptyFrameIcon() + { + return new DummyIcon(); + } +} // class BasicIconFactory diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameTitlePane.java b/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameTitlePane.java new file mode 100644 index 0000000..91db0cb --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameTitlePane.java @@ -0,0 +1,940 @@ +/* BasicInternalFrameTitlePane.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.LayoutManager; +import java.awt.Polygon; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyVetoException; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JInternalFrame; +import javax.swing.JLabel; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.UIDefaults; +import javax.swing.UIManager; + +/** + * This class acts as a titlebar for JInternalFrames. + */ +public class BasicInternalFrameTitlePane extends JComponent +{ + /** + * The Action responsible for closing the JInternalFrame. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class CloseAction extends AbstractAction + { + /** + * This method is called when something closes the JInternalFrame. + * + * @param e The ActionEvent. + */ + public void actionPerformed(ActionEvent e) + { + if (frame.isClosable()) + { + try + { + frame.setClosed(true); + } + catch (PropertyVetoException pve) + { + } + } + } + } + + /** + * This Action is responsible for iconifying the JInternalFrame. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class IconifyAction extends AbstractAction + { + /** + * This method is called when the user wants to iconify the + * JInternalFrame. + * + * @param e The ActionEvent. + */ + public void actionPerformed(ActionEvent e) + { + if (frame.isIconifiable() && ! frame.isIcon()) + { + try + { + frame.setIcon(true); + } + catch (PropertyVetoException pve) + { + } + } + } + } + + /** + * This Action is responsible for maximizing the JInternalFrame. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class MaximizeAction extends AbstractAction + { + /** + * This method is called when the user wants to maximize the + * JInternalFrame. + * + * @param e The ActionEvent. + */ + public void actionPerformed(ActionEvent e) + { + try + { + if (frame.isMaximizable() && ! frame.isMaximum()) + frame.setMaximum(true); + else if (frame.isMaximum()) + frame.setMaximum(false); + } + catch (PropertyVetoException pve) + { + } + } + } + + /** + * This Action is responsible for dragging the JInternalFrame. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class MoveAction extends AbstractAction + { + /** + * This method is called when the user wants to drag the JInternalFrame. + * + * @param e The ActionEvent. + */ + public void actionPerformed(ActionEvent e) + { + // FIXME: Implement keyboard driven? move actions. + } + } + + /** + * This Action is responsible for restoring the JInternalFrame. Restoring + * the JInternalFrame is the same as setting the maximum property to false. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class RestoreAction extends AbstractAction + { + /** + * This method is called when the user wants to restore the + * JInternalFrame. + * + * @param e The ActionEvent. + */ + public void actionPerformed(ActionEvent e) + { + if (frame.isMaximum()) + { + try + { + frame.setMaximum(false); + } + catch (PropertyVetoException pve) + { + } + } + } + } + + /** + * This action is responsible for sizing the JInternalFrame. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class SizeAction extends AbstractAction + { + /** + * This method is called when the user wants to resize the JInternalFrame. + * + * @param e The ActionEvent. + */ + public void actionPerformed(ActionEvent e) + { + // FIXME: Not sure how size actions should be handled. + } + } + + /** + * This class is responsible for handling property change events from the + * JInternalFrame and adjusting the Title Pane as necessary. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class PropertyChangeHandler implements PropertyChangeListener + { + /** + * This method is called when a PropertyChangeEvent is received by the + * Title Pane. + * + * @param evt The PropertyChangeEvent. + */ + public void propertyChange(PropertyChangeEvent evt) + { + String propName = evt.getPropertyName(); + if (propName.equals("closable")) + { + if (evt.getNewValue().equals(Boolean.TRUE)) + closeButton.setVisible(true); + else + closeButton.setVisible(false); + } + else if (propName.equals("iconifiable")) + { + if (evt.getNewValue().equals(Boolean.TRUE)) + iconButton.setVisible(true); + else + iconButton.setVisible(false); + } + else if (propName.equals("maximizable")) + { + if (evt.getNewValue().equals(Boolean.TRUE)) + maxButton.setVisible(true); + else + maxButton.setVisible(false); + } + + } + } + + /** + * This class acts as the MenuBar for the TitlePane. Clicking on the Frame + * Icon in the top left corner will activate it. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class SystemMenuBar extends JMenuBar + { + /** + * This method returns true if it can receive focus. + * + * @return True if this Component can receive focus. + */ + public boolean isFocusTransversable() + { + return true; + } + + /** + * This method returns true if this Component is expected to paint all of + * itself. + * + * @return True if this Component is expect to paint all of itself. + */ + public boolean isOpaque() + { + return true; + } + + /** + * This method paints this Component. + * + * @param g The Graphics object to paint with. + */ + public void paint(Graphics g) + { + Icon frameIcon = frame.getFrameIcon(); + if (frameIcon == null) + frameIcon = BasicDesktopIconUI.defaultIcon; + frameIcon.paintIcon(this, g, 0, 0); + } + + /** + * This method requests that focus be given to this Component. + */ + public void requestFocus() + { + super.requestFocus(); + } + } + + /** + * This class acts as the Layout Manager for the TitlePane. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class TitlePaneLayout implements LayoutManager + { + /** + * Creates a new <code>TitlePaneLayout</code> object. + */ + public TitlePaneLayout() + { + // Do nothing. + } + + /** + * This method is called when adding a Component to the Container. + * + * @param name The name to reference the added Component by. + * @param c The Component to add. + */ + public void addLayoutComponent(String name, Component c) + { + // Do nothing. + } + + /** + * This method is called to lay out the children of the Title Pane. + * + * @param c The Container to lay out. + */ + public void layoutContainer(Container c) + { + Dimension size = c.getSize(); + Insets insets = c.getInsets(); + int width = size.width - insets.left - insets.right; + int height = size.height - insets.top - insets.bottom; + + // MenuBar is always present and located at the top left corner. + Dimension menupref = menuBar.getPreferredSize(); + menuBar.setBounds(insets.left, insets.top, menupref.width, height); + + int loc = width + insets.left - 1; + int top = insets.top + 1; + int buttonWidth = height - 2; + int buttonHeight = height - 4; + if (closeButton.isVisible()) + { + loc -= buttonWidth + 2; + closeButton.setBounds(loc, top, buttonWidth, buttonHeight); + } + + if (maxButton.isVisible()) + { + loc -= buttonWidth + 2; + maxButton.setBounds(loc, top, buttonWidth, buttonHeight); + } + + if (iconButton.isVisible()) + { + loc -= buttonWidth + 2; + iconButton.setBounds(loc, top, buttonWidth, buttonHeight); + } + + if (title != null) + title.setBounds(insets.left + menupref.width, insets.top, + loc - menupref.width - insets.left, height); + } + + /** + * This method returns the minimum size of the given Container given the + * children that it has. + * + * @param c The Container to get a minimum size for. + * + * @return The minimum size of the Container. + */ + public Dimension minimumLayoutSize(Container c) + { + return preferredLayoutSize(c); + } + + /** + * This method returns the preferred size of the given Container taking + * into account the children that it has. + * + * @param c The Container to lay out. + * + * @return The preferred size of the Container. + */ + public Dimension preferredLayoutSize(Container c) + { + return new Dimension(22, 18); + } + + /** + * This method is called when removing a Component from the Container. + * + * @param c The Component to remove. + */ + public void removeLayoutComponent(Component c) + { + } + } + + /** + * This helper class is used to create the minimize, maximize and close + * buttons in the top right corner of the Title Pane. These buttons are + * special since they cannot be given focus and have no border. + */ + private class PaneButton extends JButton + { + /** + * Creates a new PaneButton object with the given Action. + * + * @param a The Action that the button uses. + */ + public PaneButton(Action a) + { + super(a); + setMargin(new Insets(0, 0, 0, 0)); + } + + /** + * This method returns true if the Component can be focused. + * + * @return false. + */ + public boolean isFocusable() + { + // These buttons cannot be given focus. + return false; + } + } + + /** The action command for the Close action. */ + protected static final String CLOSE_CMD = "Close"; + + /** The action command for the Minimize action. */ + protected static final String ICONIFY_CMD = "Minimize"; + + /** The action command for the Maximize action. */ + protected static final String MAXIMIZE_CMD = "Maximize"; + + /** The action command for the Move action. */ + protected static final String MOVE_CMD = "Move"; + + /** The action command for the Restore action. */ + protected static final String RESTORE_CMD = "Restore"; + + /** The action command for the Size action. */ + protected static final String SIZE_CMD = "Size"; + + /** The action associated with closing the JInternalFrame. */ + protected Action closeAction; + + /** The action associated with iconifying the JInternalFrame. */ + protected Action iconifyAction; + + /** The action associated with maximizing the JInternalFrame. */ + protected Action maximizeAction; + + /** The action associated with moving the JInternalFrame. */ + protected Action moveAction; + + /** The action associated with restoring the JInternalFrame. */ + protected Action restoreAction; + + /** The action associated with resizing the JInternalFrame. */ + protected Action sizeAction; + + /** The button that closes the JInternalFrame. */ + protected JButton closeButton; + + /** The button that iconifies the JInternalFrame. */ + protected JButton iconButton; + + /** The button that maximizes the JInternalFrame. */ + protected JButton maxButton; + + /** Active background color. */ + protected Color activeBGColor; + + /** Active foreground color. */ + protected Color activeFGColor; + + /** Inactive background color. */ + protected Color inactiveBGColor; + + /** Inactive foreground color. */ + protected Color inactiveFGColor; + + /** The icon displayed in the restore button. */ + protected Icon minIcon = BasicIconFactory.createEmptyFrameIcon(); + + /** The icon displayed in the maximize button. */ + protected Icon maxIcon = BasicIconFactory.createEmptyFrameIcon(); + + /** The icon displayed in the iconify button. */ + protected Icon iconIcon = BasicIconFactory.createEmptyFrameIcon(); + + /** The JInternalFrame that this TitlePane is used in. */ + protected JInternalFrame frame; + + /** The JMenuBar that is located at the top left of the Title Pane. */ + protected JMenuBar menuBar; + + /** The JMenu inside the menuBar. */ + protected JMenu windowMenu; + + /** + * The text color of the TitlePane when the JInternalFrame is not selected. + */ + protected Color notSelectedTextColor; + + /** + * The background color of the TitlePane when the JInternalFrame is not + * selected. + */ + protected Color notSelectedTitleColor; + + /** The text color of the titlePane when the JInternalFrame is selected. */ + protected Color selectedTextColor; + + /** + * The background color of the TitlePane when the JInternalFrame is + * selected. + */ + protected Color selectedTitleColor; + + /** The Property Change listener that listens to the JInternalFrame. */ + protected PropertyChangeListener propertyChangeListener; + + /** + * The label used to display the title. This label is not added to the + * TitlePane. + * This is package-private to avoid an accessor method. + */ + transient JLabel title; + + /** + * Creates a new BasicInternalFrameTitlePane object that is used in the + * given JInternalFrame. + * + * @param f The JInternalFrame this BasicInternalFrameTitlePane will be used + * in. + */ + public BasicInternalFrameTitlePane(JInternalFrame f) + { + frame = f; + setLayout(createLayout()); + title = new JLabel(); + title.setHorizontalAlignment(SwingConstants.LEFT); + title.setHorizontalTextPosition(SwingConstants.LEFT); + title.setOpaque(false); + setOpaque(true); + + setBackground(Color.LIGHT_GRAY); + + installTitlePane(); + } + + /** + * This method installs the TitlePane onto the JInternalFrameTitlePane. It + * also creates any children components that need to be created and adds + * listeners to the appropriate components. + */ + protected void installTitlePane() + { + installDefaults(); + installListeners(); + createActions(); + + assembleSystemMenu(); + + createButtons(); + setButtonIcons(); + addSubComponents(); + enableActions(); + } + + /** + * This method adds the sub components to the TitlePane. + */ + protected void addSubComponents() + { + add(menuBar); + + add(closeButton); + add(iconButton); + add(maxButton); + } + + /** + * This method creates the actions that are used to manipulate the + * JInternalFrame. + */ + protected void createActions() + { + closeAction = new CloseAction(); + closeAction.putValue(AbstractAction.ACTION_COMMAND_KEY, CLOSE_CMD); + + iconifyAction = new IconifyAction(); + iconifyAction.putValue(AbstractAction.ACTION_COMMAND_KEY, ICONIFY_CMD); + + maximizeAction = new MaximizeAction(); + maximizeAction.putValue(AbstractAction.ACTION_COMMAND_KEY, MAXIMIZE_CMD); + + sizeAction = new SizeAction(); + sizeAction.putValue(AbstractAction.ACTION_COMMAND_KEY, SIZE_CMD); + + restoreAction = new RestoreAction(); + restoreAction.putValue(AbstractAction.ACTION_COMMAND_KEY, RESTORE_CMD); + + moveAction = new MoveAction(); + moveAction.putValue(AbstractAction.ACTION_COMMAND_KEY, MOVE_CMD); + } + + /** + * This method is used to install the listeners. + */ + protected void installListeners() + { + propertyChangeListener = new PropertyChangeHandler(); + frame.addPropertyChangeListener(propertyChangeListener); + } + + /** + * This method is used to uninstall the listeners. + */ + protected void uninstallListeners() + { + frame.removePropertyChangeListener(propertyChangeListener); + propertyChangeListener = null; + } + + /** + * This method installs the defaults determined by the look and feel. + */ + protected void installDefaults() + { + // FIXME: move icons to defaults. + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + setFont(defaults.getFont("InternalFrame.titleFont")); + activeFGColor = defaults.getColor("InternalFrame.activeTitleForeground"); + activeBGColor = defaults.getColor("InternalFrame.activeTitleBackground"); + inactiveFGColor = defaults.getColor("InternalFrame.inactiveTitleForeground"); + inactiveBGColor = defaults.getColor("InternalFrame.inactiveTitleBackground"); + } + + /** + * This method uninstalls the defaults. + */ + protected void uninstallDefaults() + { + setFont(null); + activeFGColor = null; + activeBGColor = null; + inactiveFGColor = null; + inactiveBGColor = null; + } + + /** + * This method creates the buttons used in the TitlePane. + */ + protected void createButtons() + { + closeButton = new PaneButton(closeAction); + if (!frame.isClosable()) + closeButton.setVisible(false); + iconButton = new PaneButton(iconifyAction); + if (!frame.isIconifiable()) + iconButton.setVisible(false); + maxButton = new PaneButton(maximizeAction); + if (!frame.isMaximizable()) + maxButton.setVisible(false); + } + + /** + * This method sets the icons in the buttons. This is a no-op method here, it + * can be overridden by subclasses to set icons for the minimize-, maximize- + * and close-buttons. + */ + protected void setButtonIcons() + { + } + + /** + * This method creates the MenuBar used in the TitlePane. + */ + protected void assembleSystemMenu() + { + menuBar = createSystemMenuBar(); + windowMenu = createSystemMenu(); + + menuBar.add(windowMenu); + + addSystemMenuItems(windowMenu); + enableActions(); + } + + /** + * This method adds the MenuItems to the given JMenu. + * + * @param systemMenu The JMenu to add MenuItems to. + */ + protected void addSystemMenuItems(JMenu systemMenu) + { + JMenuItem tmp; + + tmp = new JMenuItem(RESTORE_CMD); + tmp.addActionListener(restoreAction); + tmp.setMnemonic(KeyEvent.VK_R); + systemMenu.add(tmp); + + tmp = new JMenuItem(MOVE_CMD); + tmp.addActionListener(moveAction); + tmp.setMnemonic(KeyEvent.VK_M); + systemMenu.add(tmp); + + tmp = new JMenuItem(SIZE_CMD); + tmp.addActionListener(sizeAction); + tmp.setMnemonic(KeyEvent.VK_S); + systemMenu.add(tmp); + + tmp = new JMenuItem(ICONIFY_CMD); + tmp.addActionListener(iconifyAction); + tmp.setMnemonic(KeyEvent.VK_N); + systemMenu.add(tmp); + + tmp = new JMenuItem(MAXIMIZE_CMD); + tmp.addActionListener(maximizeAction); + tmp.setMnemonic(KeyEvent.VK_X); + systemMenu.add(tmp); + + systemMenu.addSeparator(); + + tmp = new JMenuItem(CLOSE_CMD); + tmp.addActionListener(closeAction); + tmp.setMnemonic(KeyEvent.VK_C); + systemMenu.add(tmp); + } + + /** + * This method creates a new JMenubar. + * + * @return A new JMenuBar. + */ + protected JMenuBar createSystemMenuBar() + { + if (menuBar == null) + menuBar = new SystemMenuBar(); + menuBar.removeAll(); + return menuBar; + } + + /** + * This method creates a new JMenu. + * + * @return A new JMenu. + */ + protected JMenu createSystemMenu() + { + if (windowMenu == null) + windowMenu = new JMenu(); + windowMenu.removeAll(); + return windowMenu; + } + + /** + * This method programmatically shows the JMenu. + */ + protected void showSystemMenu() + { + // FIXME: Untested as KeyEvents are not hooked up. + menuBar.getMenu(1).getPopupMenu().show(); + } + + /** + * This method paints the TitlePane. + * + * @param g The Graphics object to paint with. + */ + public void paintComponent(Graphics g) + { + paintTitleBackground(g); + Font f = g.getFont(); + FontMetrics fm = g.getFontMetrics(f); + if (frame.getTitle() != null && title != null) + { + Color saved = g.getColor(); + if (frame.isSelected()) + g.setColor(activeFGColor); + else + g.setColor(inactiveFGColor); + title.setText(getTitle(frame.getTitle(), fm, title.getBounds().width)); + SwingUtilities.paintComponent(g, title, null, title.getBounds()); + g.setColor(saved); + } + } + + /** + * This method paints the TitlePane's background. + * + * @param g The Graphics object to paint with. + */ + protected void paintTitleBackground(Graphics g) + { + Color saved = g.getColor(); + Dimension dims = getSize(); + + Color bg = getBackground(); + if (frame.isSelected()) + bg = activeBGColor; + else + bg = inactiveBGColor; + g.setColor(bg); + g.fillRect(0, 0, dims.width, dims.height); + g.setColor(saved); + } + + /** + * This method returns the title string based on the available width and the + * font metrics. + * + * @param text The desired title. + * @param fm The FontMetrics of the font used. + * @param availableWidth The available width. + * + * @return The allowable string. + */ + protected String getTitle(String text, FontMetrics fm, int availableWidth) + { + Rectangle vr = new Rectangle(0, 0, availableWidth, fm.getHeight()); + Rectangle ir = new Rectangle(); + Rectangle tr = new Rectangle(); + String value = SwingUtilities.layoutCompoundLabel(this, fm, text, null, + SwingConstants.CENTER, + SwingConstants.LEFT, + SwingConstants.CENTER, + SwingConstants.LEFT, vr, + ir, tr, 0); + return value; + } + + /** + * This method fires something similar to a WINDOW_CLOSING event. + * + * @param frame The JInternalFrame that is being closed. + */ + protected void postClosingEvent(JInternalFrame frame) + { + // FIXME: Implement postClosingEvent when I figure out what + // it's supposed to do. + // It says that this fires an WINDOW_CLOSING like event. + // So the closest thing is some kind of InternalFrameEvent. + // But none is fired. + // Can't see it called or anything. + } + + /** + * This method enables the actions for the TitlePane given the frame's + * properties. + */ + protected void enableActions() + { + closeAction.setEnabled(frame.isClosable()); + + iconifyAction.setEnabled(frame.isIconifiable()); + // The maximize action is responsible for restoring it + // as well, if clicked from the button + maximizeAction.setEnabled(frame.isMaximizable()); + + // The restoring action is only active when selected + // from the menu. + restoreAction.setEnabled(frame.isMaximum()); + + sizeAction.setEnabled(frame.isResizable()); + + // FIXME: Tie MoveAction enabled status to a variable. + moveAction.setEnabled(false); + } + + /** + * This method creates a new PropertyChangeListener. + * + * @return A new PropertyChangeListener. + */ + protected PropertyChangeListener createPropertyChangeListener() + { + return new PropertyChangeHandler(); + } + + /** + * This method creates a new LayoutManager for the TitlePane. + * + * @return A new LayoutManager. + */ + protected LayoutManager createLayout() + { + return new TitlePaneLayout(); + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameUI.java new file mode 100644 index 0000000..1637966 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameUI.java @@ -0,0 +1,1719 @@ +/* BasicInternalFrameUI.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.AWTEvent; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.LayoutManager; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyVetoException; +import java.beans.VetoableChangeListener; + +import javax.swing.BorderFactory; +import javax.swing.DefaultDesktopManager; +import javax.swing.DesktopManager; +import javax.swing.JComponent; +import javax.swing.JDesktopPane; +import javax.swing.JInternalFrame; +import javax.swing.KeyStroke; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.border.AbstractBorder; +import javax.swing.border.BevelBorder; +import javax.swing.border.Border; +import javax.swing.event.InternalFrameEvent; +import javax.swing.event.InternalFrameListener; +import javax.swing.event.MouseInputAdapter; +import javax.swing.event.MouseInputListener; +import javax.swing.plaf.BorderUIResource; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.InternalFrameUI; +import javax.swing.plaf.UIResource; + +/** + * This is the UI delegate for the Basic look and feel for JInternalFrames. + */ +public class BasicInternalFrameUI extends InternalFrameUI +{ + /** + * This is a helper class that listens to the JInternalFrame for + * InternalFrameEvents. + */ + protected class BasicInternalFrameListener implements InternalFrameListener + { + /** + * This method is called when the JInternalFrame is activated. + * + * @param e The InternalFrameEvent. + */ + public void internalFrameActivated(InternalFrameEvent e) + { + // FIXME: Implement. + } + + /** + * This method is called when the JInternalFrame is closed. + * + * @param e The InternalFrameEvent. + */ + public void internalFrameClosed(InternalFrameEvent e) + { + // FIXME: Implement. + } + + /** + * This method is called when the JInternalFrame is closing. + * + * @param e The InternalFrameEvent. + */ + public void internalFrameClosing(InternalFrameEvent e) + { + // FIXME: Implement. + } + + /** + * This method is called when the JInternalFrame is deactivated. + * + * @param e The InternalFrameEvent. + */ + public void internalFrameDeactivated(InternalFrameEvent e) + { + // FIXME: Implement. + } + + /** + * This method is called when the JInternalFrame is deiconified. + * + * @param e The InternalFrameEvent. + */ + public void internalFrameDeiconified(InternalFrameEvent e) + { + // FIXME: Implement. + } + + /** + * This method is called when the JInternalFrame is iconified. + * + * @param e The InternalFrameEvent. + */ + public void internalFrameIconified(InternalFrameEvent e) + { + // FIXME: Implement. + } + + /** + * This method is called when the JInternalFrame is opened. + * + * @param e The InternalFrameEvent. + */ + public void internalFrameOpened(InternalFrameEvent e) + { + // FIXME: Implement. + } + } + + /** + * This helper class listens to the edges of the JInternalFrame and the + * TitlePane for mouse events. It is responsible for dragging and resizing + * the JInternalFrame in response to the MouseEvents. + */ + protected class BorderListener extends MouseInputAdapter + implements SwingConstants + { + /** FIXME: Use for something. */ + protected final int RESIZE_NONE = 0; + + /** The x offset from the top left corner of the JInternalFrame. */ + private transient int xOffset = 0; + + /** The y offset from the top left corner of the JInternalFrame. */ + private transient int yOffset = 0; + + /** The direction that the resize is occuring in. */ + private transient int direction = -1; + + /** Cache rectangle that can be reused. */ + private transient Rectangle cacheRect = new Rectangle(); + + /** + * This method is called when the mouse is clicked. + * + * @param e The MouseEvent. + */ + public void mouseClicked(MouseEvent e) + { + // There is nothing to do when the mouse is clicked + // on the border. + } + + /** + * This method is called when the mouse is dragged. This method is + * responsible for resizing or dragging the JInternalFrame. + * + * @param e The MouseEvent. + */ + public void mouseDragged(MouseEvent e) + { + // If the frame is maximized, there is nothing that + // can be dragged around. + if (frame.isMaximum()) + return; + DesktopManager dm = getDesktopManager(); + Rectangle b = frame.getBounds(); + Dimension min = frame.getMinimumSize(); + if (min == null) + min = new Dimension(0, 0); + Insets insets = frame.getInsets(); + int x = e.getX(); + int y = e.getY(); + if (e.getSource() == frame && frame.isResizable()) + { + switch (direction) + { + case NORTH: + cacheRect.setBounds(b.x, + Math.min(b.y + y, b.y + b.height + - min.height), b.width, b.height + - y); + break; + case NORTH_EAST: + cacheRect.setBounds(b.x, + Math.min(b.y + y, b.y + b.height + - min.height), x, b.height - y); + break; + case EAST: + cacheRect.setBounds(b.x, b.y, x, b.height); + break; + case SOUTH_EAST: + cacheRect.setBounds(b.x, b.y, x, y); + break; + case SOUTH: + cacheRect.setBounds(b.x, b.y, b.width, y); + break; + case SOUTH_WEST: + cacheRect.setBounds(Math.min(b.x + x, b.x + b.width - min.width), + b.y, b.width - x, y); + break; + case WEST: + cacheRect.setBounds(Math.min(b.x + x, b.x + b.width - min.width), + b.y, b.width - x, b.height); + break; + case NORTH_WEST: + cacheRect.setBounds(Math.min(b.x + x, b.x + b.width - min.width), + Math.min(b.y + y, b.y + b.height + - min.height), b.width - x, + b.height - y); + break; + } + dm.resizeFrame(frame, cacheRect.x, cacheRect.y, + Math.max(min.width, cacheRect.width), + Math.max(min.height, cacheRect.height)); + } + else if (e.getSource() == titlePane) + { + Rectangle fBounds = frame.getBounds(); + + dm.dragFrame(frame, e.getX() - xOffset + b.x, + e.getY() - yOffset + b.y); + } + } + + /** + * This method is called when the mouse exits the JInternalFrame. + * + * @param e The MouseEvent. + */ + public void mouseExited(MouseEvent e) + { + // There is nothing to do when the mouse exits + // the border area. + } + + /** + * This method is called when the mouse is moved inside the + * JInternalFrame. + * + * @param e The MouseEvent. + */ + public void mouseMoved(MouseEvent e) + { + // There is nothing to do when the mouse moves + // over the border area. + } + + /** + * This method is called when the mouse is pressed. + * + * @param e The MouseEvent. + */ + public void mousePressed(MouseEvent e) + { + activateFrame(frame); + DesktopManager dm = getDesktopManager(); + int x = e.getX(); + int y = e.getY(); + Insets insets = frame.getInsets(); + + if (e.getSource() == frame && frame.isResizable()) + { + direction = sectionOfClick(x, y); + dm.beginResizingFrame(frame, direction); + } + else if (e.getSource() == titlePane) + { + Rectangle tBounds = titlePane.getBounds(); + + xOffset = e.getX() - tBounds.x + insets.left; + yOffset = e.getY() - tBounds.y + insets.top; + + dm.beginDraggingFrame(frame); + } + } + + /** + * This method is called when the mouse is released. + * + * @param e The MouseEvent. + */ + public void mouseReleased(MouseEvent e) + { + DesktopManager dm = getDesktopManager(); + xOffset = 0; + yOffset = 0; + if (e.getSource() == frame && frame.isResizable()) + dm.endResizingFrame(frame); + else if (e.getSource() == titlePane) + dm.endDraggingFrame(frame); + } + + /** + * This method determines the direction of the resize based on the + * coordinates and the size of the JInternalFrame. + * + * @param x The x coordinate of the MouseEvent. + * @param y The y coordinate of the MouseEvent. + * + * @return The direction of the resize (a SwingConstant direction). + */ + private int sectionOfClick(int x, int y) + { + Insets insets = frame.getInsets(); + Rectangle b = frame.getBounds(); + if (x < insets.left && y < insets.top) + return NORTH_WEST; + else if (x > b.width - insets.right && y < insets.top) + return NORTH_EAST; + else if (x > b.width - insets.right && y > b.height - insets.bottom) + return SOUTH_EAST; + else if (x < insets.left && y > b.height - insets.bottom) + return SOUTH_WEST; + else if (y < insets.top) + return NORTH; + else if (x < insets.left) + return WEST; + else if (y > b.height - insets.bottom) + return SOUTH; + else if (x > b.width - insets.right) + return EAST; + + return -1; + } + } + + /** + * This helper class listens to the JDesktopPane that parents this + * JInternalFrame and listens for resize events and resizes the + * JInternalFrame appropriately. + */ + protected class ComponentHandler implements ComponentListener + { + /** + * This method is called when the JDesktopPane is hidden. + * + * @param e The ComponentEvent fired. + */ + public void componentHidden(ComponentEvent e) + { + // Do nothing. + } + + /** + * This method is called when the JDesktopPane is moved. + * + * @param e The ComponentEvent fired. + */ + public void componentMoved(ComponentEvent e) + { + // Do nothing. + } + + /** + * This method is called when the JDesktopPane is resized. + * + * @param e The ComponentEvent fired. + */ + public void componentResized(ComponentEvent e) + { + if (frame.isMaximum()) + { + JDesktopPane pane = (JDesktopPane) e.getSource(); + Insets insets = pane.getInsets(); + Rectangle bounds = pane.getBounds(); + + frame.setBounds(bounds.x + insets.left, bounds.y + insets.top, + bounds.width - insets.left - insets.right, + bounds.height - insets.top - insets.bottom); + frame.revalidate(); + frame.repaint(); + } + + // Sun also resizes the icons. but it doesn't seem to do anything. + } + + /** + * This method is called when the JDesktopPane is shown. + * + * @param e The ComponentEvent fired. + */ + public void componentShown(ComponentEvent e) + { + // Do nothing. + } + } + + /** + * This helper class acts as the LayoutManager for JInternalFrames. + */ + public class InternalFrameLayout implements LayoutManager + { + /** + * This method is called when the given Component is added to the + * JInternalFrame. + * + * @param name The name of the Component. + * @param c The Component added. + */ + public void addLayoutComponent(String name, Component c) + { + } + + /** + * This method is used to set the bounds of the children of the + * JInternalFrame. + * + * @param c The Container to lay out. + */ + public void layoutContainer(Container c) + { + Dimension dims = frame.getSize(); + Insets insets = frame.getInsets(); + + dims.width -= insets.left + insets.right; + dims.height -= insets.top + insets.bottom; + + frame.getRootPane().getGlassPane().setBounds(0, 0, dims.width, + dims.height); + int nh = 0; + int sh = 0; + int ew = 0; + int ww = 0; + + if (northPane != null) + { + Dimension nDims = northPane.getPreferredSize(); + nh = Math.min(nDims.height, dims.height); + + northPane.setBounds(insets.left, insets.top, dims.width, nh); + } + + if (southPane != null) + { + Dimension sDims = southPane.getPreferredSize(); + sh = Math.min(sDims.height, dims.height - nh); + + southPane.setBounds(insets.left, insets.top + dims.height - sh, + dims.width, sh); + } + + int remHeight = dims.height - sh - nh; + + if (westPane != null) + { + Dimension wDims = westPane.getPreferredSize(); + ww = Math.min(dims.width, wDims.width); + + westPane.setBounds(insets.left, insets.top + nh, ww, remHeight); + } + + if (eastPane != null) + { + Dimension eDims = eastPane.getPreferredSize(); + ew = Math.min(eDims.width, dims.width - ww); + + eastPane.setBounds(insets.left + dims.width - ew, insets.top + nh, + ew, remHeight); + } + + int remWidth = dims.width - ww - ew; + + frame.getRootPane().setBounds(insets.left + ww, insets.top + nh, + remWidth, remHeight); + } + + /** + * This method returns the minimum layout size. + * + * @param c The Container to find a minimum layout size for. + * + * @return The minimum dimensions for the JInternalFrame. + */ + public Dimension minimumLayoutSize(Container c) + { + return getSize(c, true); + } + + /** + * This method returns the maximum layout size. + * + * @param c The Container to find a maximum layout size for. + * + * @return The maximum dimensions for the JInternalFrame. + */ + public Dimension maximumLayoutSize(Container c) + { + return preferredLayoutSize(c); + } + + /** + * Th8is method returns the preferred layout size. + * + * @param c The Container to find a preferred layout size for. + * + * @return The preferred dimensions for the JInternalFrame. + */ + public Dimension preferredLayoutSize(Container c) + { + return getSize(c, false); + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + * @param min DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + private Dimension getSize(Container c, boolean min) + { + Insets insets = frame.getInsets(); + + Dimension contentDims = frame.getContentPane().getPreferredSize(); + if (min) + contentDims.width = contentDims.height = 0; + int nWidth = 0; + int nHeight = 0; + int sWidth = 0; + int sHeight = 0; + int eWidth = 0; + int eHeight = 0; + int wWidth = 0; + int wHeight = 0; + Dimension dims; + + if (northPane != null) + { + dims = northPane.getPreferredSize(); + if (dims != null) + { + nWidth = dims.width; + nHeight = dims.height; + } + } + + if (southPane != null) + { + dims = southPane.getPreferredSize(); + if (dims != null) + { + sWidth = dims.width; + sHeight = dims.height; + } + } + + if (eastPane != null) + { + dims = eastPane.getPreferredSize(); + if (dims != null) + { + sWidth = dims.width; + sHeight = dims.height; + } + } + + if (westPane != null) + { + dims = westPane.getPreferredSize(); + if (dims != null) + { + wWidth = dims.width; + wHeight = dims.height; + } + } + + int width = Math.max(sWidth, nWidth); + width = Math.max(width, contentDims.width + eWidth + wWidth); + + int height = Math.max(eHeight, wHeight); + height = Math.max(height, contentDims.height); + height += nHeight + sHeight; + + width += insets.left + insets.right; + height += insets.top + insets.bottom; + + return new Dimension(width, height); + } + + /** + * This method is called when a Component is removed from the + * JInternalFrame. + * + * @param c The Component that was removed. + */ + public void removeLayoutComponent(Component c) + { + } + } + + /** + * This helper class is used to listen to the JDesktopPane's glassPane for + * MouseEvents. The JInternalFrame can then be selected if a click is + * detected on its children. + */ + protected class GlassPaneDispatcher implements MouseInputListener + { + /** The MouseEvent target. */ + private transient Component mouseEventTarget; + + /** The component pressed. */ + private transient Component pressedComponent; + + /** The last component entered. */ + private transient Component lastComponentEntered; + + /** Used to store/reset lastComponentEntered. */ + private transient Component tempComponent; + + /** The number of presses. */ + private transient int pressCount; + + /** + * This method is called when the mouse enters the glass pane. + * + * @param e The MouseEvent. + */ + public void mouseEntered(MouseEvent e) + { + handleEvent(e); + } + + /** + * This method is called when the mouse is clicked on the glass pane. + * + * @param e The MouseEvent. + */ + public void mouseClicked(MouseEvent e) + { + handleEvent(e); + } + + /** + * This method is called when the mouse is dragged in the glass pane. + * + * @param e The MouseEvent. + */ + public void mouseDragged(MouseEvent e) + { + handleEvent(e); + } + + /** + * This method is called when the mouse exits the glass pane. + * + * @param e The MouseEvent. + */ + public void mouseExited(MouseEvent e) + { + handleEvent(e); + } + + /** + * This method is called when the mouse is moved in the glass pane. + * + * @param e The MouseEvent. + */ + public void mouseMoved(MouseEvent e) + { + handleEvent(e); + } + + /** + * This method is called when the mouse is pressed in the glass pane. + * + * @param e The MouseEvent. + */ + public void mousePressed(MouseEvent e) + { + activateFrame(frame); + handleEvent(e); + } + + /** + * This method is called when the mouse is released in the glass pane. + * + * @param e The MouseEvent. + */ + public void mouseReleased(MouseEvent e) + { + handleEvent(e); + } + + /** + * This method acquires a candidate component to dispatch the MouseEvent + * to. + * + * @param me The MouseEvent to acquire a component for. + */ + private void acquireComponentForMouseEvent(MouseEvent me) + { + int x = me.getX(); + int y = me.getY(); + + // Find the candidate which should receive this event. + Component parent = frame.getContentPane(); + if (parent == null) + return; + Component candidate = null; + Point p = me.getPoint(); + while (candidate == null && parent != null) + { + candidate = SwingUtilities.getDeepestComponentAt(parent, p.x, p.y); + if (candidate == null) + { + p = SwingUtilities.convertPoint(parent, p.x, p.y, + parent.getParent()); + parent = parent.getParent(); + } + } + + // If the only candidate we found was the native container itself, + // don't dispatch any event at all. We only care about the lightweight + // children here. + if (candidate == frame.getContentPane()) + candidate = null; + + // If our candidate is new, inform the old target we're leaving. + if (lastComponentEntered != null && lastComponentEntered.isShowing() + && lastComponentEntered != candidate) + { + Point tp = SwingUtilities.convertPoint(frame.getContentPane(), x, y, + lastComponentEntered); + MouseEvent exited = new MouseEvent(lastComponentEntered, + MouseEvent.MOUSE_EXITED, + me.getWhen(), me.getModifiersEx(), + tp.x, tp.y, me.getClickCount(), + me.isPopupTrigger(), + me.getButton()); + tempComponent = lastComponentEntered; + lastComponentEntered = null; + tempComponent.dispatchEvent(exited); + } + + // If we have a candidate, maybe enter it. + if (candidate != null) + { + mouseEventTarget = candidate; + if (candidate.isLightweight() && candidate.isShowing() + && candidate != frame.getContentPane() + && candidate != lastComponentEntered) + { + lastComponentEntered = mouseEventTarget; + Point cp = SwingUtilities.convertPoint(frame.getContentPane(), + x, y, lastComponentEntered); + MouseEvent entered = new MouseEvent(lastComponentEntered, + MouseEvent.MOUSE_ENTERED, + me.getWhen(), + me.getModifiersEx(), cp.x, + cp.y, me.getClickCount(), + me.isPopupTrigger(), + me.getButton()); + lastComponentEntered.dispatchEvent(entered); + } + } + + if (me.getID() == MouseEvent.MOUSE_RELEASED + || me.getID() == MouseEvent.MOUSE_PRESSED && pressCount > 0 + || me.getID() == MouseEvent.MOUSE_DRAGGED) + // If any of the following events occur while a button is held down, + // they should be dispatched to the same component to which the + // original MOUSE_PRESSED event was dispatched: + // - MOUSE_RELEASED + // - MOUSE_PRESSED: another button pressed while the first is held down + // - MOUSE_DRAGGED + mouseEventTarget = pressedComponent; + else if (me.getID() == MouseEvent.MOUSE_CLICKED) + { + // Don't dispatch CLICKED events whose target is not the same as the + // target for the original PRESSED event. + if (candidate != pressedComponent) + mouseEventTarget = null; + else if (pressCount == 0) + pressedComponent = null; + } + } + + /** + * This is a helper method that dispatches the GlassPane MouseEvents to + * the proper component. + * + * @param e The AWTEvent to be dispatched. Usually an instance of + * MouseEvent. + */ + private void handleEvent(AWTEvent e) + { + if (e instanceof MouseEvent) + { + MouseEvent me = SwingUtilities.convertMouseEvent(frame.getRootPane() + .getGlassPane(), + (MouseEvent) e, + frame.getRootPane() + .getGlassPane()); + + acquireComponentForMouseEvent(me); + + // Avoid dispatching ENTERED and EXITED events twice. + if (mouseEventTarget != null && mouseEventTarget.isShowing() + && e.getID() != MouseEvent.MOUSE_ENTERED + && e.getID() != MouseEvent.MOUSE_EXITED) + { + MouseEvent newEvt = SwingUtilities.convertMouseEvent(frame + .getContentPane(), + me, + mouseEventTarget); + mouseEventTarget.dispatchEvent(newEvt); + + switch (e.getID()) + { + case MouseEvent.MOUSE_PRESSED: + if (pressCount++ == 0) + pressedComponent = mouseEventTarget; + break; + case MouseEvent.MOUSE_RELEASED: + // Clear our memory of the original PRESSED event, only if + // we're not expecting a CLICKED event after this. If + // there is a CLICKED event after this, it will do clean up. + if (--pressCount == 0 + && mouseEventTarget != pressedComponent) + pressedComponent = null; + break; + } + } + } + } + } + + /** + * This helper class listens for PropertyChangeEvents from the + * JInternalFrame. + */ + public class InternalFramePropertyChangeListener + implements PropertyChangeListener, VetoableChangeListener + { + + /** + * This method is called when one of the JInternalFrame's properties + * change. This method is to allow JInternalFrame to veto an attempt + * to close the internal frame. This allows JInternalFrame to honour + * its defaultCloseOperation if that is DO_NOTHING_ON_CLOSE. + */ + public void vetoableChange(PropertyChangeEvent e) throws PropertyVetoException + { + if (e.getPropertyName().equals(JInternalFrame.IS_CLOSED_PROPERTY)) + { + if (frame.getDefaultCloseOperation() == JInternalFrame.HIDE_ON_CLOSE) + { + frame.setVisible(false); + frame.getDesktopPane().repaint(); + throw new PropertyVetoException ("close operation is HIDE_ON_CLOSE\n", e); + } + else if (frame.getDefaultCloseOperation() == JInternalFrame.DISPOSE_ON_CLOSE) + closeFrame(frame); + else + throw new PropertyVetoException ("close operation is DO_NOTHING_ON_CLOSE\n", e); + } + } + + /** + * This method is called when one of the JInternalFrame's properties + * change. + * + * @param evt The PropertyChangeEvent. + */ + public void propertyChange(PropertyChangeEvent evt) + { + if (evt.getPropertyName().equals(JInternalFrame.IS_MAXIMUM_PROPERTY)) + { + if (frame.isMaximum()) + maximizeFrame(frame); + else + minimizeFrame(frame); + } + else if (evt.getPropertyName().equals(JInternalFrame.IS_ICON_PROPERTY)) + { + if (frame.isIcon()) + iconifyFrame(frame); + else + deiconifyFrame(frame); + } + else if (evt.getPropertyName().equals(JInternalFrame.IS_SELECTED_PROPERTY)) + { + if (frame.isSelected()) + activateFrame(frame); + else + getDesktopManager().deactivateFrame(frame); + } + else if (evt.getPropertyName().equals(JInternalFrame.ROOT_PANE_PROPERTY) + || evt.getPropertyName().equals(JInternalFrame.GLASS_PANE_PROPERTY)) + { + Component old = (Component) evt.getOldValue(); + old.removeMouseListener(glassPaneDispatcher); + old.removeMouseMotionListener(glassPaneDispatcher); + + Component newPane = (Component) evt.getNewValue(); + newPane.addMouseListener(glassPaneDispatcher); + newPane.addMouseMotionListener(glassPaneDispatcher); + + frame.revalidate(); + } + /* FIXME: need to add ancestor properties to JComponents. + else if (evt.getPropertyName().equals(JComponent.ANCESTOR_PROPERTY)) + { + if (desktopPane != null) + desktopPane.removeComponentListener(componentListener); + desktopPane = frame.getDesktopPane(); + if (desktopPane != null) + desktopPane.addComponentListener(componentListener); + } + */ + } + } + + /** + * This helper class is the border for the JInternalFrame. + */ + private class InternalFrameBorder extends AbstractBorder + implements UIResource + { + /** The width of the border. */ + private static final int bSize = 5; + + /** The size of the corners. */ + private static final int offset = 10; + + /** + * This method returns whether the border is opaque. + * + * @return Whether the border is opaque. + */ + public boolean isBorderOpaque() + { + return true; + } + + /** + * This method returns the insets of the border. + * + * @param c The Component to find border insets for. + * + * @return The border insets. + */ + public Insets getBorderInsets(Component c) + { + return new Insets(bSize, bSize, bSize, bSize); + } + + /** + * This method paints the border. + * + * @param c The Component that owns the border. + * @param g The Graphics object to paint with. + * @param x The x coordinate to paint at. + * @param y The y coordinate to paint at. + * @param width The width of the Component. + * @param height The height of the Component. + */ + public void paintBorder(Component c, Graphics g, int x, int y, int width, + int height) + { + g.translate(x, y); + Color saved = g.getColor(); + Rectangle b = frame.getBounds(); + + Color d = c.getBackground(); + g.setColor(d); + g.fillRect(0, 0, bSize, b.height); + g.fillRect(0, 0, b.width, bSize); + g.fillRect(0, b.height - bSize, b.width, bSize); + g.fillRect(b.width - bSize, 0, bSize, b.height); + + int x1 = 0; + int x2 = bSize; + int x3 = b.width - bSize; + int x4 = b.width; + + int y1 = 0; + int y2 = bSize; + int y3 = b.height - bSize; + int y4 = b.height; + + g.setColor(Color.GRAY); + g.fillRect(0, 0, bSize, y4); + g.fillRect(0, 0, x4, bSize); + g.fillRect(0, y3, b.width, bSize); + g.fillRect(x3, 0, bSize, b.height); + + g.fill3DRect(0, offset, bSize, b.height - 2 * offset, false); + g.fill3DRect(offset, 0, b.width - 2 * offset, bSize, false); + g.fill3DRect(offset, b.height - bSize, b.width - 2 * offset, bSize, false); + g.fill3DRect(b.width - bSize, offset, bSize, b.height - 2 * offset, false); + + g.translate(-x, -y); + g.setColor(saved); + } + } + + /** + * The MouseListener that is responsible for dragging and resizing the + * JInternalFrame in response to MouseEvents. + */ + protected MouseInputAdapter borderListener; + + /** + * The ComponentListener that is responsible for resizing the JInternalFrame + * in response to ComponentEvents from the JDesktopPane. + */ + protected ComponentListener componentListener; + + /** + * The MouseListener that is responsible for activating the JInternalFrame + * when the mouse press activates one of its descendents. + */ + protected MouseInputListener glassPaneDispatcher; + + /** + * The PropertyChangeListener that is responsible for listening to + * PropertyChangeEvents from the JInternalFrame. + */ + protected PropertyChangeListener propertyChangeListener; + + /** + * The VetoableChangeListener. Listens to PropertyChangeEvents + * from the JInternalFrame and allows the JInternalFrame to + * veto attempts to close it. + */ + private VetoableChangeListener internalFrameVetoableChangeListener; + + /** The InternalFrameListener that listens to the JInternalFrame. */ + private transient BasicInternalFrameListener internalFrameListener; + + /** The JComponent placed at the east region of the JInternalFrame. */ + protected JComponent eastPane; + + /** The JComponent placed at the north region of the JInternalFrame. */ + protected JComponent northPane; + + /** The JComponent placed at the south region of the JInternalFrame. */ + protected JComponent southPane; + + /** The JComponent placed at the west region of the JInternalFrame. */ + protected JComponent westPane; + + /** + * The Keystroke bound to open the menu. + * @deprecated + */ + protected KeyStroke openMenuKey; + + /** The TitlePane displayed at the top of the JInternalFrame. */ + protected BasicInternalFrameTitlePane titlePane; + + /** The JInternalFrame this UI is responsible for. */ + protected JInternalFrame frame; + + /** The LayoutManager used in the JInternalFrame. */ + protected LayoutManager internalFrameLayout; + + /** The JDesktopPane that is the parent of the JInternalFrame. */ + private transient JDesktopPane desktopPane; + + /** + * Creates a new BasicInternalFrameUI object. + * + * @param b The JInternalFrame this UI will represent. + */ + public BasicInternalFrameUI(JInternalFrame b) + { + } + + /** + * This method will create a new BasicInternalFrameUI for the given + * JComponent. + * + * @param b The JComponent to create a BasicInternalFrameUI for. + * + * @return A new BasicInternalFrameUI. + */ + public static ComponentUI createUI(JComponent b) + { + return new BasicInternalFrameUI((JInternalFrame) b); + } + + /** + * This method installs a UI for the JInternalFrame. + * + * @param c The JComponent to install this UI on. + */ + public void installUI(JComponent c) + { + if (c instanceof JInternalFrame) + { + frame = (JInternalFrame) c; + + internalFrameLayout = createLayoutManager(); + frame.setLayout(internalFrameLayout); + + ((JComponent) frame.getRootPane().getGlassPane()).setOpaque(false); + frame.getRootPane().getGlassPane().setVisible(true); + + installDefaults(); + installListeners(); + installComponents(); + installKeyboardActions(); + + frame.setOpaque(true); + titlePane.setOpaque(true); + frame.invalidate(); + } + } + + /** + * This method reverses the work done by installUI. + * + * @param c The JComponent to uninstall this UI for. + */ + public void uninstallUI(JComponent c) + { + uninstallKeyboardActions(); + uninstallComponents(); + uninstallListeners(); + uninstallDefaults(); + + frame.setLayout(null); + ((JComponent) frame.getRootPane().getGlassPane()).setOpaque(true); + frame.getRootPane().getGlassPane().setVisible(false); + + frame = null; + } + + /** + * This method installs the defaults specified by the look and feel. + */ + protected void installDefaults() + { + // This is the border of InternalFrames in the BasicLookAndFeel. + // Note that there exist entries for various border colors in + // BasicLookAndFeel's defaults, but obviously they differ + // from the colors that are actually used by the JDK. + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + Color borderColor = defaults.getColor("InternalFrame.borderColor"); + Border inner = BorderFactory.createLineBorder(borderColor, 1); + Color borderDarkShadow = defaults.getColor + ("InternalFrame.borderDarkShadow"); + Color borderHighlight = defaults.getColor + ("InternalFrame.borderHighlight"); + Color borderShadow = defaults.getColor("InternalFrame.borderShadow"); + Color borderLight = defaults.getColor("InternalFrame.borderLight"); + Border outer = BorderFactory.createBevelBorder(BevelBorder.RAISED, + borderShadow, + borderHighlight, + borderDarkShadow, + borderShadow); + Border border = new BorderUIResource.CompoundBorderUIResource(outer, + inner); + frame.setBorder(border); + + // InternalFrames are invisible by default. + frame.setVisible(false); + } + + /** + * This method installs the keyboard actions for the JInternalFrame. + */ + protected void installKeyboardActions() + { + // FIXME: Implement. + } + + /** + * This method installs the Components for the JInternalFrame. + */ + protected void installComponents() + { + setNorthPane(createNorthPane(frame)); + setSouthPane(createSouthPane(frame)); + setEastPane(createEastPane(frame)); + setWestPane(createWestPane(frame)); + } + + /** + * This method installs the listeners for the JInternalFrame. + */ + protected void installListeners() + { + glassPaneDispatcher = createGlassPaneDispatcher(); + createInternalFrameListener(); + borderListener = createBorderListener(frame); + componentListener = createComponentListener(); + propertyChangeListener = createPropertyChangeListener(); + internalFrameVetoableChangeListener = new InternalFramePropertyChangeListener(); + + frame.addMouseListener(borderListener); + frame.addMouseMotionListener(borderListener); + frame.addInternalFrameListener(internalFrameListener); + frame.addPropertyChangeListener(propertyChangeListener); + frame.addVetoableChangeListener(internalFrameVetoableChangeListener); + frame.getRootPane().getGlassPane().addMouseListener(glassPaneDispatcher); + frame.getRootPane().getGlassPane().addMouseMotionListener(glassPaneDispatcher); + } + + /** + * This method uninstalls the defaults for the JInternalFrame. + */ + protected void uninstallDefaults() + { + frame.setBorder(null); + } + + /** + * This method uninstalls the Components for the JInternalFrame. + */ + protected void uninstallComponents() + { + setNorthPane(null); + setSouthPane(null); + setEastPane(null); + setWestPane(null); + } + + /** + * This method uninstalls the listeners for the JInternalFrame. + */ + protected void uninstallListeners() + { + if (desktopPane != null) + desktopPane.removeComponentListener(componentListener); + + frame.getRootPane().getGlassPane().removeMouseMotionListener(glassPaneDispatcher); + frame.getRootPane().getGlassPane().removeMouseListener(glassPaneDispatcher); + + frame.removePropertyChangeListener(propertyChangeListener); + frame.removeInternalFrameListener(internalFrameListener); + frame.removeMouseMotionListener(borderListener); + frame.removeMouseListener(borderListener); + + propertyChangeListener = null; + componentListener = null; + borderListener = null; + internalFrameListener = null; + glassPaneDispatcher = null; + } + + /** + * This method uninstalls the keyboard actions for the JInternalFrame. + */ + protected void uninstallKeyboardActions() + { + // FIXME: Implement. + } + + /** + * This method creates a new LayoutManager for the JInternalFrame. + * + * @return A new LayoutManager for the JInternalFrame. + */ + protected LayoutManager createLayoutManager() + { + return new InternalFrameLayout(); + } + + /** + * This method creates a new PropertyChangeListener for the JInternalFrame. + * + * @return A new PropertyChangeListener for the JInternalFrame. + */ + protected PropertyChangeListener createPropertyChangeListener() + { + return new InternalFramePropertyChangeListener(); + } + + /** + * This method returns the preferred size of the given JComponent. + * + * @param x The JComponent to find a preferred size for. + * + * @return The preferred size. + */ + public Dimension getPreferredSize(JComponent x) + { + return internalFrameLayout.preferredLayoutSize(x); + } + + /** + * This method returns the minimum size of the given JComponent. + * + * @param x The JComponent to find a minimum size for. + * + * @return The minimum size. + */ + public Dimension getMinimumSize(JComponent x) + { + return internalFrameLayout.minimumLayoutSize(x); + } + + /** + * This method returns the maximum size of the given JComponent. + * + * @param x The JComponent to find a maximum size for. + * + * @return The maximum size. + */ + public Dimension getMaximumSize(JComponent x) + { + return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); + } + + /** + * This method replaces the currentPane with the newPane. When replacing it + * also removes the MouseHandlers for the old pane and installs them on + * the new pane. + * + * @param currentPane The old pane to remove. + * @param newPane The new pane to install. + */ + protected void replacePane(JComponent currentPane, JComponent newPane) + { + if (currentPane != null) + { + deinstallMouseHandlers(currentPane); + frame.remove(currentPane); + } + + if (newPane != null) + { + installMouseHandlers(newPane); + frame.add(newPane); + } + } + + /** + * This method removes the necessary MouseListeners from the given + * JComponent. + * + * @param c The JComponent to remove MouseListeners from. + */ + protected void deinstallMouseHandlers(JComponent c) + { + c.removeMouseListener(borderListener); + c.removeMouseMotionListener(borderListener); + } + + /** + * This method installs the necessary MouseListeners from the given + * JComponent. + * + * @param c The JComponent to install MouseListeners on. + */ + protected void installMouseHandlers(JComponent c) + { + c.addMouseListener(borderListener); + c.addMouseMotionListener(borderListener); + } + + /** + * This method creates the north pane used in the JInternalFrame. + * + * @param w The JInternalFrame to create a north pane for. + * + * @return The north pane. + */ + protected JComponent createNorthPane(JInternalFrame w) + { + titlePane = new BasicInternalFrameTitlePane(w); + return titlePane; + } + + /** + * This method creates the west pane used in the JInternalFrame. + * + * @param w The JInternalFrame to create a west pane for. + * + * @return The west pane. + */ + protected JComponent createWestPane(JInternalFrame w) + { + return null; + } + + /** + * This method creates the south pane used in the JInternalFrame. + * + * @param w The JInternalFrame to create a south pane for. + * + * @return The south pane. + */ + protected JComponent createSouthPane(JInternalFrame w) + { + return null; + } + + /** + * This method creates the east pane used in the JInternalFrame. + * + * @param w The JInternalFrame to create an east pane for. + * + * @return The east pane. + */ + protected JComponent createEastPane(JInternalFrame w) + { + return null; + } + + /** + * This method returns a new BorderListener for the given JInternalFrame. + * + * @param w The JIntenalFrame to create a BorderListener for. + * + * @return A new BorderListener. + */ + protected MouseInputAdapter createBorderListener(JInternalFrame w) + { + return new BorderListener(); + } + + /** + * This method creates a new InternalFrameListener for the JInternalFrame. + */ + protected void createInternalFrameListener() + { + internalFrameListener = new BasicInternalFrameListener(); + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + protected final boolean isKeyBindingRegistered() + { + // FIXME: Implement. + return false; + } + + /** + * DOCUMENT ME! + * + * @param b DOCUMENT ME! + */ + protected final void setKeyBindingRegistered(boolean b) + { + // FIXME: Implement. + } + + /** + * DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public final boolean isKeyBindingActive() + { + // FIXME: Implement. + return false; + } + + /** + * DOCUMENT ME! + * + * @param b DOCUMENT ME! + */ + protected final void setKeyBindingActive(boolean b) + { + // FIXME: Implement. + } + + /** + * DOCUMENT ME! + */ + protected void setupMenuOpenKey() + { + // FIXME: Implement. + } + + /** + * DOCUMENT ME! + */ + protected void setupMenuCloseKey() + { + // FIXME: Implement. + } + + /** + * This method returns the north pane. + * + * @return The north pane. + */ + public JComponent getNorthPane() + { + return northPane; + } + + /** + * This method sets the north pane to be the given JComponent. + * + * @param c The new north pane. + */ + public void setNorthPane(JComponent c) + { + replacePane(northPane, c); + northPane = c; + } + + /** + * This method returns the south pane. + * + * @return The south pane. + */ + public JComponent getSouthPane() + { + return southPane; + } + + /** + * This method sets the south pane to be the given JComponent. + * + * @param c The new south pane. + */ + public void setSouthPane(JComponent c) + { + replacePane(southPane, c); + southPane = c; + } + + /** + * This method sets the east pane to be the given JComponent. + * + * @param c The new east pane. + */ + public void setEastPane(JComponent c) + { + replacePane(eastPane, c); + eastPane = c; + } + + /** + * This method returns the east pane. + * + * @return The east pane. + */ + public JComponent getEastPane() + { + return eastPane; + } + + /** + * This method sets the west pane to be the given JComponent. + * + * @param c The new west pane. + */ + public void setWestPane(JComponent c) + { + replacePane(westPane, c); + westPane = c; + } + + /** + * This method returns the west pane. + * + * @return The west pane. + */ + public JComponent getWestPane() + { + return westPane; + } + + /** + * This method returns the DesktopManager to use with the JInternalFrame. + * + * @return The DesktopManager to use with the JInternalFrame. + */ + protected DesktopManager getDesktopManager() + { + DesktopManager value = null; + JDesktopPane pane = frame.getDesktopPane(); + if (pane != null) + value = frame.getDesktopPane().getDesktopManager(); + if (value == null) + value = createDesktopManager(); + return value; + } + + /** + * This method returns a default DesktopManager that can be used with this + * JInternalFrame. + * + * @return A default DesktopManager that can be used with this + * JInternalFrame. + */ + protected DesktopManager createDesktopManager() + { + return new DefaultDesktopManager(); + } + + /** + * This is a convenience method that closes the JInternalFrame. + * + * @param f The JInternalFrame to close. + */ + protected void closeFrame(JInternalFrame f) + { + getDesktopManager().closeFrame(f); + } + + /** + * This is a convenience method that maximizes the JInternalFrame. + * + * @param f The JInternalFrame to maximize. + */ + protected void maximizeFrame(JInternalFrame f) + { + getDesktopManager().maximizeFrame(f); + } + + /** + * This is a convenience method that minimizes the JInternalFrame. + * + * @param f The JInternalFrame to minimize. + */ + protected void minimizeFrame(JInternalFrame f) + { + getDesktopManager().minimizeFrame(f); + } + + /** + * This is a convenience method that iconifies the JInternalFrame. + * + * @param f The JInternalFrame to iconify. + */ + protected void iconifyFrame(JInternalFrame f) + { + getDesktopManager().iconifyFrame(f); + } + + /** + * This is a convenience method that deiconifies the JInternalFrame. + * + * @param f The JInternalFrame to deiconify. + */ + protected void deiconifyFrame(JInternalFrame f) + { + getDesktopManager().deiconifyFrame(f); + } + + /** + * This is a convenience method that activates the JInternalFrame. + * + * @param f The JInternalFrame to activate. + */ + protected void activateFrame(JInternalFrame f) + { + getDesktopManager().activateFrame(f); + } + + /** + * This method returns a new ComponentListener for the JDesktopPane. + * + * @return A new ComponentListener. + */ + protected ComponentListener createComponentListener() + { + return new ComponentHandler(); + } + + /** + * This method returns a new GlassPaneDispatcher. + * + * @return A new GlassPaneDispatcher. + */ + protected MouseInputListener createGlassPaneDispatcher() + { + return new GlassPaneDispatcher(); + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicLabelUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicLabelUI.java new file mode 100644 index 0000000..e71e82f --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicLabelUI.java @@ -0,0 +1,425 @@ +/* BasicLabelUI.java + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Rectangle; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.SwingUtilities; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.LabelUI; + + +/** + * This is the Basic Look and Feel class for the JLabel. One BasicLabelUI + * object is used to paint all JLabels that utilize the Basic Look and Feel. + */ +public class BasicLabelUI extends LabelUI implements PropertyChangeListener +{ + /** The labelUI that is shared by all labels. */ + protected static BasicLabelUI labelUI; + + /** + * Creates a new BasicLabelUI object. + */ + public BasicLabelUI() + { + super(); + } + + /** + * Creates and returns a UI for the label. Since one UI is shared by all + * labels, this means creating only if necessary and returning the shared + * UI. + * + * @param c The {@link JComponent} that a UI is being created for. + * + * @return A label UI for the Basic Look and Feel. + */ + public static ComponentUI createUI(JComponent c) + { + if (labelUI == null) + labelUI = new BasicLabelUI(); + return labelUI; + } + + /** + * Returns the preferred size of this component as calculated by the + * {@link #layoutCL(JLabel, FontMetrics, String, Icon, Rectangle, Rectangle, + * Rectangle)} method. + * + * @param c This {@link JComponent} to get a preferred size for. + * + * @return The preferred size. + */ + public Dimension getPreferredSize(JComponent c) + { + JLabel lab = (JLabel)c; + Rectangle vr = new Rectangle(); + Rectangle ir = new Rectangle(); + Rectangle tr = new Rectangle(); + Insets insets = lab.getInsets(); + FontMetrics fm = lab.getToolkit().getFontMetrics(lab.getFont()); + layoutCL(lab, fm, lab.getText(), lab.getIcon(), vr, ir, tr); + Rectangle cr = tr.union(ir); + return new Dimension(insets.left + cr.width + insets.right, + insets.top + cr.height + insets.bottom); + + } + + /** + * This method returns the minimum size of the {@link JComponent} given. If + * this method returns null, then it is up to the Layout Manager to give + * this component a minimum size. + * + * @param c The {@link JComponent} to get a minimum size for. + * + * @return The minimum size. + */ + public Dimension getMinimumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the maximum size of the {@link JComponent} given. If + * this method returns null, then it is up to the Layout Manager to give + * this component a maximum size. + * + * @param c The {@link JComponent} to get a maximum size for. + * + * @return The maximum size. + */ + public Dimension getMaximumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * The method that paints the label according to its current state. + * + * @param g The {@link Graphics} object to paint with. + * @param c The {@link JComponent} to paint. + */ + public void paint(Graphics g, JComponent c) + { + JLabel b = (JLabel) c; + + Font saved_font = g.getFont(); + + Rectangle tr = new Rectangle(); + Rectangle ir = new Rectangle(); + Rectangle vr = new Rectangle(); + + Font f = c.getFont(); + + g.setFont(f); + FontMetrics fm = g.getFontMetrics(f); + + vr = SwingUtilities.calculateInnerArea(c, vr); + + if (vr.width < 0) + vr.width = 0; + if (vr.height < 0) + vr.height = 0; + + Icon icon = (b.isEnabled()) ? b.getIcon() : b.getDisabledIcon(); + + String text = layoutCL(b, fm, b.getText(), icon, vr, ir, tr); + + if (icon != null) + icon.paintIcon(b, g, ir.x, ir.y); + if (text != null && ! text.equals("")) + { + if (b.isEnabled()) + paintEnabledText(b, g, text, tr.x, tr.y + fm.getAscent()); + else + paintDisabledText(b, g, text, tr.x, tr.y + fm.getAscent()); + } + g.setFont(saved_font); + } + + /** + * This method is simply calls SwingUtilities's layoutCompoundLabel. + * + * @param label The label to lay out. + * @param fontMetrics The FontMetrics for the font used. + * @param text The text to paint. + * @param icon The icon to draw. + * @param viewR The entire viewable rectangle. + * @param iconR The icon bounds rectangle. + * @param textR The text bounds rectangle. + * + * @return A possibly clipped version of the text. + */ + protected String layoutCL(JLabel label, FontMetrics fontMetrics, + String text, Icon icon, Rectangle viewR, + Rectangle iconR, Rectangle textR) + { + return SwingUtilities.layoutCompoundLabel(label, fontMetrics, text, icon, + label.getVerticalAlignment(), + label.getHorizontalAlignment(), + label.getVerticalTextPosition(), + label.getHorizontalTextPosition(), + viewR, iconR, textR, + label.getIconTextGap()); + } + + /** + * Paints the text if the label is disabled. By default, this paints the + * clipped text returned by layoutCompoundLabel using the + * background.brighter() color. It also paints the same text using the + * background.darker() color one pixel to the right and one pixel down. + * + * @param l The {@link JLabel} being painted. + * @param g The {@link Graphics} object to paint with. + * @param s The String to paint. + * @param textX The x coordinate of the start of the baseline. + * @param textY The y coordinate of the start of the baseline. + */ + protected void paintDisabledText(JLabel l, Graphics g, String s, int textX, + int textY) + { + Color saved_color = g.getColor(); + + g.setColor(l.getBackground().brighter()); + + int mnemIndex = l.getDisplayedMnemonicIndex(); + + if (mnemIndex != -1) + BasicGraphicsUtils.drawStringUnderlineCharAt(g, s, mnemIndex, textX, + textY); + else + g.drawString(s, textX, textY); + + g.setColor(l.getBackground().darker()); + if (mnemIndex != -1) + BasicGraphicsUtils.drawStringUnderlineCharAt(g, s, mnemIndex, textX + 1, + textY + 1); + else + g.drawString(s, textX + 1, textY + 1); + + g.setColor(saved_color); + } + + /** + * Paints the text if the label is enabled. The text is painted using the + * foreground color. + * + * @param l The {@link JLabel} being painted. + * @param g The {@link Graphics} object to paint with. + * @param s The String to paint. + * @param textX The x coordinate of the start of the baseline. + * @param textY The y coordinate of the start of the baseline. + */ + protected void paintEnabledText(JLabel l, Graphics g, String s, int textX, + int textY) + { + Color saved_color = g.getColor(); + g.setColor(l.getForeground()); + + int mnemIndex = l.getDisplayedMnemonicIndex(); + + if (mnemIndex != -1) + BasicGraphicsUtils.drawStringUnderlineCharAt(g, s, mnemIndex, textX, + textY); + else + g.drawString(s, textX, textY); + + g.setColor(saved_color); + } + + /** + * This method installs the UI for the given {@link JComponent}. This + * method will install the component, defaults, listeners, and keyboard + * actions. + * + * @param c The {@link JComponent} that this UI is being installed on. + */ + public void installUI(JComponent c) + { + super.installUI(c); + if (c instanceof JLabel) + { + JLabel l = (JLabel) c; + + installComponents(l); + installDefaults(l); + installListeners(l); + installKeyboardActions(l); + } + } + + /** + * This method uninstalls the UI for the given {@link JComponent}. This + * method will uninstall the component, defaults, listeners, and keyboard + * actions. + * + * @param c The {@link JComponent} that this UI is being installed on. + */ + public void uninstallUI(JComponent c) + { + super.uninstallUI(c); + if (c instanceof JLabel) + { + JLabel l = (JLabel) c; + + uninstallKeyboardActions(l); + uninstallListeners(l); + uninstallDefaults(l); + uninstallComponents(l); + } + } + + /** + * This method installs the components for this {@link JLabel}. + * + * @param c The {@link JLabel} to install components for. + */ + protected void installComponents(JLabel c) + { + //FIXME: fix javadoc + implement. + } + + /** + * This method uninstalls the components for this {@link JLabel}. + * + * @param c The {@link JLabel} to uninstall components for. + */ + protected void uninstallComponents(JLabel c) + { + //FIXME: fix javadoc + implement. + } + + /** + * This method installs the defaults that are defined in the Basic look and + * feel for this {@link JLabel}. + * + * @param c The {@link JLabel} to install defaults for. + */ + protected void installDefaults(JLabel c) + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + c.setForeground(defaults.getColor("Label.foreground")); + c.setBackground(defaults.getColor("Label.background")); + c.setFont(defaults.getFont("Label.font")); + //XXX: There are properties we don't use called disabledForeground + //and disabledShadow. + } + + /** + * This method uninstalls the defaults that are defined in the Basic look + * and feel for this {@link JLabel}. + * + * @param c The {@link JLabel} to uninstall defaults for. + */ + protected void uninstallDefaults(JLabel c) + { + c.setForeground(null); + c.setBackground(null); + c.setFont(null); + } + + /** + * This method installs the keyboard actions for the given {@link JLabel}. + * + * @param l The {@link JLabel} to install keyboard actions for. + */ + protected void installKeyboardActions(JLabel l) + { + //FIXME: implement. + } + + /** + * This method uninstalls the keyboard actions for the given {@link JLabel}. + * + * @param l The {@link JLabel} to uninstall keyboard actions for. + */ + protected void uninstallKeyboardActions(JLabel l) + { + //FIXME: implement. + } + + /** + * This method installs the listeners for the given {@link JLabel}. The UI + * delegate only listens to the label. + * + * @param c The {@link JLabel} to install listeners for. + */ + protected void installListeners(JLabel c) + { + c.addPropertyChangeListener(this); + } + + /** + * This method uninstalls the listeners for the given {@link JLabel}. The UI + * delegate only listens to the label. + * + * @param c The {@link JLabel} to uninstall listeners for. + */ + protected void uninstallListeners(JLabel c) + { + c.removePropertyChangeListener(this); + } + + /** + * This method is called whenever any JLabel's that use this UI has one of + * their properties change. + * + * @param e The {@link PropertyChangeEvent} that describes the change. + */ + public void propertyChange(PropertyChangeEvent e) + { + JLabel c = (JLabel) e.getSource(); + c.revalidate(); + c.repaint(); + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicListUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicListUI.java new file mode 100644 index 0000000..24c6cd2 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicListUI.java @@ -0,0 +1,1004 @@ +/* BasicListUI.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.CellRendererPane; +import javax.swing.JComponent; +import javax.swing.JList; +import javax.swing.JViewport; +import javax.swing.ListCellRenderer; +import javax.swing.ListModel; +import javax.swing.ListSelectionModel; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import javax.swing.event.MouseInputListener; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.ListUI; + +/** + * The Basic Look and Feel UI delegate for the + * JList. + */ +public class BasicListUI extends ListUI +{ + + /** + * A helper class which listens for {@link ComponentEvent}s from + * the JList. + */ + private class ComponentHandler extends ComponentAdapter { + + /** + * Called when the component is hidden. Invalidates the internal + * layout. + */ + public void componentResized(ComponentEvent ev) { + BasicListUI.this.damageLayout(); + } + } + + /** + * A helper class which listens for {@link FocusEvent}s + * from the JList. + */ + public class FocusHandler implements FocusListener + { + /** + * Called when the JList acquires focus. + * + * @param e The FocusEvent representing focus acquisition + */ + public void focusGained(FocusEvent e) + { + repaintCellFocus(); + } + + /** + * Called when the JList loses focus. + * + * @param e The FocusEvent representing focus loss + */ + public void focusLost(FocusEvent e) + { + repaintCellFocus(); + } + + /** + * Helper method to repaint the focused cell's + * lost or acquired focus state. + */ + void repaintCellFocus() + { + } + } + + /** + * A helper class which listens for {@link ListDataEvent}s generated by + * the {@link JList}'s {@link ListModel}. + * + * @see javax.swing.JList#getModel() + */ + public class ListDataHandler implements ListDataListener + { + /** + * Called when a general change has happened in the model which cannot + * be represented in terms of a simple addition or deletion. + * + * @param e The event representing the change + */ + public void contentsChanged(ListDataEvent e) + { + BasicListUI.this.damageLayout(); + } + + /** + * Called when an interval of objects has been added to the model. + * + * @param e The event representing the addition + */ + public void intervalAdded(ListDataEvent e) + { + BasicListUI.this.damageLayout(); + } + + /** + * Called when an inteval of objects has been removed from the model. + * + * @param e The event representing the removal + */ + public void intervalRemoved(ListDataEvent e) + { + BasicListUI.this.damageLayout(); + } + } + + /** + * A helper class which listens for {@link ListSelectionEvent}s + * from the {@link JList}'s {@link ListSelectionModel}. + */ + public class ListSelectionHandler implements ListSelectionListener + { + /** + * Called when the list selection changes. + * + * @param e The event representing the change + */ + public void valueChanged(ListSelectionEvent e) + { + } + } + + /** + * A helper class which listens for {@link KeyEvents}s + * from the {@link JList}. + */ + private class KeyHandler extends KeyAdapter + { + public KeyHandler() + { + } + + public void keyPressed( KeyEvent evt ) + { + int lead = BasicListUI.this.list.getLeadSelectionIndex(); + int max = BasicListUI.this.list.getModel().getSize() - 1; + // Do nothing if list is empty + if (max == -1) + return; + + // Process the key event. Bindings can be found in + // javax.swing.plaf.basic.BasicLookAndFeel.java + if ((evt.getKeyCode() == KeyEvent.VK_DOWN) + || (evt.getKeyCode() == KeyEvent.VK_KP_DOWN)) + { + if (!evt.isShiftDown()) + { + BasicListUI.this.list.clearSelection(); + BasicListUI.this.list.setSelectedIndex(Math.min(lead+1,max)); + } + else + { + BasicListUI.this.list.getSelectionModel(). + setLeadSelectionIndex(Math.min(lead+1,max)); + } + } + else if ((evt.getKeyCode() == KeyEvent.VK_UP) + || (evt.getKeyCode() == KeyEvent.VK_KP_UP)) + { + if (!evt.isShiftDown()) + { + BasicListUI.this.list.clearSelection(); + BasicListUI.this.list.setSelectedIndex(Math.max(lead-1,0)); + } + else + { + BasicListUI.this.list.getSelectionModel(). + setLeadSelectionIndex(Math.max(lead-1,0)); + } + } + else if (evt.getKeyCode() == KeyEvent.VK_PAGE_UP) + { + // FIXME: implement, need JList.ensureIndexIsVisible to work + } + else if (evt.getKeyCode() == KeyEvent.VK_PAGE_DOWN) + { + // FIXME: implement, need JList.ensureIndexIsVisible to work + } + else if (evt.getKeyCode() == KeyEvent.VK_BACK_SLASH + && evt.isControlDown()) + { + BasicListUI.this.list.clearSelection(); + } + else if ((evt.getKeyCode() == KeyEvent.VK_HOME) + || evt.getKeyCode() == KeyEvent.VK_END) + { + // index is either 0 for HOME, or last cell for END + int index = (evt.getKeyCode() == KeyEvent.VK_HOME) ? 0 : max; + + if (!evt.isShiftDown() ||(BasicListUI.this.list.getSelectionMode() + == ListSelectionModel.SINGLE_SELECTION)) + BasicListUI.this.list.setSelectedIndex(index); + else if (BasicListUI.this.list.getSelectionMode() == + ListSelectionModel.SINGLE_INTERVAL_SELECTION) + BasicListUI.this.list.setSelectionInterval + (BasicListUI.this.list.getAnchorSelectionIndex(), index); + else + BasicListUI.this.list.getSelectionModel(). + setLeadSelectionIndex(index); + } + else if ((evt.getKeyCode() == KeyEvent.VK_A || evt.getKeyCode() + == KeyEvent.VK_SLASH) && evt.isControlDown()) + { + BasicListUI.this.list.setSelectionInterval(0, max); + } + else if (evt.getKeyCode() == KeyEvent.VK_SPACE && evt.isControlDown()) + { + BasicListUI.this.list.getSelectionModel(). + setLeadSelectionIndex(Math.min(lead+1,max)); + } + + } + } + + /** + * A helper class which listens for {@link MouseEvent}s + * from the {@link JList}. + */ + public class MouseInputHandler implements MouseInputListener + { + /** + * Called when a mouse button press/release cycle completes + * on the {@link JList} + * + * @param event The event representing the mouse click + */ + public void mouseClicked(MouseEvent event) + { + Point click = event.getPoint(); + int index = BasicListUI.this.locationToIndex(list, click); + if (index == -1) + return; + if (event.isControlDown()) + { + if (BasicListUI.this.list.getSelectionMode() == + ListSelectionModel.SINGLE_SELECTION) + BasicListUI.this.list.setSelectedIndex(index); + else if (BasicListUI.this.list.isSelectedIndex(index)) + BasicListUI.this.list.removeSelectionInterval(index,index); + else + BasicListUI.this.list.addSelectionInterval(index,index); + } + else if (event.isShiftDown()) + { + if (BasicListUI.this.list.getSelectionMode() == + ListSelectionModel.SINGLE_SELECTION) + BasicListUI.this.list.setSelectedIndex(index); + else if (BasicListUI.this.list.getSelectionMode() == + ListSelectionModel.SINGLE_INTERVAL_SELECTION) + // COMPAT: the IBM VM is compatible with the following line of code. + // However, compliance with Sun's VM would correspond to replacing + // getAnchorSelectionIndex() with getLeadSelectionIndex().This is + // both unnatural and contradictory to the way they handle other + // similar UI interactions. + BasicListUI.this.list.setSelectionInterval + (BasicListUI.this.list.getAnchorSelectionIndex(), index); + else + // COMPAT: both Sun and IBM are compatible instead with: + // BasicListUI.this.list.setSelectionInterval + // (BasicListUI.this.list.getLeadSelectionIndex(),index); + // Note that for IBM this is contradictory to what they did in + // the above situation for SINGLE_INTERVAL_SELECTION. + // The most natural thing to do is the following: + BasicListUI.this.list.getSelectionModel(). + setLeadSelectionIndex(index); + } + else + BasicListUI.this.list.setSelectedIndex(index); + } + + /** + * Called when a mouse button is pressed down on the + * {@link JList}. + * + * @param event The event representing the mouse press + */ + public void mousePressed(MouseEvent event) + { + } + + /** + * Called when a mouse button is released on + * the {@link JList} + * + * @param event The event representing the mouse press + */ + public void mouseReleased(MouseEvent event) + { + } + + /** + * Called when the mouse pointer enters the area bounded + * by the {@link JList} + * + * @param event The event representing the mouse entry + */ + public void mouseEntered(MouseEvent event) + { + } + + /** + * Called when the mouse pointer leaves the area bounded + * by the {@link JList} + * + * @param event The event representing the mouse exit + */ + public void mouseExited(MouseEvent event) + { + } + + /** + * Called when the mouse pointer moves over the area bounded + * by the {@link JList} while a button is held down. + * + * @param event The event representing the mouse drag + */ + public void mouseDragged(MouseEvent event) + { + } + + /** + * Called when the mouse pointer moves over the area bounded + * by the {@link JList}. + * + * @param event The event representing the mouse move + */ + public void mouseMoved(MouseEvent event) + { + } + } + + /** + * Helper class which listens to {@link PropertyChangeEvent}s + * from the {@link JList}. + */ + public class PropertyChangeHandler implements PropertyChangeListener + { + /** + * Called when the {@link JList} changes one of its bound properties. + * + * @param e The event representing the property change + */ + public void propertyChange(PropertyChangeEvent e) + { + if (e.getSource() == BasicListUI.this.list) + { + if (e.getOldValue() != null && e.getOldValue() instanceof ListModel) + ((ListModel) e.getOldValue()).removeListDataListener(BasicListUI.this.listDataListener); + + if (e.getNewValue() != null && e.getNewValue() instanceof ListModel) + ((ListModel) e.getNewValue()).addListDataListener(BasicListUI.this.listDataListener); + } + BasicListUI.this.damageLayout(); + } + } + + /** + * Creates a new BasicListUI for the component. + * + * @param c The component to create a UI for + * + * @return A new UI + */ + public static ComponentUI createUI(final JComponent c) + { + return new BasicListUI(); + } + + /** The current focus listener. */ + protected FocusListener focusListener; + + /** The data listener listening to the model. */ + protected ListDataListener listDataListener; + + /** The selection listener listening to the selection model. */ + protected ListSelectionListener listSelectionListener; + + /** The mouse listener listening to the list. */ + protected MouseInputListener mouseInputListener; + + /** The key listener listening to the list */ + private KeyHandler keyListener; + + /** The property change listener listening to the list. */ + protected PropertyChangeListener propertyChangeListener; + + + /** The component listener that receives notification for resizing the + * JList component.*/ + private ComponentListener componentListener; + + /** Saved reference to the list this UI was created for. */ + protected JList list; + + /** The height of a single cell in the list. */ + protected int cellHeight; + + /** The width of a single cell in the list. */ + protected int cellWidth; + + /** + * An array of varying heights of cells in the list, in cases where each + * cell might have a different height. + */ + protected int[] cellHeights; + + /** + * A simple counter. When nonzero, indicates that the UI class is out of + * date with respect to the underlying list, and must recalculate the + * list layout before painting or performing size calculations. + */ + protected int updateLayoutStateNeeded; + + /** + * The {@link CellRendererPane} that is used for painting. + */ + protected CellRendererPane rendererPane; + + /** + * Calculate the height of a particular row. If there is a fixed {@link + * #cellHeight}, return it; otherwise return the specific row height + * requested from the {@link #cellHeights} array. If the requested row + * is invalid, return <code>-1</code>. + * + * @param row The row to get the height of + * + * @return The height, in pixels, of the specified row + */ + protected int getRowHeight(int row) + { + if (row < 0 || row >= cellHeights.length) + return -1; + else if (cellHeight != -1) + return cellHeight; + else + return cellHeights[row]; + } + + /** + * Calculate the bounds of a particular cell, considering the upper left + * corner of the list as the origin position <code>(0,0)</code>. + * + * @param l Ignored; calculates over <code>this.list</code> + * @param index1 The first row to include in the bounds + * @param index2 The last row to incude in the bounds + * + * @return A rectangle encompassing the range of rows between + * <code>index1</code> and <code>index2</code> inclusive + */ + public Rectangle getCellBounds(JList l, int index1, int index2) + { + maybeUpdateLayoutState(); + + if (l != list || cellWidth == -1) + return null; + + int minIndex = Math.min(index1, index2); + int maxIndex = Math.max(index1, index2); + Point loc = indexToLocation(list, minIndex); + Rectangle bounds = new Rectangle(loc.x, loc.y, cellWidth, + getRowHeight(minIndex)); + + for (int i = minIndex + 1; i <= maxIndex; i++) + { + Point hiLoc = indexToLocation(list, i); + Rectangle hibounds = new Rectangle(hiLoc.x, hiLoc.y, cellWidth, + getRowHeight(i)); + bounds = bounds.union(hibounds); + } + + return bounds; + } + + /** + * Calculate the Y coordinate of the upper edge of a particular row, + * considering the Y coordinate <code>0</code> to occur at the top of the + * list. + * + * @param row The row to calculate the Y coordinate of + * + * @return The Y coordinate of the specified row, or <code>-1</code> if + * the specified row number is invalid + */ + protected int convertRowToY(int row) + { + int y = 0; + for (int i = 0; i < row; ++i) + { + int h = getRowHeight(i); + if (h == -1) + return -1; + y += h; + } + return y; + } + + /** + * Calculate the row number containing a particular Y coordinate, + * considering the Y coodrinate <code>0</code> to occur at the top of the + * list. + * + * @param y0 The Y coordinate to calculate the row number for + * + * @return The row number containing the specified Y value, or <code>-1</code> + * if the specified Y coordinate is invalid + */ + protected int convertYToRow(int y0) + { + for (int row = 0; row < cellHeights.length; ++row) + { + int h = getRowHeight(row); + + if (y0 < h) + return row; + y0 -= h; + } + return -1; + } + + /** + * Recomputes the {@link #cellHeights}, {@link #cellHeight}, and {@link + * #cellWidth} properties by examining the variouis properties of the + * {@link JList}. + */ + protected void updateLayoutState() + { + int nrows = list.getModel().getSize(); + cellHeight = -1; + cellWidth = -1; + if (cellHeights == null || cellHeights.length != nrows) + cellHeights = new int[nrows]; + if (list.getFixedCellHeight() == -1 || list.getFixedCellWidth() == -1) + { + ListCellRenderer rend = list.getCellRenderer(); + for (int i = 0; i < nrows; ++i) + { + Component flyweight = rend.getListCellRendererComponent(list, + list.getModel() + .getElementAt(i), + 0, false, + false); + Dimension dim = flyweight.getPreferredSize(); + cellHeights[i] = dim.height; + // compute average cell height (little hack here) + cellHeight = (cellHeight * i + cellHeights[i]) / (i + 1); + cellWidth = Math.max(cellWidth, dim.width); + if (list.getLayoutOrientation() == JList.VERTICAL) + cellWidth = Math.max(cellWidth, list.getSize().width); + } + } + else + { + cellHeight = list.getFixedCellHeight(); + cellWidth = list.getFixedCellWidth(); + } + } + + /** + * Marks the current layout as damaged and requests revalidation from the + * JList. + * This is package-private to avoid an accessor method. + * + * @see #updateLayoutStateNeeded + */ + void damageLayout() + { + updateLayoutStateNeeded = 1; + } + + /** + * Calls {@link #updateLayoutState} if {@link #updateLayoutStateNeeded} + * is nonzero, then resets {@link #updateLayoutStateNeeded} to zero. + */ + protected void maybeUpdateLayoutState() + { + if (updateLayoutStateNeeded != 0) + { + updateLayoutState(); + updateLayoutStateNeeded = 0; + } + } + + /** + * Creates a new BasicListUI object. + */ + public BasicListUI() + { + focusListener = new FocusHandler(); + listDataListener = new ListDataHandler(); + listSelectionListener = new ListSelectionHandler(); + mouseInputListener = new MouseInputHandler(); + keyListener = new KeyHandler(); + propertyChangeListener = new PropertyChangeHandler(); + componentListener = new ComponentHandler(); + updateLayoutStateNeeded = 1; + rendererPane = new CellRendererPane(); + } + + /** + * Installs various default settings (mostly colors) from the {@link + * UIDefaults} into the {@link JList} + * + * @see #uninstallDefaults + */ + protected void installDefaults() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + list.setForeground(defaults.getColor("List.foreground")); + list.setBackground(defaults.getColor("List.background")); + list.setSelectionForeground(defaults.getColor("List.selectionForeground")); + list.setSelectionBackground(defaults.getColor("List.selectionBackground")); + list.setOpaque(true); + } + + /** + * Resets to <code>null</code> those defaults which were installed in + * {@link #installDefaults} + */ + protected void uninstallDefaults() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + list.setForeground(null); + list.setBackground(null); + list.setSelectionForeground(null); + list.setSelectionBackground(null); + } + + /** + * Attaches all the listeners we have in the UI class to the {@link + * JList}, its model and its selection model. + * + * @see #uninstallListeners + */ + protected void installListeners() + { + list.addFocusListener(focusListener); + list.getModel().addListDataListener(listDataListener); + list.addListSelectionListener(listSelectionListener); + list.addMouseListener(mouseInputListener); + list.addKeyListener(keyListener); + list.addMouseMotionListener(mouseInputListener); + list.addPropertyChangeListener(propertyChangeListener); + list.addComponentListener(componentListener); + } + + /** + * Detaches all the listeners we attached in {@link #installListeners}. + */ + protected void uninstallListeners() + { + list.removeFocusListener(focusListener); + list.getModel().removeListDataListener(listDataListener); + list.removeListSelectionListener(listSelectionListener); + list.removeMouseListener(mouseInputListener); + list.removeKeyListener(keyListener); + list.removeMouseMotionListener(mouseInputListener); + list.removePropertyChangeListener(propertyChangeListener); + } + + /** + * Installs keyboard actions for this UI in the {@link JList}. + */ + protected void installKeyboardActions() + { + } + + /** + * Uninstalls keyboard actions for this UI in the {@link JList}. + */ + protected void uninstallKeyboardActions() + { + } + + /** + * Installs the various aspects of the UI in the {@link JList}. In + * particular, calls {@link #installDefaults}, {@link #installListeners} + * and {@link #installKeyboardActions}. Also saves a reference to the + * provided component, cast to a {@link JList}. + * + * @param c The {@link JList} to install the UI into + */ + public void installUI(final JComponent c) + { + super.installUI(c); + list = (JList) c; + installDefaults(); + installListeners(); + installKeyboardActions(); + maybeUpdateLayoutState(); + } + + /** + * Uninstalls all the aspects of the UI which were installed in {@link + * #installUI}. When finished uninstalling, drops the saved reference to + * the {@link JList}. + * + * @param c Ignored; the UI is uninstalled from the {@link JList} + * reference saved during the call to {@link #installUI} + */ + public void uninstallUI(final JComponent c) + { + uninstallKeyboardActions(); + uninstallListeners(); + uninstallDefaults(); + list = null; + } + + /** + * Gets the size this list would prefer to assume. This is calculated by + * calling {@link #getCellBounds} over the entire list. + * + * @param c Ignored; uses the saved {@link JList} reference + * + * @return DOCUMENT ME! + */ + public Dimension getPreferredSize(JComponent c) + { + int size = list.getModel().getSize(); + if (size == 0) + return new Dimension(0, 0); + int visibleRows = list.getVisibleRowCount(); + int layoutOrientation = list.getLayoutOrientation(); + Rectangle bounds = getCellBounds(list, 0, list.getModel().getSize() - 1); + Dimension retVal = bounds.getSize(); + Component parent = list.getParent(); + if ((visibleRows == -1) && (parent instanceof JViewport)) + { + JViewport viewport = (JViewport) parent; + + if (layoutOrientation == JList.HORIZONTAL_WRAP) + { + int h = viewport.getSize().height; + int cellsPerCol = h / cellHeight; + int w = size / cellsPerCol * cellWidth; + retVal = new Dimension(w, h); + } + else if (layoutOrientation == JList.VERTICAL_WRAP) + { + int w = viewport.getSize().width; + int cellsPerRow = Math.max(w / cellWidth, 1); + int h = size / cellsPerRow * cellHeight; + retVal = new Dimension(w, h); + } + } + return retVal; + } + + /** + * Paints the packground of the list using the background color + * of the specified component. + * + * @param g The graphics context to paint in + * @param c The component to paint the background of + */ + private void paintBackground(Graphics g, JComponent c) + { + Dimension size = getPreferredSize(c); + Color save = g.getColor(); + g.setColor(c.getBackground()); + g.fillRect(0, 0, size.width, size.height); + g.setColor(save); + } + + /** + * Paints a single cell in the list. + * + * @param g The graphics context to paint in + * @param row The row number to paint + * @param bounds The bounds of the cell to paint, assuming a coordinate + * system beginning at <code>(0,0)</code> in the upper left corner of the + * list + * @param rend A cell renderer to paint with + * @param data The data to provide to the cell renderer + * @param sel A selection model to provide to the cell renderer + * @param lead The lead selection index of the list + */ + protected void paintCell(Graphics g, int row, Rectangle bounds, + ListCellRenderer rend, ListModel data, + ListSelectionModel sel, int lead) + { + boolean is_sel = list.isSelectedIndex(row); + boolean has_focus = false; + Component comp = rend.getListCellRendererComponent(list, + data.getElementAt(row), + 0, is_sel, has_focus); + //comp.setBounds(new Rectangle(0, 0, bounds.width, bounds.height)); + //comp.paint(g); + rendererPane.paintComponent(g, comp, list, bounds); + } + + /** + * Paints the list by calling {@link #paintBackground} and then repeatedly + * calling {@link #paintCell} for each visible cell in the list. + * + * @param g The graphics context to paint with + * @param c Ignored; uses the saved {@link JList} reference + */ + public void paint(Graphics g, JComponent c) + { + int nrows = list.getModel().getSize(); + if (nrows == 0) + return; + + maybeUpdateLayoutState(); + ListCellRenderer render = list.getCellRenderer(); + ListModel model = list.getModel(); + ListSelectionModel sel = list.getSelectionModel(); + int lead = sel.getLeadSelectionIndex(); + Rectangle clip = g.getClipBounds(); + paintBackground(g, list); + + for (int row = 0; row < nrows; ++row) + { + Rectangle bounds = getCellBounds(list, row, row); + if (bounds.intersects(clip)) + paintCell(g, row, bounds, render, model, sel, lead); + } + } + + /** + * Computes the index of a list cell given a point within the list. + * + * @param list the list which on which the computation is based on + * @param location the coordinates + * + * @return the index of the list item that is located at the given + * coordinates or <code>null</code> if the location is invalid + */ + public int locationToIndex(JList list, Point location) + { + int layoutOrientation = list.getLayoutOrientation(); + int index = -1; + switch (layoutOrientation) + { + case JList.VERTICAL: + index = convertYToRow(location.y); + break; + case JList.HORIZONTAL_WRAP: + // determine visible rows and cells per row + int visibleRows = list.getVisibleRowCount(); + int cellsPerRow = -1; + int numberOfItems = list.getModel().getSize(); + Dimension listDim = list.getSize(); + if (visibleRows <= 0) + { + try + { + cellsPerRow = listDim.width / cellWidth; + } + catch (ArithmeticException ex) + { + cellsPerRow = 1; + } + } + else + { + cellsPerRow = numberOfItems / visibleRows + 1; + } + + // determine index for the given location + int cellsPerColumn = numberOfItems / cellsPerRow + 1; + int gridX = Math.min(location.x / cellWidth, cellsPerRow - 1); + int gridY = Math.min(location.y / cellHeight, cellsPerColumn); + index = gridX + gridY * cellsPerRow; + break; + case JList.VERTICAL_WRAP: + // determine visible rows and cells per column + int visibleRows2 = list.getVisibleRowCount(); + if (visibleRows2 <= 0) + { + Dimension listDim2 = list.getSize(); + visibleRows2 = listDim2.height / cellHeight; + } + int numberOfItems2 = list.getModel().getSize(); + int cellsPerRow2 = numberOfItems2 / visibleRows2 + 1; + + Dimension listDim2 = list.getSize(); + int gridX2 = Math.min(location.x / cellWidth, cellsPerRow2 - 1); + int gridY2 = Math.min(location.y / cellHeight, visibleRows2); + index = gridY2 + gridX2 * visibleRows2; + break; + } + return index; + } + + public Point indexToLocation(JList list, int index) + { + int layoutOrientation = list.getLayoutOrientation(); + Point loc = null; + switch (layoutOrientation) + { + case JList.VERTICAL: + loc = new Point(0, convertRowToY(index)); + break; + case JList.HORIZONTAL_WRAP: + // determine visible rows and cells per row + int visibleRows = list.getVisibleRowCount(); + int numberOfCellsPerRow = -1; + if (visibleRows <= 0) + { + Dimension listDim = list.getSize(); + numberOfCellsPerRow = Math.max(listDim.width / cellWidth, 1); + } + else + { + int numberOfItems = list.getModel().getSize(); + numberOfCellsPerRow = numberOfItems / visibleRows + 1; + } + // compute coordinates inside the grid + int gridX = index % numberOfCellsPerRow; + int gridY = index / numberOfCellsPerRow; + int locX = gridX * cellWidth; + int locY = gridY * cellHeight; + loc = new Point(locX, locY); + break; + case JList.VERTICAL_WRAP: + // determine visible rows and cells per column + int visibleRows2 = list.getVisibleRowCount(); + if (visibleRows2 <= 0) + { + Dimension listDim2 = list.getSize(); + visibleRows2 = listDim2.height / cellHeight; + } + // compute coordinates inside the grid + if (visibleRows2 > 0) + { + int gridY2 = index % visibleRows2; + int gridX2 = index / visibleRows2; + int locX2 = gridX2 * cellWidth; + int locY2 = gridY2 * cellHeight; + loc = new Point(locX2, locY2); + } + else + loc = new Point(0, convertRowToY(index)); + break; + } + return loc; + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicLookAndFeel.java b/libjava/classpath/javax/swing/plaf/basic/BasicLookAndFeel.java new file mode 100644 index 0000000..14fe28f --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicLookAndFeel.java @@ -0,0 +1,1058 @@ +/* BasicLookAndFeel.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.io.Serializable; +import java.util.Enumeration; +import java.util.ResourceBundle; + +import javax.swing.BorderFactory; +import javax.swing.KeyStroke; +import javax.swing.LookAndFeel; +import javax.swing.UIDefaults; +import javax.swing.border.BevelBorder; +import javax.swing.border.Border; +import javax.swing.plaf.BorderUIResource; +import javax.swing.plaf.ColorUIResource; +import javax.swing.plaf.DimensionUIResource; +import javax.swing.plaf.FontUIResource; +import javax.swing.plaf.InsetsUIResource; +import javax.swing.text.JTextComponent; + +/** + * BasicLookAndFeel + * @author Andrew Selkirk + */ +public abstract class BasicLookAndFeel extends LookAndFeel + implements Serializable +{ + static final long serialVersionUID = -6096995660290287879L; + + /** + * Creates a new instance of the Basic look and feel. + */ + public BasicLookAndFeel() + { + // TODO + } + + /** + * Creates and returns a new instance of the default resources for this look + * and feel. + * + * @return The UI defaults. + */ + public UIDefaults getDefaults() + { + // Variables + UIDefaults def = new UIDefaults(); + // Initialize Class Defaults + initClassDefaults(def); + // Initialize System Colour Defaults + initSystemColorDefaults(def); + // Initialize Component Defaults + initComponentDefaults(def); + // Return UI Defaults + return def; + } + + /** + * Populates the <code>defaults</code> table with mappings between class IDs + * and fully qualified class names for the UI delegates. + * + * @param defaults the defaults table (<code>null</code> not permitted). + */ + protected void initClassDefaults(UIDefaults defaults) + { + // Variables + Object[] uiDefaults; + // Initialize Class Defaults + uiDefaults = new Object[] { + "ButtonUI", "javax.swing.plaf.basic.BasicButtonUI", + "CheckBoxMenuItemUI", "javax.swing.plaf.basic.BasicCheckBoxMenuItemUI", + "CheckBoxUI", "javax.swing.plaf.basic.BasicCheckBoxUI", + "ColorChooserUI", "javax.swing.plaf.basic.BasicColorChooserUI", + "ComboBoxUI", "javax.swing.plaf.basic.BasicComboBoxUI", + "DesktopIconUI", "javax.swing.plaf.basic.BasicDesktopIconUI", + "DesktopPaneUI", "javax.swing.plaf.basic.BasicDesktopPaneUI", + "EditorPaneUI", "javax.swing.plaf.basic.BasicEditorPaneUI", + "FileChooserUI", "javax.swing.plaf.basic.BasicFileChooserUI", + "FormattedTextFieldUI", "javax.swing.plaf.basic.BasicFormattedTextFieldUI", + "InternalFrameUI", "javax.swing.plaf.basic.BasicInternalFrameUI", + "LabelUI", "javax.swing.plaf.basic.BasicLabelUI", + "ListUI", "javax.swing.plaf.basic.BasicListUI", + "MenuBarUI", "javax.swing.plaf.basic.BasicMenuBarUI", + "MenuItemUI", "javax.swing.plaf.basic.BasicMenuItemUI", + "MenuUI", "javax.swing.plaf.basic.BasicMenuUI", + "OptionPaneUI", "javax.swing.plaf.basic.BasicOptionPaneUI", + "PanelUI", "javax.swing.plaf.basic.BasicPanelUI", + "PasswordFieldUI", "javax.swing.plaf.basic.BasicPasswordFieldUI", + "PopupMenuSeparatorUI", "javax.swing.plaf.basic.BasicPopupMenuSeparatorUI", + "PopupMenuUI", "javax.swing.plaf.basic.BasicPopupMenuUI", + "ProgressBarUI", "javax.swing.plaf.basic.BasicProgressBarUI", + "RadioButtonMenuItemUI", "javax.swing.plaf.basic.BasicRadioButtonMenuItemUI", + "RadioButtonUI", "javax.swing.plaf.basic.BasicRadioButtonUI", + "RootPaneUI", "javax.swing.plaf.basic.BasicRootPaneUI", + "ScrollBarUI", "javax.swing.plaf.basic.BasicScrollBarUI", + "ScrollPaneUI", "javax.swing.plaf.basic.BasicScrollPaneUI", + "SeparatorUI", "javax.swing.plaf.basic.BasicSeparatorUI", + "SliderUI", "javax.swing.plaf.basic.BasicSliderUI", + "SplitPaneUI", "javax.swing.plaf.basic.BasicSplitPaneUI", + "SpinnerUI", "javax.swing.plaf.basic.BasicSpinnerUI", + "StandardDialogUI", "javax.swing.plaf.basic.BasicStandardDialogUI", + "TabbedPaneUI", "javax.swing.plaf.basic.BasicTabbedPaneUI", + "TableHeaderUI", "javax.swing.plaf.basic.BasicTableHeaderUI", + "TableUI", "javax.swing.plaf.basic.BasicTableUI", + "TextPaneUI", "javax.swing.plaf.basic.BasicTextPaneUI", + "TextAreaUI", "javax.swing.plaf.basic.BasicTextAreaUI", + "TextFieldUI", "javax.swing.plaf.basic.BasicTextFieldUI", + "TextPaneUI", "javax.swing.plaf.basic.BasicTextPaneUI", + "ToggleButtonUI", "javax.swing.plaf.basic.BasicToggleButtonUI", + "ToolBarSeparatorUI", "javax.swing.plaf.basic.BasicToolBarSeparatorUI", + "ToolBarUI", "javax.swing.plaf.basic.BasicToolBarUI", + "ToolTipUI", "javax.swing.plaf.basic.BasicToolTipUI", + "TreeUI", "javax.swing.plaf.basic.BasicTreeUI", + "ViewportUI", "javax.swing.plaf.basic.BasicViewportUI" + }; + // Add Class Defaults to UI Defaults table + defaults.putDefaults(uiDefaults); + } + + /** + * Populates the <code>defaults</code> table with system color defaults. + * + * @param defaults the defaults table (<code>null</code> not permitted). + */ + protected void initSystemColorDefaults(UIDefaults defaults) + { + Color highLight = new Color(249, 247, 246); + Color light = new Color(239, 235, 231); + Color shadow = new Color(139, 136, 134); + Color darkShadow = new Color(16, 16, 16); + + Object[] uiDefaults; + uiDefaults = new Object[] { + "activeCaption", new ColorUIResource(0, 0, 128), + "activeCaptionBorder", new ColorUIResource(Color.lightGray), + "activeCaptionText", new ColorUIResource(Color.white), + "control", new ColorUIResource(light), + "controlDkShadow", new ColorUIResource(shadow), + "controlHighlight", new ColorUIResource(highLight), + "controlLtHighlight", new ColorUIResource(highLight), + "controlShadow", new ColorUIResource(shadow), + "controlText", new ColorUIResource(darkShadow), + "desktop", new ColorUIResource(0, 92, 92), + "inactiveCaption", new ColorUIResource(Color.gray), + "inactiveCaptionBorder", new ColorUIResource(Color.lightGray), + "inactiveCaptionText", new ColorUIResource(Color.lightGray), + "info", new ColorUIResource(light), + "infoText", new ColorUIResource(darkShadow), + "menu", new ColorUIResource(light), + "menuText", new ColorUIResource(darkShadow), + "scrollbar", new ColorUIResource(light), + "text", new ColorUIResource(Color.white), + "textHighlight", new ColorUIResource(Color.black), + "textHighlightText", new ColorUIResource(Color.white), + "textInactiveText", new ColorUIResource(Color.gray), + "textText", new ColorUIResource(Color.black), + "window", new ColorUIResource(light), + "windowBorder", new ColorUIResource(Color.black), + "windowText", new ColorUIResource(darkShadow) + }; + defaults.putDefaults(uiDefaults); + } + + /** + * Loads the system colors. This method is not implemented yet. + * + * @param defaults the defaults table (<code>null</code> not permitted). + * @param systemColors TODO + * @param useNative TODO + */ + protected void loadSystemColors(UIDefaults defaults, String[] systemColors, + boolean useNative) + { + // TODO + } + + /** + * loadResourceBundle + * @param defaults TODO + */ + private void loadResourceBundle(UIDefaults defaults) + { + ResourceBundle bundle; + Enumeration e; + String key; + String value; + bundle = ResourceBundle.getBundle("resources/basic"); + // Process Resources + e = bundle.getKeys(); + while (e.hasMoreElements()) + { + key = (String) e.nextElement(); + value = bundle.getString(key); + defaults.put(key, value); + } + } + + /** + * initComponentDefaults + * @param defaults the defaults table (<code>null</code> not permitted). + */ + protected void initComponentDefaults(UIDefaults defaults) + { + Object[] uiDefaults; + + Color highLight = new Color(249, 247, 246); + Color light = new Color(239, 235, 231); + Color shadow = new Color(139, 136, 134); + Color darkShadow = new Color(16, 16, 16); + + uiDefaults = new Object[] { + + "AbstractUndoableEdit.undoText", "Undo", + "AbstractUndoableEdit.redoText", "Redo", + "Button.background", new ColorUIResource(Color.LIGHT_GRAY), + "Button.border", + new UIDefaults.LazyValue() + { + public Object createValue(UIDefaults table) + { + return BasicBorders.getButtonBorder(); + } + }, + "Button.darkShadow", new ColorUIResource(Color.BLACK), + "Button.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { + "SPACE", "pressed", + "released SPACE", "released" + }), + "Button.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "Button.foreground", new ColorUIResource(Color.BLACK), + "Button.highlight", new ColorUIResource(Color.WHITE), + "Button.light", new ColorUIResource(Color.LIGHT_GRAY), + "Button.margin", new InsetsUIResource(2, 2, 2, 2), + "Button.shadow", new ColorUIResource(Color.GRAY), + "Button.textIconGap", new Integer(4), + "Button.textShiftOffset", new Integer(0), + "CheckBox.background", new ColorUIResource(light), + "CheckBox.border", new BorderUIResource.CompoundBorderUIResource(null, + null), + "CheckBox.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { + "SPACE", "pressed", + "released SPACE", "released" + }), + "CheckBox.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "CheckBox.foreground", new ColorUIResource(darkShadow), + "CheckBox.icon", BasicIconFactory.getCheckBoxIcon(), + "CheckBox.margin",new InsetsUIResource(2, 2, 2, 2), + "CheckBox.textIconGap", new Integer(4), + "CheckBox.textShiftOffset", new Integer(0), + "CheckBoxMenuItem.acceleratorFont", new FontUIResource("Dialog", + Font.PLAIN, 12), + "CheckBoxMenuItem.acceleratorForeground", + new ColorUIResource(darkShadow), + "CheckBoxMenuItem.acceleratorSelectionForeground", + new ColorUIResource(Color.white), + "CheckBoxMenuItem.arrowIcon", BasicIconFactory.getMenuItemArrowIcon(), + "CheckBoxMenuItem.background", new ColorUIResource(light), + "CheckBoxMenuItem.border", new BasicBorders.MarginBorder(), + "CheckBoxMenuItem.borderPainted", Boolean.FALSE, + "CheckBoxMenuItem.checkIcon", BasicIconFactory.getCheckBoxMenuItemIcon(), + "CheckBoxMenuItem.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "CheckBoxMenuItem.foreground", new ColorUIResource(darkShadow), + "CheckBoxMenuItem.margin", new InsetsUIResource(2, 2, 2, 2), + "CheckBoxMenuItem.selectionBackground", new ColorUIResource(Color.black), + "CheckBoxMenuItem.selectionForeground", new ColorUIResource(Color.white), + "ColorChooser.background", new ColorUIResource(light), + "ColorChooser.cancelText", "Cancel", + "ColorChooser.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "ColorChooser.foreground", new ColorUIResource(darkShadow), + "ColorChooser.hsbBlueText", "B", + "ColorChooser.hsbBrightnessText", "B", + "ColorChooser.hsbGreenText", "G", + "ColorChooser.hsbHueText", "H", + "ColorChooser.hsbNameText", "HSB", + "ColorChooser.hsbRedText", "R", + "ColorChooser.hsbSaturationText", "S", + "ColorChooser.okText", "OK", + "ColorChooser.previewText", "Preview", + "ColorChooser.resetText", "Reset", + "ColorChooser.rgbBlueMnemonic", new Integer(66), + "ColorChooser.rgbBlueText", "Blue", + "ColorChooser.rgbGreenMnemonic", new Integer(71), + "ColorChooser.rgbGreenText", "Green", + "ColorChooser.rgbNameText", "RGB", + "ColorChooser.rgbRedMnemonic", new Integer(82), + "ColorChooser.rgbRedText", "Red", + "ColorChooser.sampleText", "Sample Text Sample Text", + "ColorChooser.swatchesDefaultRecentColor", new ColorUIResource(light), + "ColorChooser.swatchesNameText", "Swatches", + "ColorChooser.swatchesRecentSwatchSize", new Dimension(10, 10), + "ColorChooser.swatchesRecentText", "Recent:", + "ColorChooser.swatchesSwatchSize", new Dimension(10, 10), + "ComboBox.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { + "ESCAPE", "hidePopup", + "PAGE_UP", "pageUpPassThrough", + "PAGE_DOWN", "pageDownPassThrough", + "HOME", "homePassThrough", + "END", "endPassThrough" + }), + "ComboBox.background", new ColorUIResource(light), + "ComboBox.buttonBackground", new ColorUIResource(light), + "ComboBox.buttonDarkShadow", new ColorUIResource(shadow), + "ComboBox.buttonHighlight", new ColorUIResource(highLight), + "ComboBox.buttonShadow", new ColorUIResource(shadow), + "ComboBox.disabledBackground", new ColorUIResource(light), + "ComboBox.disabledForeground", new ColorUIResource(Color.gray), + "ComboBox.font", new FontUIResource("SansSerif", Font.PLAIN, 12), + "ComboBox.foreground", new ColorUIResource(Color.black), + "ComboBox.selectionBackground", new ColorUIResource(Color.black), + "ComboBox.selectionForeground", new ColorUIResource(Color.white), + "Desktop.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { + "KP_LEFT", "left", + "KP_RIGHT", "right", + "ctrl F5", "restore", + "LEFT", "left", + "ctrl alt F6", "selectNextFrame", + "UP", "up", + "ctrl F6", "selectNextFrame", + "RIGHT", "right", + "DOWN", "down", + "ctrl F7", "move", + "ctrl F8", "resize", + "ESCAPE", "escape", + "ctrl TAB", "selectNextFrame", + "ctrl F9", "minimize", + "KP_UP", "up", + "ctrl F4", "close", + "KP_DOWN", "down", + "ctrl F10", "maximize", + "ctrl alt shift F6","selectPreviousFrame" + }), + "Desktop.background", new ColorUIResource(0, 92, 92), + "DesktopIcon.border", new BorderUIResource.CompoundBorderUIResource(null, + null), + "EditorPane.background", new ColorUIResource(Color.white), + "EditorPane.border", new BasicBorders.MarginBorder(), + "EditorPane.caretBlinkRate", new Integer(500), + "EditorPane.caretForeground", new ColorUIResource(Color.black), + "EditorPane.font", new FontUIResource("Serif", Font.PLAIN, 12), + "EditorPane.foreground", new ColorUIResource(Color.black), + "EditorPane.inactiveForeground", new ColorUIResource(Color.gray), + "EditorPane.keyBindings", new JTextComponent.KeyBinding[] { + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_UP, + 0), "caret-up"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, + 0), "caret-down"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, + 0), "page-up"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, + 0), "page-down"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, + 0), "insert-break"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, + 0), "insert-tab") + }, + "EditorPane.margin", new InsetsUIResource(3, 3, 3, 3), + "EditorPane.selectionBackground", new ColorUIResource(Color.black), + "EditorPane.selectionForeground", new ColorUIResource(Color.white), + "FileChooser.acceptAllFileFilterText", "All Files (*.*)", + "FileChooser.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { + "ESCAPE", "cancelSelection" + }), + "FileChooser.cancelButtonMnemonic", new Integer(67), + "FileChooser.cancelButtonText", "Cancel", + "FileChooser.cancelButtonToolTipText", "Abort file chooser dialog", + // XXX Don't use gif +// "FileChooser.detailsViewIcon", new IconUIResource(new ImageIcon("icons/DetailsView.gif")), + "FileChooser.directoryDescriptionText", "Directory", + "FileChooser.fileDescriptionText", "Generic File", + "FileChooser.helpButtonMnemonic", new Integer(72), + "FileChooser.helpButtonText", "Help", + "FileChooser.helpButtonToolTipText", "FileChooser help", + // XXX Don't use gif +// "FileChooser.homeFolderIcon", new IconUIResource(new ImageIcon("icons/HomeFolder.gif")), + // XXX Don't use gif +// "FileChooser.listViewIcon", new IconUIResource(new ImageIcon("icons/ListView.gif")), + "FileChooser.newFolderErrorSeparator", ":", + "FileChooser.newFolderErrorText", "Error creating new folder", + // XXX Don't use gif +// "FileChooser.newFolderIcon", new IconUIResource(new ImageIcon("icons/NewFolder.gif")), + "FileChooser.openButtonMnemonic", new Integer(79), + "FileChooser.openButtonText", "Open", + "FileChooser.openButtonToolTipText", "Open selected file", + "FileChooser.saveButtonMnemonic", new Integer(83), + "FileChooser.saveButtonText", "Save", + "FileChooser.saveButtonToolTipText", "Save selected file", + // XXX Don't use gif +// "FileChooser.upFolderIcon", new IconUIResource(new ImageIcon("icons/UpFolder.gif")), + "FileChooser.updateButtonMnemonic", new Integer(85), + "FileChooser.updateButtonText", "Update", + "FileChooser.updateButtonToolTipText", "Update directory listing", + // XXX Don't use gif +// "FileView.computerIcon", new IconUIResource(new ImageIcon("icons/Computer.gif")), + // XXX Don't use gif +// "FileView.directoryIcon", new IconUIResource(new ImageIcon("icons/Directory.gif")), + // XXX Don't use gif +// "FileView.fileIcon", new IconUIResource(new ImageIcon("icons/File.gif")), + // XXX Don't use gif +// "FileView.floppyDriveIcon", new IconUIResource(new ImageIcon("icons/Floppy.gif")), + // XXX Don't use gif +// "FileView.hardDriveIcon", new IconUIResource(new ImageIcon("icons/HardDrive.gif")), + "FocusManagerClassName", "TODO", + "FormattedTextField.background", new ColorUIResource(light), + "FormattedTextField.caretForeground", new ColorUIResource(Color.black), + "FormattedTextField.foreground", new ColorUIResource(Color.black), + "FormattedTextField.inactiveBackground", new ColorUIResource(light), + "FormattedTextField.inactiveForeground", new ColorUIResource(Color.gray), + "FormattedTextField.selectionBackground", + new ColorUIResource(Color.black), + "FormattedTextField.selectionForeground", + new ColorUIResource(Color.white), + "FormView.resetButtonText", "Reset", + "FormView.submitButtonText", "Submit Query", + "InternalFrame.activeTitleBackground", new ColorUIResource(0, 0, 128), + "InternalFrame.activeTitleForeground", new ColorUIResource(Color.white), + "InternalFrame.border", + new UIDefaults.LazyValue() + { + public Object createValue(UIDefaults table) + { + Color lineColor = new Color(238, 238, 238); + Border inner = BorderFactory.createLineBorder(lineColor, 1); + Color shadowInner = new Color(184, 207, 229); + Color shadowOuter = new Color(122, 138, 153); + Border outer = BorderFactory.createBevelBorder(BevelBorder.RAISED, + Color.WHITE, + Color.WHITE, + shadowOuter, + shadowInner); + Border border = new BorderUIResource.CompoundBorderUIResource(outer, + inner); + return border; + } + }, + "InternalFrame.borderColor", new ColorUIResource(light), + "InternalFrame.borderDarkShadow", new ColorUIResource(Color.BLACK), + "InternalFrame.borderHighlight", new ColorUIResource(Color.WHITE), + "InternalFrame.borderLight", new ColorUIResource(Color.LIGHT_GRAY), + "InternalFrame.borderShadow", new ColorUIResource(Color.GRAY), + "InternalFrame.closeIcon", BasicIconFactory.createEmptyFrameIcon(), + // XXX Don't use gif +// "InternalFrame.icon", new IconUIResource(new ImageIcon("icons/JavaCup.gif")), + "InternalFrame.iconifyIcon", BasicIconFactory.createEmptyFrameIcon(), + "InternalFrame.inactiveTitleBackground", new ColorUIResource(Color.gray), + "InternalFrame.inactiveTitleForeground", + new ColorUIResource(Color.lightGray), + "InternalFrame.maximizeIcon", BasicIconFactory.createEmptyFrameIcon(), + "InternalFrame.minimizeIcon", BasicIconFactory.createEmptyFrameIcon(), + "InternalFrame.titleFont", new FontUIResource("Dialog", Font.PLAIN, 12), + "InternalFrame.windowBindings", new Object[] { + "shift ESCAPE", "showSystemMenu", + "ctrl SPACE", "showSystemMenu", + "ESCAPE", "showSystemMenu" + }, + "Label.background", new ColorUIResource(light), + "Label.disabledForeground", new ColorUIResource(Color.white), + "Label.disabledShadow", new ColorUIResource(shadow), + "Label.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "Label.foreground", new ColorUIResource(darkShadow), + "List.background", new ColorUIResource(light), + "List.border", new BasicBorders.MarginBorder(), + "List.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { + "PAGE_UP", "scrollUp", + "ctrl \\", "clearSelection", + "PAGE_DOWN", "scrollDown", + "shift PAGE_DOWN","scrollDownExtendSelection", + "END", "selectLastRow", + "HOME", "selectFirstRow", + "shift END", "selectLastRowExtendSelection", + "shift HOME", "selectFirstRowExtendSelection", + "UP", "selectPreviousRow", + "ctrl /", "selectAll", + "ctrl A", "selectAll", + "DOWN", "selectNextRow", + "shift UP", "selectPreviousRowExtendSelection", + "ctrl SPACE", "selectNextRowExtendSelection", + "shift DOWN", "selectNextRowExtendSelection", + "KP_UP", "selectPreviousRow", + "shift PAGE_UP","scrollUpExtendSelection", + "KP_DOWN", "selectNextRow" + }), + "List.foreground", new ColorUIResource(darkShadow), + "List.selectionBackground", new ColorUIResource(Color.black), + "List.selectionForeground", new ColorUIResource(Color.white), + "Menu.acceleratorFont", new FontUIResource("Dialog", Font.PLAIN, 12), + "Menu.acceleratorForeground", new ColorUIResource(darkShadow), + "Menu.acceleratorSelectionForeground", new ColorUIResource(Color.white), + "Menu.arrowIcon", BasicIconFactory.getMenuArrowIcon(), + "Menu.background", new ColorUIResource(light), + "Menu.border", new BasicBorders.MarginBorder(), + "Menu.borderPainted", Boolean.FALSE, + "Menu.checkIcon", BasicIconFactory.getMenuItemCheckIcon(), + "Menu.consumesTabs", Boolean.TRUE, + "Menu.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "Menu.foreground", new ColorUIResource(darkShadow), + "Menu.margin", new InsetsUIResource(2, 2, 2, 2), + "Menu.selectedWindowInputMapBindings", new Object[] { + "ESCAPE", "cancel", + "DOWN", "selectNext", + "KP_DOWN", "selectNext", + "UP", "selectPrevious", + "KP_UP", "selectPrevious", + "LEFT", "selectParent", + "KP_LEFT", "selectParent", + "RIGHT", "selectChild", + "KP_RIGHT", "selectChild", + "ENTER", "return", + "SPACE", "return" + }, + "Menu.selectionBackground", new ColorUIResource(Color.black), + "Menu.selectionForeground", new ColorUIResource(Color.white), + "MenuBar.background", new ColorUIResource(light), + "MenuBar.border", new BasicBorders.MenuBarBorder(null, null), + "MenuBar.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "MenuBar.foreground", new ColorUIResource(darkShadow), + "MenuBar.highlight", new ColorUIResource(highLight), + "MenuBar.shadow", new ColorUIResource(shadow), + "MenuBar.windowBindings", new Object[] { + "F10", "takeFocus" + }, + "MenuItem.acceleratorDelimiter", "-", + "MenuItem.acceleratorFont", new FontUIResource("Dialog", Font.PLAIN, 12), + "MenuItem.acceleratorForeground", new ColorUIResource(darkShadow), + "MenuItem.acceleratorSelectionForeground", + new ColorUIResource(Color.white), + "MenuItem.arrowIcon", BasicIconFactory.getMenuItemArrowIcon(), + "MenuItem.background", new ColorUIResource(light), + "MenuItem.border", new BasicBorders.MarginBorder(), + "MenuItem.borderPainted", Boolean.FALSE, + "MenuItem.checkIcon", BasicIconFactory.getMenuItemCheckIcon(), + "MenuItem.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "MenuItem.foreground", new ColorUIResource(darkShadow), + "MenuItem.margin", new InsetsUIResource(2, 2, 2, 2), + "MenuItem.selectionBackground", new ColorUIResource(Color.black), + "MenuItem.selectionForeground", new ColorUIResource(Color.white), + "OptionPane.background", new ColorUIResource(light), + "OptionPane.border", + new BorderUIResource.EmptyBorderUIResource(0, 0, 0, 0), + "OptionPane.buttonAreaBorder", + new BorderUIResource.EmptyBorderUIResource(0, 0, 0, 0), + "OptionPane.cancelButtonText", "Cancel", + // XXX Don't use gif +// "OptionPane.errorIcon", +// new IconUIResource(new ImageIcon("icons/Error.gif")), + "OptionPane.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "OptionPane.foreground", new ColorUIResource(darkShadow), + // XXX Don't use gif +// "OptionPane.informationIcon", +// new IconUIResource(new ImageIcon("icons/Inform.gif")), + "OptionPane.messageAreaBorder", + new BorderUIResource.EmptyBorderUIResource(0, 0, 0, 0), + "OptionPane.messageForeground", new ColorUIResource(darkShadow), + "OptionPane.minimumSize", new DimensionUIResource(262, 90), + "OptionPane.noButtonText", "No", + "OptionPane.okButtonText", "OK", + // XXX Don't use gif +// "OptionPane.questionIcon", +// new IconUIResource(new ImageIcon("icons/Question.gif")), + // XXX Don't use gif +// "OptionPane.warningIcon", +// new IconUIResource(new ImageIcon("icons/Warn.gif")), + "OptionPane.windowBindings", new Object[] { + "ESCAPE", "close" + }, + "OptionPane.yesButtonText", "Yes", + "Panel.background", new ColorUIResource(light), + "Panel.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "Panel.foreground", new ColorUIResource(Color.black), + "PasswordField.background", new ColorUIResource(light), + "PasswordField.border", new BasicBorders.FieldBorder(null, null, + null, null), + "PasswordField.caretBlinkRate", new Integer(500), + "PasswordField.caretForeground", new ColorUIResource(Color.black), + "PasswordField.font", new FontUIResource("MonoSpaced", Font.PLAIN, 12), + "PasswordField.foreground", new ColorUIResource(Color.black), + "PasswordField.inactiveBackground", new ColorUIResource(light), + "PasswordField.inactiveForeground", new ColorUIResource(Color.gray), + "PasswordField.keyBindings", new JTextComponent.KeyBinding[] { + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, + 0), + "notify-field-accept")}, + "PasswordField.margin", new InsetsUIResource(0, 0, 0, 0), + "PasswordField.selectionBackground", new ColorUIResource(Color.black), + "PasswordField.selectionForeground", new ColorUIResource(Color.white), + "PopupMenu.background", new ColorUIResource(light), + "PopupMenu.border", new BorderUIResource.BevelBorderUIResource(0), + "PopupMenu.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "PopupMenu.foreground", new ColorUIResource(darkShadow), + "ProgressBar.background", new ColorUIResource(light), + "ProgressBar.border", new BorderUIResource.LineBorderUIResource(Color.darkGray), + "ProgressBar.cellLength", new Integer(1), + "ProgressBar.cellSpacing", new Integer(0), + "ProgressBar.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "ProgressBar.foreground", new ColorUIResource(Color.black), + "ProgressBar.selectionBackground", new ColorUIResource(Color.black), + "ProgressBar.selectionForeground", new ColorUIResource(light), + "ProgressBar.repaintInterval", new Integer(250), + "ProgressBar.cycleTime", new Integer(6000), + "RadioButton.background", new ColorUIResource(light), + "RadioButton.border", new BorderUIResource.CompoundBorderUIResource(null, + null), + "RadioButton.darkShadow", new ColorUIResource(shadow), + "RadioButton.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { + "SPACE", "pressed", + "released SPACE", "released" + }), + "RadioButton.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "RadioButton.foreground", new ColorUIResource(darkShadow), + "RadioButton.highlight", new ColorUIResource(highLight), + "RadioButton.icon", BasicIconFactory.getRadioButtonIcon(), + "RadioButton.light", new ColorUIResource(highLight), + "RadioButton.margin", new InsetsUIResource(2, 2, 2, 2), + "RadioButton.shadow", new ColorUIResource(shadow), + "RadioButton.textIconGap", new Integer(4), + "RadioButton.textShiftOffset", new Integer(0), + "RadioButtonMenuItem.acceleratorFont", + new FontUIResource("Dialog", Font.PLAIN, 12), + "RadioButtonMenuItem.acceleratorForeground", + new ColorUIResource(darkShadow), + "RadioButtonMenuItem.acceleratorSelectionForeground", + new ColorUIResource(Color.white), + "RadioButtonMenuItem.arrowIcon", BasicIconFactory.getMenuItemArrowIcon(), + "RadioButtonMenuItem.background", new ColorUIResource(light), + "RadioButtonMenuItem.border", new BasicBorders.MarginBorder(), + "RadioButtonMenuItem.borderPainted", Boolean.FALSE, + "RadioButtonMenuItem.checkIcon", BasicIconFactory.getRadioButtonMenuItemIcon(), + "RadioButtonMenuItem.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "RadioButtonMenuItem.foreground", new ColorUIResource(darkShadow), + "RadioButtonMenuItem.margin", new InsetsUIResource(2, 2, 2, 2), + "RadioButtonMenuItem.selectionBackground", + new ColorUIResource(Color.black), + "RadioButtonMenuItem.selectionForeground", + new ColorUIResource(Color.white), + "RootPane.defaultButtonWindowKeyBindings", new Object[] { + "ENTER", "press", + "released ENTER", "release", + "ctrl ENTER", "press", + "ctrl released ENTER", "release" + }, + "ScrollBar.background", new ColorUIResource(224, 224, 224), + "ScrollBar.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { + "PAGE_UP", "negativeBlockIncrement", + "PAGE_DOWN", "positiveBlockIncrement", + "END", "maxScroll", + "HOME", "minScroll", + "LEFT", "positiveUnitIncrement", + "KP_UP", "negativeUnitIncrement", + "KP_DOWN", "positiveUnitIncrement", + "UP", "negativeUnitIncrement", + "RIGHT", "negativeUnitIncrement", + "KP_LEFT", "positiveUnitIncrement", + "DOWN", "positiveUnitIncrement", + "KP_RIGHT", "negativeUnitIncrement" + }), + "ScrollBar.foreground", new ColorUIResource(light), + "ScrollBar.maximumThumbSize", new DimensionUIResource(4096, 4096), + "ScrollBar.minimumThumbSize", new DimensionUIResource(8, 8), + "ScrollBar.thumb", new ColorUIResource(light), + "ScrollBar.thumbDarkShadow", new ColorUIResource(shadow), + "ScrollBar.thumbHighlight", new ColorUIResource(highLight), + "ScrollBar.thumbShadow", new ColorUIResource(shadow), + "ScrollBar.track", new ColorUIResource(light), + "ScrollBar.trackHighlight", new ColorUIResource(shadow), + "ScrollPane.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { + "PAGE_UP", "scrollUp", + "KP_LEFT", "unitScrollLeft", + "ctrl PAGE_DOWN","scrollRight", + "PAGE_DOWN", "scrollDown", + "KP_RIGHT", "unitScrollRight", + "LEFT", "unitScrollLeft", + "ctrl END", "scrollEnd", + "UP", "unitScrollUp", + "RIGHT", "unitScrollRight", + "DOWN", "unitScrollDown", + "ctrl HOME", "scrollHome", + "ctrl PAGE_UP", "scrollLeft", + "KP_UP", "unitScrollUp", + "KP_DOWN", "unitScrollDown" + }), + "ScrollPane.background", new ColorUIResource(light), + "ScrollPane.border", new BorderUIResource.EtchedBorderUIResource(), + "ScrollPane.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "ScrollPane.foreground", new ColorUIResource(darkShadow), + "Separator.background", new ColorUIResource(highLight), + "Separator.foreground", new ColorUIResource(shadow), + "Separator.highlight", new ColorUIResource(highLight), + "Separator.shadow", new ColorUIResource(shadow), + "Slider.background", new ColorUIResource(light), + "Slider.focus", new ColorUIResource(shadow), + "Slider.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { + "PAGE_UP", "positiveBlockIncrement", + "PAGE_DOWN", "negativeBlockIncrement", + "END", "maxScroll", + "HOME", "minScroll", + "LEFT", "negativeUnitIncrement", + "KP_UP", "positiveUnitIncrement", + "KP_DOWN", "negativeUnitIncrement", + "UP", "positiveUnitIncrement", + "RIGHT", "positiveUnitIncrement", + "KP_LEFT", "negativeUnitIncrement", + "DOWN", "negativeUnitIncrement", + "KP_RIGHT", "positiveUnitIncrement" + }), + "Slider.focusInsets", new InsetsUIResource(2, 2, 2, 2), + "Slider.foreground", new ColorUIResource(light), + "Slider.highlight", new ColorUIResource(highLight), + "Slider.shadow", new ColorUIResource(shadow), + "Slider.thumbHeight", new Integer(20), + "Slider.thumbWidth", new Integer(10), + "Slider.tickHeight", new Integer(12), + "Spinner.background", new ColorUIResource(light), + "Spinner.foreground", new ColorUIResource(light), + "SplitPane.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { + "F6", "toggleFocus", + "F8", "startResize", + "END", "selectMax", + "HOME", "selectMin", + "LEFT", "negativeIncremnent", + "KP_UP", "negativeIncrement", + "KP_DOWN", "positiveIncrement", + "UP", "negativeIncrement", + "RIGHT", "positiveIncrement", + "KP_LEFT", "negativeIncrement", + "DOWN", "positiveIncrement", + "KP_RIGHT", "positiveIncrement" + }), + "SplitPane.background", new ColorUIResource(light), + "SplitPane.border", new BasicBorders.SplitPaneBorder(null, null), + "SplitPane.darkShadow", new ColorUIResource(shadow), + "SplitPane.dividerSize", new Integer(10), + "SplitPane.highlight", new ColorUIResource(highLight), + "SplitPane.shadow", new ColorUIResource(shadow), + "TabbedPane.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { + "ctrl PAGE_DOWN","navigatePageDown", + "ctrl PAGE_UP", "navigatePageUp", + "ctrl UP", "requestFocus", + "ctrl KP_UP", "requestFocus" + }), + "TabbedPane.background", new ColorUIResource(light), + "TabbedPane.contentBorderInsets", new InsetsUIResource(2, 2, 3, 3), + "TabbedPane.darkShadow", new ColorUIResource(shadow), + "TabbedPane.focus", new ColorUIResource(darkShadow), + "TabbedPane.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { + "LEFT", "navigateLeft", + "KP_UP", "navigateUp", + "ctrl DOWN", "requestFocusForVisibleComponent", + "UP", "navigateUp", + "KP_DOWN", "navigateDown", + "RIGHT", "navigateRight", + "KP_LEFT", "navigateLeft", + "ctrl KP_DOWN", "requestFocusForVisibleComponent", + "KP_RIGHT", "navigateRight", + "DOWN", "navigateDown" + }), + "TabbedPane.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "TabbedPane.foreground", new ColorUIResource(darkShadow), + "TabbedPane.highlight", new ColorUIResource(highLight), + "TabbedPane.light", new ColorUIResource(highLight), + "TabbedPane.selectedTabPadInsets", new InsetsUIResource(2, 2, 2, 1), + "TabbedPane.shadow", new ColorUIResource(shadow), + "TabbedPane.tabbedPaneTabAreaInsets", new InsetsUIResource(3, 2, 1, 2), + "TabbedPane.tabbedPaneTabInsets", new InsetsUIResource(1, 4, 1, 4), + "TabbedPane.tabbedPaneContentBorderInsets", new InsetsUIResource(3, 2, 1, 2), + "TabbedPane.tabbedPaneTabPadInsets", new InsetsUIResource(1, 1, 1, 1), + "TabbedPane.tabRunOverlay", new Integer(2), + "TabbedPane.textIconGap", new Integer(4), + "Table.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { + "shift PAGE_DOWN","scrollDownExtendSelection", + "PAGE_DOWN", "scrollDownChangeSelection", + "END", "selectLastColumn", + "shift END", "selectLastColumnExtendSelection", + "HOME", "selectFirstColumn", + "ctrl END", "selectLastRow", + "ctrl shift END","selectLastRowExtendSelection", + "LEFT", "selectPreviousColumn", + "shift HOME", "selectFirstColumnExtendSelection", + "UP", "selectPreviousRow", + "RIGHT", "selectNextColumn", + "ctrl HOME", "selectFirstRow", + "shift LEFT", "selectPreviousColumnExtendSelection", + "DOWN", "selectNextRow", + "ctrl shift HOME","selectFirstRowExtendSelection", + "shift UP", "selectPreviousRowExtendSelection", + "F2", "startEditing", + "shift RIGHT", "selectNextColumnExtendSelection", + "TAB", "selectNextColumnCell", + "shift DOWN", "selectNextRowExtendSelection", + "ENTER", "selectNextRowCell", + "KP_UP", "selectPreviousRow", + "KP_DOWN", "selectNextRow", + "KP_LEFT", "selectPreviousColumn", + "KP_RIGHT", "selectNextColumn", + "shift TAB", "selectPreviousColumnCell", + "ctrl A", "selectAll", + "shift ENTER", "selectPreviousRowCell", + "shift KP_DOWN", "selectNextRowExtendSelection", + "shift KP_LEFT", "selectPreviousColumnExtendSelection", + "ESCAPE", "cancel", + "ctrl shift PAGE_UP", "scrollRightExtendSelection", + "shift KP_RIGHT", " selectNextColumnExtendSelection", + "ctrl PAGE_UP", "scrollLeftChangeSelection", + "shift PAGE_UP", "scrollUpExtendSelection", + "ctrl shift PAGE_DOWN", "scrollLeftExtendSelection", + "ctrl PAGE_DOWN", "scrollRightChangeSelection", + "PAGE_UP", "scrollUpChangeSelection" + }), + "Table.background", new ColorUIResource(light), + "Table.focusCellBackground", new ColorUIResource(light), + "Table.focusCellForeground", new ColorUIResource(darkShadow), + "Table.focusCellHighlightBorder", + new BorderUIResource.LineBorderUIResource( + new ColorUIResource(255, 255, 0)), + "Table.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "Table.foreground", new ColorUIResource(darkShadow), + "Table.gridColor", new ColorUIResource(Color.gray), + "Table.scrollPaneBorder", new BorderUIResource.BevelBorderUIResource(0), + "Table.selectionBackground", new ColorUIResource(Color.black), + "Table.selectionForeground", new ColorUIResource(Color.white), + "TableHeader.background", new ColorUIResource(light), + "TableHeader.cellBorder", new BorderUIResource.BevelBorderUIResource(0), + "TableHeader.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "TableHeader.foreground", new ColorUIResource(darkShadow), + + "TextArea.background", new ColorUIResource(light), + "TextArea.border", new BasicBorders.MarginBorder(), + "TextArea.caretBlinkRate", new Integer(500), + "TextArea.caretForeground", new ColorUIResource(Color.black), + "TextArea.font", new FontUIResource("MonoSpaced", Font.PLAIN, 12), + "TextArea.foreground", new ColorUIResource(Color.black), + "TextArea.inactiveForeground", new ColorUIResource(Color.gray), + "TextArea.keyBindings", new JTextComponent.KeyBinding[] { + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_UP, + 0), "caret-up"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, + 0), "caret-down"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, + 0), "page-up"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, + 0), "page-down"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, + 0), "insert-break"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, + 0), "insert-tab") + }, + "TextArea.margin", new InsetsUIResource(0, 0, 0, 0), + "TextArea.selectionBackground", new ColorUIResource(Color.black), + "TextArea.selectionForeground", new ColorUIResource(Color.white), + "TextField.background", new ColorUIResource(light), + "TextField.border", new BasicBorders.FieldBorder(null, null, null, null), + "TextField.caretBlinkRate", new Integer(500), + "TextField.caretForeground", new ColorUIResource(Color.black), + "TextField.darkShadow", new ColorUIResource(shadow), + "TextField.font", new FontUIResource("SansSerif", Font.PLAIN, 12), + "TextField.foreground", new ColorUIResource(Color.black), + "TextField.highlight", new ColorUIResource(highLight), + "TextField.inactiveBackground", new ColorUIResource(light), + "TextField.inactiveForeground", new ColorUIResource(Color.gray), + "TextField.light", new ColorUIResource(highLight), + "TextField.highlight", new ColorUIResource(light), + "TextField.keyBindings", new JTextComponent.KeyBinding[] { + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, + 0), + "notify-field-accept"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, + InputEvent.SHIFT_DOWN_MASK), + "selection-backward"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, + InputEvent.SHIFT_DOWN_MASK), + "selection-forward"), + }, + "TextField.margin", new InsetsUIResource(0, 0, 0, 0), + "TextField.selectionBackground", new ColorUIResource(Color.black), + "TextField.selectionForeground", new ColorUIResource(Color.white), + "TextPane.background", new ColorUIResource(Color.white), + "TextPane.border", new BasicBorders.MarginBorder(), + "TextPane.caretBlinkRate", new Integer(500), + "TextPane.caretForeground", new ColorUIResource(Color.black), + "TextPane.font", new FontUIResource("Serif", Font.PLAIN, 12), + "TextPane.foreground", new ColorUIResource(Color.black), + "TextPane.inactiveForeground", new ColorUIResource(Color.gray), + "TextPane.keyBindings", new JTextComponent.KeyBinding[] { + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_UP, + 0), "caret-up"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, + 0), "caret-down"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, + 0), "page-up"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, + 0), "page-down"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, + 0), "insert-break"), + new JTextComponent.KeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, + 0), "insert-tab") + }, + "TextPane.margin", new InsetsUIResource(3, 3, 3, 3), + "TextPane.selectionBackground", new ColorUIResource(Color.black), + "TextPane.selectionForeground", new ColorUIResource(Color.white), + "TitledBorder.border", new BorderUIResource.EtchedBorderUIResource(), + "TitledBorder.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "TitledBorder.titleColor", new ColorUIResource(darkShadow), + "ToggleButton.background", new ColorUIResource(light), + "ToggleButton.border", + new BorderUIResource.CompoundBorderUIResource(null, null), + "ToggleButton.darkShadow", new ColorUIResource(shadow), + "ToggleButton.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { + "SPACE", "pressed", + "released SPACE", "released" + }), + "ToggleButton.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "ToggleButton.foreground", new ColorUIResource(darkShadow), + "ToggleButton.highlight", new ColorUIResource(highLight), + "ToggleButton.light", new ColorUIResource(light), + "ToggleButton.margin", new InsetsUIResource(2, 14, 2, 14), + "ToggleButton.shadow", new ColorUIResource(shadow), + "ToggleButton.textIconGap", new Integer(4), + "ToggleButton.textShiftOffset", new Integer(0), + "ToolBar.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { + "UP", "navigateUp", + "KP_UP", "navigateUp", + "DOWN", "navigateDown", + "KP_DOWN", "navigateDown", + "LEFT", "navigateLeft", + "KP_LEFT", "navigateLeft", + "RIGHT", "navigateRight", + "KP_RIGHT", "navigateRight" + }), + "ToolBar.background", new ColorUIResource(light), + "ToolBar.border", new BorderUIResource.EtchedBorderUIResource(), + "ToolBar.darkShadow", new ColorUIResource(shadow), + "ToolBar.dockingBackground", new ColorUIResource(light), + "ToolBar.dockingForeground", new ColorUIResource(Color.red), + "ToolBar.floatingBackground", new ColorUIResource(light), + "ToolBar.floatingForeground", new ColorUIResource(Color.darkGray), + "ToolBar.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "ToolBar.foreground", new ColorUIResource(darkShadow), + "ToolBar.highlight", new ColorUIResource(highLight), + "ToolBar.light", new ColorUIResource(highLight), + "ToolBar.separatorSize", new DimensionUIResource(20, 20), + "ToolBar.shadow", new ColorUIResource(shadow), + "ToolTip.background", new ColorUIResource(light), + "ToolTip.border", new BorderUIResource.LineBorderUIResource(Color.lightGray), + "ToolTip.font", new FontUIResource("SansSerif", Font.PLAIN, 12), + "ToolTip.foreground", new ColorUIResource(darkShadow), + "Tree.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { + "ESCAPE", "cancel" + }), + "Tree.background", new ColorUIResource(light), + "Tree.changeSelectionWithFocus", Boolean.TRUE, +// "Tree.closedIcon", new IconUIResource(new ImageIcon("icons/TreeClosed.png")), +// "Tree.collapsedIcon", new IconUIResource(new ImageIcon("icons/TreeCollapsed.png")), + "Tree.drawsFocusBorderAroundIcon", Boolean.FALSE, + "Tree.editorBorder", new BorderUIResource.LineBorderUIResource(Color.lightGray), + "Tree.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { + "shift PAGE_DOWN", "scrollDownExtendSelection", + "PAGE_DOWN", "scrollDownChangeSelection", + "END", "selectLast", + "ctrl KP_UP", "selectPreviousChangeLead", + "shift END", "selectLastExtendSelection", + "HOME", "selectFirst", + "ctrl END", "selectLastChangeLead", + "ctrl /", "selectAll", + "LEFT", "selectParent", + "shift HOME", "selectFirstExtendSelection", + "UP", "selectPrevious", + "ctrl KP_DOWN", "selectNextChangeLead", + "RIGHT", "selectChild", + "ctrl HOME", "selectFirstChangeLead", + "DOWN", "selectNext", + "ctrl KP_LEFT", "scrollLeft", + "shift UP", "selectPreviousExtendSelection", + "F2", "startEditing", + "ctrl LEFT", "scrollLeft", + "ctrl KP_RIGHT","scrollRight", + "ctrl UP", "selectPreviousChangeLead", + "shift DOWN", "selectNextExtendSelection", + "ENTER", "toggle", + "KP_UP", "selectPrevious", + "KP_DOWN", "selectNext", + "ctrl RIGHT", "scrollRight", + "KP_LEFT", "selectParent", + "KP_RIGHT", "selectChild", + "ctrl DOWN", "selectNextChangeLead", + "ctrl A", "selectAll", + "shift KP_UP", "selectPreviousExtendSelection", + "shift KP_DOWN","selectNextExtendSelection", + "ctrl SPACE", "toggleSelectionPreserveAnchor", + "ctrl shift PAGE_UP", "scrollUpExtendSelection", + "ctrl \\", "clearSelection", + "shift SPACE", "extendSelection", + "ctrl PAGE_UP", "scrollUpChangeLead", + "shift PAGE_UP","scrollUpExtendSelection", + "SPACE", "toggleSelectionPreserveAnchor", + "ctrl shift PAGE_DOWN", "scrollDownExtendSelection", + "PAGE_UP", "scrollUpChangeSelection", + "ctrl PAGE_DOWN", "scrollDownChangeLead" + }), + "Tree.font", new FontUIResource(new Font("Helvetica", Font.PLAIN, 12)), + "Tree.foreground", new ColorUIResource(Color.black), + "Tree.hash", new ColorUIResource(new Color(128, 128, 128)), + "Tree.leftChildIndent", new Integer(7), + "Tree.rightChildIndent", new Integer(13), + "Tree.rowHeight", new Integer(20), // FIXME + "Tree.scrollsOnExpand", Boolean.TRUE, + "Tree.selectionBackground", new ColorUIResource(Color.black), + "Tree.nonSelectionBackground", new ColorUIResource(new Color(239, 235, 231)), + "Tree.selectionBorderColor", new ColorUIResource(Color.black), + "Tree.selectionForeground", new ColorUIResource(new Color(255, 255, 255)), + "Tree.textBackground", new ColorUIResource(new Color(255, 255, 255)), + "Tree.textForeground", new ColorUIResource(Color.black), + "Viewport.background", new ColorUIResource(light), + "Viewport.foreground", new ColorUIResource(Color.black), + "Viewport.font", new FontUIResource("Dialog", Font.PLAIN, 12) + }; + defaults.putDefaults(uiDefaults); + } +} // class BasicLookAndFeel diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicMenuBarUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicMenuBarUI.java new file mode 100644 index 0000000..95f6b84 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicMenuBarUI.java @@ -0,0 +1,304 @@ +/* BasicMenuBarUI.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Dimension; +import java.awt.event.ContainerEvent; +import java.awt.event.ContainerListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.BoxLayout; +import javax.swing.JComponent; +import javax.swing.JMenuBar; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.MenuBarUI; + +/** + * UI Delegate for JMenuBar. + */ +public class BasicMenuBarUI extends MenuBarUI +{ + protected ChangeListener changeListener; + + /*ContainerListener that listens to the ContainerEvents fired from menu bar*/ + protected ContainerListener containerListener; + + /*Property change listeners that listener to PropertyChangeEvent from menu bar*/ + protected PropertyChangeListener propertyChangeListener; + + /* menu bar for which this UI delegate is for*/ + protected JMenuBar menuBar; + + /** + * Creates a new BasicMenuBarUI object. + */ + public BasicMenuBarUI() + { + changeListener = createChangeListener(); + containerListener = createContainerListener(); + propertyChangeListener = new PropertyChangeHandler(); + } + + /** + * Creates ChangeListener + * + * @return The ChangeListener + */ + protected ChangeListener createChangeListener() + { + return new ChangeHandler(); + } + + /** + * Creates ContainerListener() to listen for ContainerEvents + * fired by JMenuBar. + * + * @return The ContainerListener + */ + protected ContainerListener createContainerListener() + { + return new ContainerHandler(); + } + + /** + * Factory method to create a BasicMenuBarUI for the given {@link + * JComponent}, which should be a {@link JMenuBar}. + * + * @param x The {@link JComponent} a UI is being created for. + * + * @return A BasicMenuBarUI for the {@link JComponent}. + */ + public static ComponentUI createUI(JComponent x) + { + return new BasicMenuBarUI(); + } + + /** + * Returns maximum size for the specified menu bar + * + * @param c component for which to get maximum size + * + * @return Maximum size for the specified menu bar + */ + public Dimension getMaximumSize(JComponent c) + { + // let layout manager calculate its size + return null; + } + + /** + * Returns maximum allowed size of JMenuBar. + * + * @param c menuBar for which to return maximum size + * + * @return Maximum size of the give menu bar. + */ + public Dimension getMinimumSize(JComponent c) + { + // let layout manager calculate its size + return null; + } + + /** + * Returns preferred size of JMenuBar. + * + * @param c menuBar for which to return preferred size + * + * @return Preferred size of the give menu bar. + */ + public Dimension getPreferredSize(JComponent c) + { + // let layout manager calculate its size + return null; + } + + /** + * Initializes any default properties that this UI has from the defaults for + * the Basic look and feel. + */ + protected void installDefaults() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + menuBar.setBackground(defaults.getColor("MenuBar.background")); + menuBar.setBorder(defaults.getBorder("MenuBar.border")); + menuBar.setFont(defaults.getFont("MenuBar.font")); + menuBar.setForeground(defaults.getColor("MenuBar.foreground")); + menuBar.setOpaque(true); + } + + /** + * This method installs the keyboard actions for the JMenuBar. + */ + protected void installKeyboardActions() + { + // FIXME: implement + } + + /** + * This method installs the listeners needed for this UI to function. + */ + protected void installListeners() + { + menuBar.addContainerListener(containerListener); + menuBar.addPropertyChangeListener(propertyChangeListener); + } + + /** + * Installs and initializes all fields for this UI delegate. Any properties + * of the UI that need to be initialized and/or set to defaults will be + * done now. It will also install any listeners necessary. + * + * @param c The {@link JComponent} that is having this UI installed. + */ + public void installUI(JComponent c) + { + super.installUI(c); + menuBar = (JMenuBar) c; + menuBar.setLayout(new BoxLayout(menuBar, BoxLayout.X_AXIS)); + installDefaults(); + installListeners(); + installKeyboardActions(); + } + + /** + * This method uninstalls the defaults and nulls any objects created during + * install. + */ + protected void uninstallDefaults() + { + menuBar.setBackground(null); + menuBar.setBorder(null); + menuBar.setFont(null); + menuBar.setForeground(null); + } + + /** + * This method reverses the work done in installKeyboardActions. + */ + protected void uninstallKeyboardActions() + { + // FIXME: implement. + } + + /** + * Unregisters all the listeners that this UI delegate was using. + */ + protected void uninstallListeners() + { + menuBar.removeContainerListener(containerListener); + menuBar.removePropertyChangeListener(propertyChangeListener); + } + + /** + * Performs the opposite of installUI. Any properties or resources that need + * to be cleaned up will be done now. It will also uninstall any listeners + * it has. In addition, any properties of this UI will be nulled. + * + * @param c The {@link JComponent} that is having this UI uninstalled. + */ + public void uninstallUI(JComponent c) + { + uninstallDefaults(); + uninstallListeners(); + uninstallKeyboardActions(); + menuBar = null; + } + + protected class ChangeHandler implements ChangeListener + { + public void stateChanged(ChangeEvent event) + { + } + } + + /** + * This class handles ContainerEvents fired by JMenuBar. It revalidates + * and repaints menu bar whenever menu is added or removed from it. + */ + protected class ContainerHandler implements ContainerListener + { + /** + * This method is called whenever menu is added to the menu bar + * + * @param e The ContainerEvent. + */ + public void componentAdded(ContainerEvent e) + { + menuBar.revalidate(); + menuBar.repaint(); + } + + /** + * This method is called whenever menu is removed from the menu bar. + * + * @param e The ContainerEvent. + */ + public void componentRemoved(ContainerEvent e) + { + menuBar.revalidate(); + menuBar.repaint(); + } + } + + /** + * This class handles PropertyChangeEvents fired from the JMenuBar + */ + protected class PropertyChangeHandler implements PropertyChangeListener + { + /** + * This method is called whenever one of the properties of the MenuBar + * changes. + * + * @param e The PropertyChangeEvent. + */ + public void propertyChange(PropertyChangeEvent e) + { + if (e.getPropertyName().equals("borderPainted")) + menuBar.repaint(); + if (e.getPropertyName().equals("margin")) + menuBar.repaint(); + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicMenuItemUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicMenuItemUI.java new file mode 100644 index 0000000..a5bf082 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicMenuItemUI.java @@ -0,0 +1,1006 @@ +/* BasicMenuItemUI.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.ArrayList; + +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.KeyStroke; +import javax.swing.MenuElement; +import javax.swing.MenuSelectionManager; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.event.MenuDragMouseEvent; +import javax.swing.event.MenuDragMouseListener; +import javax.swing.event.MenuKeyEvent; +import javax.swing.event.MenuKeyListener; +import javax.swing.event.MouseInputListener; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.MenuItemUI; + +/** + * UI Delegate for JMenuItem. + */ +public class BasicMenuItemUI extends MenuItemUI +{ + /** + * Font to be used when displaying menu item's accelerator. + */ + protected Font acceleratorFont; + + /** + * Color to be used when displaying menu item's accelerator. + */ + protected Color acceleratorForeground; + + /** + * Color to be used when displaying menu item's accelerator when menu item is + * selected. + */ + protected Color acceleratorSelectionForeground; + + /** + * Icon that is displayed after the text to indicated that this menu contains + * submenu. + */ + protected Icon arrowIcon; + + /** + * Icon that is displayed before the text. This icon is only used in + * JCheckBoxMenuItem or JRadioBoxMenuItem. + */ + protected Icon checkIcon; + + /** + * Number of spaces between icon and text. + */ + protected int defaultTextIconGap = 4; + + /** + * Color of the text when menu item is disabled + */ + protected Color disabledForeground; + + /** + * The menu Drag mouse listener listening to the menu item. + */ + protected MenuDragMouseListener menuDragMouseListener; + + /** + * The menu item itself + */ + protected JMenuItem menuItem; + + /** + * Menu Key listener listening to the menu item. + */ + protected MenuKeyListener menuKeyListener; + + /** + * mouse input listener listening to menu item. + */ + protected MouseInputListener mouseInputListener; + + /** + * Indicates if border should be painted + */ + protected boolean oldBorderPainted; + + /** + * Color of text that is used when menu item is selected + */ + protected Color selectionBackground; + + /** + * Color of the text that is used when menu item is selected. + */ + protected Color selectionForeground; + + /** + * String that separates description of the modifiers and the key + */ + private String acceleratorDelimiter; + + /** + * PropertyChangeListener to listen for property changes in the menu item + */ + private PropertyChangeListener propertyChangeListener; + + /** + * Number of spaces between accelerator and menu item's label. + */ + private int defaultAcceleratorLabelGap = 4; + + /** + * Creates a new BasicMenuItemUI object. + */ + public BasicMenuItemUI() + { + mouseInputListener = createMouseInputListener(menuItem); + menuDragMouseListener = createMenuDragMouseListener(menuItem); + menuKeyListener = createMenuKeyListener(menuItem); + propertyChangeListener = new PropertyChangeHandler(); + } + + /** + * Create MenuDragMouseListener to listen for mouse dragged events. + * + * @param c menu item to listen to + * + * @return The MenuDragMouseListener + */ + protected MenuDragMouseListener createMenuDragMouseListener(JComponent c) + { + return new MenuDragMouseHandler(); + } + + /** + * Creates MenuKeyListener to listen to key events occuring when menu item + * is visible on the screen. + * + * @param c menu item to listen to + * + * @return The MenuKeyListener + */ + protected MenuKeyListener createMenuKeyListener(JComponent c) + { + return new MenuKeyHandler(); + } + + /** + * Handles mouse input events occuring for this menu item + * + * @param c menu item to listen to + * + * @return The MouseInputListener + */ + protected MouseInputListener createMouseInputListener(JComponent c) + { + return new MouseInputHandler(); + } + + /** + * Factory method to create a BasicMenuItemUI for the given {@link + * JComponent}, which should be a {@link JMenuItem}. + * + * @param c The {@link JComponent} a UI is being created for. + * + * @return A BasicMenuItemUI for the {@link JComponent}. + */ + public static ComponentUI createUI(JComponent c) + { + return new BasicMenuItemUI(); + } + + /** + * Programatically clicks menu item. + * + * @param msm MenuSelectionManager for the menu hierarchy + */ + protected void doClick(MenuSelectionManager msm) + { + menuItem.doClick(); + msm.clearSelectedPath(); + } + + /** + * Returns maximum size for the specified menu item + * + * @param c component for which to get maximum size + * + * @return Maximum size for the specified menu item. + */ + public Dimension getMaximumSize(JComponent c) + { + return null; + } + + /** + * Returns minimum size for the specified menu item + * + * @param c component for which to get minimum size + * + * @return Minimum size for the specified menu item. + */ + public Dimension getMinimumSize(JComponent c) + { + return null; + } + + /** + * Returns path to this menu item. + * + * @return $MenuElement[]$ Returns array of menu elements + * that constitute a path to this menu item. + */ + public MenuElement[] getPath() + { + ArrayList path = new ArrayList(); + + // Path to menu should also include its popup menu. + if (menuItem instanceof JMenu) + path.add(((JMenu) menuItem).getPopupMenu()); + + Component c = menuItem; + while (c instanceof MenuElement) + { + path.add(0, (MenuElement) c); + + if (c instanceof JPopupMenu) + c = ((JPopupMenu) c).getInvoker(); + else + c = c.getParent(); + } + + MenuElement[] pathArray = new MenuElement[path.size()]; + path.toArray(pathArray); + return pathArray; + } + + /** + * Returns preferred size for the given menu item. + * + * @param c menu item for which to get preferred size + * @param checkIcon chech icon displayed in the given menu item + * @param arrowIcon arrow icon displayed in the given menu item + * @param defaultTextIconGap space between icon and text in the given menuItem + * + * @return $Dimension$ preferred size for the given menu item + */ + protected Dimension getPreferredMenuItemSize(JComponent c, Icon checkIcon, + Icon arrowIcon, + int defaultTextIconGap) + { + JMenuItem m = (JMenuItem) c; + Dimension d = BasicGraphicsUtils.getPreferredButtonSize(m, + defaultTextIconGap); + + // if menu item has accelerator then take accelerator's size into account + // when calculating preferred size. + KeyStroke accelerator = m.getAccelerator(); + Rectangle rect; + + if (accelerator != null) + { + rect = getAcceleratorRect(accelerator, + m.getToolkit().getFontMetrics(acceleratorFont)); + + // add width of accelerator's text + d.width = d.width + rect.width + defaultAcceleratorLabelGap; + + // adjust the heigth of the preferred size if necessary + if (d.height < rect.height) + d.height = rect.height; + } + + if (checkIcon != null) + { + d.width = d.width + checkIcon.getIconWidth() + defaultTextIconGap; + + if (checkIcon.getIconHeight() > d.height) + d.height = checkIcon.getIconHeight(); + } + + if (arrowIcon != null && (c instanceof JMenu)) + { + d.width = d.width + arrowIcon.getIconWidth() + defaultTextIconGap; + + if (arrowIcon.getIconHeight() > d.height) + d.height = arrowIcon.getIconHeight(); + } + + return d; + } + + /** + * Returns preferred size of the given component + * + * @param c component for which to return preferred size + * + * @return $Dimension$ preferred size for the given component + */ + public Dimension getPreferredSize(JComponent c) + { + return getPreferredMenuItemSize(c, checkIcon, arrowIcon, defaultTextIconGap); + } + + protected String getPropertyPrefix() + { + return null; + } + + /** + * This method installs the components for this {@link JMenuItem}. + * + * @param menuItem The {@link JMenuItem} to install components for. + */ + protected void installComponents(JMenuItem menuItem) + { + // FIXME: Need to implement + } + + /** + * This method installs the defaults that are defined in the Basic look and + * feel for this {@link JMenuItem}. + */ + protected void installDefaults() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + menuItem.setBackground(defaults.getColor("MenuItem.background")); + menuItem.setBorder(defaults.getBorder("MenuItem.border")); + menuItem.setFont(defaults.getFont("MenuItem.font")); + menuItem.setForeground(defaults.getColor("MenuItem.foreground")); + menuItem.setMargin(defaults.getInsets("MenuItem.margin")); + menuItem.setOpaque(true); + acceleratorFont = defaults.getFont("MenuItem.acceleratorFont"); + acceleratorForeground = defaults.getColor("MenuItem.acceleratorForeground"); + acceleratorSelectionForeground = defaults.getColor("MenuItem.acceleratorSelectionForeground"); + selectionBackground = defaults.getColor("MenuItem.selectionBackground"); + selectionForeground = defaults.getColor("MenuItem.selectionForeground"); + acceleratorDelimiter = defaults.getString("MenuItem.acceleratorDelimiter"); + + menuItem.setHorizontalTextPosition(SwingConstants.TRAILING); + menuItem.setHorizontalAlignment(SwingConstants.LEADING); + } + + /** + * This method installs the keyboard actions for this {@link JMenuItem}. + */ + protected void installKeyboardActions() + { + // FIXME: Need to implement + } + + /** + * This method installs the listeners for the {@link JMenuItem}. + */ + protected void installListeners() + { + menuItem.addMouseListener(mouseInputListener); + menuItem.addMouseMotionListener(mouseInputListener); + menuItem.addMenuDragMouseListener(menuDragMouseListener); + menuItem.addMenuKeyListener(menuKeyListener); + menuItem.addPropertyChangeListener(propertyChangeListener); + } + + /** + * Installs and initializes all fields for this UI delegate. Any properties + * of the UI that need to be initialized and/or set to defaults will be + * done now. It will also install any listeners necessary. + * + * @param c The {@link JComponent} that is having this UI installed. + */ + public void installUI(JComponent c) + { + super.installUI(c); + menuItem = (JMenuItem) c; + installDefaults(); + installComponents(menuItem); + installListeners(); + } + + /** + * Paints given menu item using specified graphics context + * + * @param g The graphics context used to paint this menu item + * @param c Menu Item to paint + */ + public void paint(Graphics g, JComponent c) + { + paintMenuItem(g, c, checkIcon, arrowIcon, c.getBackground(), + c.getForeground(), defaultTextIconGap); + } + + /** + * Paints background of the menu item + * + * @param g The graphics context used to paint this menu item + * @param menuItem menu item to paint + * @param bgColor Background color to use when painting menu item + */ + protected void paintBackground(Graphics g, JMenuItem menuItem, Color bgColor) + { + Dimension size = getPreferredSize(menuItem); + Color foreground = g.getColor(); + g.setColor(bgColor); + g.drawRect(0, 0, size.width, size.height); + g.setColor(foreground); + } + + /** + * Paints specified menu item + * + * @param g The graphics context used to paint this menu item + * @param c menu item to paint + * @param checkIcon check icon to use when painting menu item + * @param arrowIcon arrow icon to use when painting menu item + * @param background Background color of the menu item + * @param foreground Foreground color of the menu item + * @param defaultTextIconGap space to use between icon and + * text when painting menu item + */ + protected void paintMenuItem(Graphics g, JComponent c, Icon checkIcon, + Icon arrowIcon, Color background, + Color foreground, int defaultTextIconGap) + { + JMenuItem m = (JMenuItem) c; + Rectangle tr = new Rectangle(); // text rectangle + Rectangle ir = new Rectangle(); // icon rectangle + Rectangle vr = new Rectangle(); // view rectangle + Rectangle br = new Rectangle(); // border rectangle + Rectangle ar = new Rectangle(); // accelerator rectangle + Rectangle cr = new Rectangle(); // checkIcon rectangle + + int vertAlign = m.getVerticalAlignment(); + int horAlign = m.getHorizontalAlignment(); + int vertTextPos = m.getVerticalTextPosition(); + int horTextPos = m.getHorizontalTextPosition(); + + Font f = m.getFont(); + g.setFont(f); + FontMetrics fm = g.getFontMetrics(f); + SwingUtilities.calculateInnerArea(m, br); + SwingUtilities.calculateInsetArea(br, m.getInsets(), vr); + paintBackground(g, m, m.getBackground()); + + /* MenuItems insets are equal to menuItems margin, space between text and + menuItems border. We need to paint insets region as well. */ + Insets insets = m.getInsets(); + br.x -= insets.left; + br.y -= insets.top; + br.width += insets.right + insets.left; + br.height += insets.top + insets.bottom; + + // Menu item is considered to be highlighted when it is selected. + if (m.isSelected() || m.getModel().isArmed() && + (m.getParent() instanceof MenuElement)) + { + if (m.isContentAreaFilled()) + { + g.setColor(selectionBackground); + g.fillRect(br.x, br.y, br.width, br.height); + } + } + else + { + if (m.isContentAreaFilled()) + { + g.setColor(m.getBackground()); + g.fillRect(br.x, br.y, br.width, br.height); + } + } + + // If this menu item is a JCheckBoxMenuItem then paint check icon + if (checkIcon != null) + { + SwingUtilities.layoutCompoundLabel(m, fm, null, checkIcon, vertAlign, + horAlign, vertTextPos, horTextPos, + vr, cr, tr, defaultTextIconGap); + checkIcon.paintIcon(m, g, cr.x, cr.y); + + // We need to calculate position of the menu text and position of + // user menu icon if there exists one relative to the check icon. + // So we need to adjust view rectangle s.t. its starting point is at + // checkIcon.width + defaultTextIconGap. + vr.x = cr.x + cr.width + defaultTextIconGap; + } + + // if this is a submenu, then paint arrow icon to indicate it. + if (arrowIcon != null && (c instanceof JMenu)) + { + if (! ((JMenu) c).isTopLevelMenu()) + { + int width = arrowIcon.getIconWidth(); + int height = arrowIcon.getIconHeight(); + + arrowIcon.paintIcon(m, g, vr.width - width + defaultTextIconGap, + vr.y + 2); + } + } + + // paint text and user menu icon if it exists + Icon i = m.getIcon(); + SwingUtilities.layoutCompoundLabel(c, fm, m.getText(), i, + vertAlign, horAlign, vertTextPos, + horTextPos, vr, ir, tr, + defaultTextIconGap); + if (i != null) + i.paintIcon(c, g, ir.x, ir.y); + + paintText(g, m, tr, m.getText()); + + // paint accelerator + String acceleratorText = ""; + + if (m.getAccelerator() != null) + { + acceleratorText = getAcceleratorText(m.getAccelerator()); + fm = g.getFontMetrics(acceleratorFont); + ar.width = fm.stringWidth(acceleratorText); + ar.x = br.width - ar.width; + vr.x = br.width - ar.width; + + SwingUtilities.layoutCompoundLabel(m, fm, acceleratorText, null, + vertAlign, horAlign, vertTextPos, + horTextPos, vr, ir, ar, + defaultTextIconGap); + + paintAccelerator(g, m, ar, acceleratorText); + } + } + + /** + * Paints label for the given menu item + * + * @param g The graphics context used to paint this menu item + * @param menuItem menu item for which to draw its label + * @param textRect rectangle specifiying position of the text relative to + * the given menu item + * @param text label of the menu item + */ + protected void paintText(Graphics g, JMenuItem menuItem, Rectangle textRect, + String text) + { + Font f = menuItem.getFont(); + g.setFont(f); + FontMetrics fm = g.getFontMetrics(f); + + if (text != null && ! text.equals("")) + { + if (menuItem.isEnabled()) + { + // Menu item is considered to be highlighted when it is selected. + if (menuItem.isSelected() || menuItem.getModel().isArmed() && + (menuItem.getParent() instanceof MenuElement)) + g.setColor(selectionForeground); + else + g.setColor(menuItem.getForeground()); + } + else + // FIXME: should fix this to use 'disabledForeground', but its + // default value in BasicLookAndFeel is null. + + // FIXME: should there be different foreground colours for selected + // or deselected, when disabled? + g.setColor(Color.gray); + + int mnemonicIndex = menuItem.getDisplayedMnemonicIndex(); + + if (mnemonicIndex != -1) + BasicGraphicsUtils.drawStringUnderlineCharAt(g, text, mnemonicIndex, + textRect.x, + textRect.y + + fm.getAscent()); + else + BasicGraphicsUtils.drawString(g, text, 0, textRect.x, + textRect.y + fm.getAscent()); + } + } + + /** + * This method uninstalls the components for this {@link JMenuItem}. + * + * @param menuItem The {@link JMenuItem} to uninstall components for. + */ + protected void uninstallComponents(JMenuItem menuItem) + { + // FIXME: need to implement + } + + /** + * This method uninstalls the defaults and sets any objects created during + * install to null + */ + protected void uninstallDefaults() + { + menuItem.setForeground(null); + menuItem.setBackground(null); + menuItem.setBorder(null); + menuItem.setMargin(null); + menuItem.setBackground(null); + menuItem.setBorder(null); + menuItem.setFont(null); + menuItem.setForeground(null); + menuItem.setMargin(null); + acceleratorFont = null; + acceleratorForeground = null; + acceleratorSelectionForeground = null; + arrowIcon = null; + selectionBackground = null; + selectionForeground = null; + acceleratorDelimiter = null; + } + + /** + * Uninstalls any keyboard actions. + */ + protected void uninstallKeyboardActions() + { + // FIXME: need to implement + } + + /** + * Unregisters all the listeners that this UI delegate was using. + */ + protected void uninstallListeners() + { + menuItem.removeMouseListener(mouseInputListener); + menuItem.removeMenuDragMouseListener(menuDragMouseListener); + menuItem.removeMenuKeyListener(menuKeyListener); + menuItem.removePropertyChangeListener(propertyChangeListener); + } + + /** + * Performs the opposite of installUI. Any properties or resources that need + * to be cleaned up will be done now. It will also uninstall any listeners + * it has. In addition, any properties of this UI will be nulled. + * + * @param c The {@link JComponent} that is having this UI uninstalled. + */ + public void uninstallUI(JComponent c) + { + uninstallListeners(); + uninstallDefaults(); + uninstallComponents(menuItem); + menuItem = null; + } + + /** + * This method calls paint. + * + * @param g The graphics context used to paint this menu item + * @param c The menu item to paint + */ + public void update(Graphics g, JComponent c) + { + paint(g, c); + } + + /** + * Return text representation of the specified accelerator + * + * @param accelerator Accelerator for which to return string representation + * + * @return $String$ Text representation of the given accelerator + */ + private String getAcceleratorText(KeyStroke accelerator) + { + // convert keystroke into string format + String modifiersText = ""; + int modifiers = accelerator.getModifiers(); + char keyChar = accelerator.getKeyChar(); + int keyCode = accelerator.getKeyCode(); + + if (modifiers != 0) + modifiersText = KeyEvent.getKeyModifiersText(modifiers) + + acceleratorDelimiter; + + if (keyCode == KeyEvent.VK_UNDEFINED) + return modifiersText + keyChar; + else + return modifiersText + KeyEvent.getKeyText(keyCode); + } + + /** + * Calculates and return rectange in which accelerator should be displayed + * + * @param accelerator accelerator for which to return the display rectangle + * @param fm The font metrics used to measure the text + * + * @return $Rectangle$ reactangle which will be used to display accelerator + */ + private Rectangle getAcceleratorRect(KeyStroke accelerator, FontMetrics fm) + { + int width = fm.stringWidth(getAcceleratorText(accelerator)); + int height = fm.getHeight(); + return new Rectangle(0, 0, width, height); + } + + /** + * Paints accelerator inside menu item + * + * @param g The graphics context used to paint the border + * @param menuItem Menu item for which to draw accelerator + * @param acceleratorRect rectangle representing position + * of the accelerator relative to the menu item + * @param acceleratorText accelerator's text + */ + private void paintAccelerator(Graphics g, JMenuItem menuItem, + Rectangle acceleratorRect, + String acceleratorText) + { + g.setFont(acceleratorFont); + FontMetrics fm = g.getFontMetrics(acceleratorFont); + + if (menuItem.isEnabled()) + g.setColor(acceleratorForeground); + else + // FIXME: should fix this to use 'disabledForeground', but its + // default value in BasicLookAndFeel is null. + g.setColor(Color.gray); + + BasicGraphicsUtils.drawString(g, acceleratorText, 0, acceleratorRect.x, + acceleratorRect.y + fm.getAscent()); + } + + /** + * This class handles mouse events occuring inside the menu item. + * Most of the events are forwarded for processing to MenuSelectionManager + * of the current menu hierarchy. + * + */ + protected class MouseInputHandler implements MouseInputListener + { + /** + * Creates a new MouseInputHandler object. + */ + protected MouseInputHandler() + { + } + + /** + * This method is called when mouse is clicked on the menu item. + * It forwards this event to MenuSelectionManager. + * + * @param e A {@link MouseEvent}. + */ + public void mouseClicked(MouseEvent e) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.processMouseEvent(e); + } + + /** + * This method is called when mouse is dragged inside the menu item. + * It forwards this event to MenuSelectionManager. + * + * @param e A {@link MouseEvent}. + */ + public void mouseDragged(MouseEvent e) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.processMouseEvent(e); + } + + /** + * This method is called when mouse enters menu item. + * When this happens menu item is considered to be selected and selection path + * in MenuSelectionManager is set. This event is also forwarded to MenuSelection + * Manager for further processing. + * + * @param e A {@link MouseEvent}. + */ + public void mouseEntered(MouseEvent e) + { + Component source = (Component) e.getSource(); + if (source.getParent() instanceof MenuElement) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.setSelectedPath(getPath()); + manager.processMouseEvent(e); + } + } + + /** + * This method is called when mouse exits menu item. The event is + * forwarded to MenuSelectionManager for processing. + * + * @param e A {@link MouseEvent}. + */ + public void mouseExited(MouseEvent e) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.processMouseEvent(e); + } + + /** + * This method is called when mouse is inside the menu item. + * This event is forwarder to MenuSelectionManager for further processing. + * + * @param e A {@link MouseEvent}. + */ + public void mouseMoved(MouseEvent e) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.processMouseEvent(e); + } + + /** + * This method is called when mouse is pressed. This event is forwarded to + * MenuSelectionManager for further processing. + * + * @param e A {@link MouseEvent}. + */ + public void mousePressed(MouseEvent e) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.processMouseEvent(e); + } + + /** + * This method is called when mouse is released. If the mouse is released + * inside this menuItem, then this menu item is considered to be chosen and + * the menu hierarchy should be closed. + * + * @param e A {@link MouseEvent}. + */ + public void mouseReleased(MouseEvent e) + { + Rectangle size = menuItem.getBounds(); + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + if (e.getX() > 0 && e.getX() < size.width && e.getY() > 0 + && e.getY() < size.height) + { + manager.clearSelectedPath(); + menuItem.doClick(); + } + + else + manager.processMouseEvent(e); + } + } + + /** + * This class handles mouse dragged events. + */ + protected class MenuDragMouseHandler implements MenuDragMouseListener + { + /** + * Tbis method is invoked when mouse is dragged over the menu item. + * + * @param e The MenuDragMouseEvent + */ + public void menuDragMouseDragged(MenuDragMouseEvent e) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.setSelectedPath(e.getPath()); + } + + /** + * Tbis method is invoked when mouse enters the menu item while it is + * being dragged. + * + * @param e The MenuDragMouseEvent + */ + public void menuDragMouseEntered(MenuDragMouseEvent e) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.setSelectedPath(e.getPath()); + } + + /** + * Tbis method is invoked when mouse exits the menu item while + * it is being dragged + * + * @param e The MenuDragMouseEvent + */ + public void menuDragMouseExited(MenuDragMouseEvent e) + { + } + + /** + * Tbis method is invoked when mouse was dragged and released + * inside the menu item. + * + * @param e The MenuDragMouseEvent + */ + public void menuDragMouseReleased(MenuDragMouseEvent e) + { + MenuElement[] path = e.getPath(); + + if (path[path.length - 1] instanceof JMenuItem) + ((JMenuItem) path[path.length - 1]).doClick(); + + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.clearSelectedPath(); + } + } + + /** + * This class handles key events occuring when menu item is visible on the + * screen. + */ + protected class MenuKeyHandler implements MenuKeyListener + { + /** + * This method is invoked when key has been pressed + * + * @param e A {@link MenuKeyEvent}. + */ + public void menuKeyPressed(MenuKeyEvent e) + { + } + + /** + * This method is invoked when key has been pressed + * + * @param e A {@link MenuKeyEvent}. + */ + public void menuKeyReleased(MenuKeyEvent e) + { + } + + /** + * This method is invoked when key has been typed + * It handles the mnemonic key for the menu item. + * + * @param e A {@link MenuKeyEvent}. + */ + public void menuKeyTyped(MenuKeyEvent e) + { + } + } + + /** + * Helper class that listens for changes to the properties of the {@link + * JMenuItem}. + */ + protected class PropertyChangeHandler implements PropertyChangeListener + { + /** + * This method is called when one of the menu item's properties change. + * + * @param evt A {@link PropertyChangeEvent}. + */ + public void propertyChange(PropertyChangeEvent evt) + { + menuItem.revalidate(); + menuItem.repaint(); + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicMenuUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicMenuUI.java new file mode 100644 index 0000000..6bd15ed --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicMenuUI.java @@ -0,0 +1,541 @@ +/* BasicMenuUI.java + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Dimension; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.JComponent; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JPopupMenu; +import javax.swing.MenuSelectionManager; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.MenuDragMouseEvent; +import javax.swing.event.MenuDragMouseListener; +import javax.swing.event.MenuEvent; +import javax.swing.event.MenuKeyEvent; +import javax.swing.event.MenuKeyListener; +import javax.swing.event.MenuListener; +import javax.swing.event.MouseInputListener; +import javax.swing.plaf.ComponentUI; + +/** + * UI Delegate for JMenu + */ +public class BasicMenuUI extends BasicMenuItemUI +{ + protected ChangeListener changeListener; + + /* MenuListener listens to MenuEvents fired by JMenu */ + protected MenuListener menuListener; + + /* PropertyChangeListner that listens to propertyChangeEvents occuring in JMenu*/ + protected PropertyChangeListener propertyChangeListener; + + /** + * Creates a new BasicMenuUI object. + */ + public BasicMenuUI() + { + mouseInputListener = createMouseInputListener((JMenu) menuItem); + menuListener = createMenuListener((JMenu) menuItem); + propertyChangeListener = createPropertyChangeListener((JMenu) menuItem); + } + + /** + * This method creates a new ChangeListener. + * + * @return A new ChangeListener. + */ + protected ChangeListener createChangeListener(JComponent c) + { + return new ChangeHandler(); + } + + /** + * This method creates new MenuDragMouseListener to listen to mouse dragged events + * occuring in the Menu + * + * @param c the menu to listen to + * + * @return The MenuDrageMouseListener + */ + protected MenuDragMouseListener createMenuDragMouseListener(JComponent c) + { + return new MenuDragMouseHandler(); + } + + /** + * This method creates new MenuDragKeyListener to listen to key events + * + * @param c the menu to listen to + * + * @return The MenuKeyListener + */ + protected MenuKeyListener createMenuKeyListener(JComponent c) + { + return new MenuKeyHandler(); + } + + /** + * This method creates new MenuListener to listen to menu events + * occuring in the Menu + * + * @param c the menu to listen to + * + * @return The MenuListener + */ + protected MenuListener createMenuListener(JComponent c) + { + return new MenuHandler(); + } + + /** + * This method creates new MouseInputListener to listen to mouse input events + * occuring in the Menu + * + * @param c the menu to listen to + * + * @return The MouseInputListener + */ + protected MouseInputListener createMouseInputListener(JComponent c) + { + return new MouseInputHandler(); + } + + /** + * This method creates newPropertyChangeListener to listen to property changes + * occuring in the Menu + * + * @param c the menu to listen to + * + * @return The PropertyChangeListener + */ + protected PropertyChangeListener createPropertyChangeListener(JComponent c) + { + return new PropertyChangeHandler(); + } + + /** + * This method creates a new BasicMenuUI. + * + * @param c The JComponent to create a UI for. + * + * @return A new BasicMenuUI. + */ + public static ComponentUI createUI(JComponent c) + { + return new BasicMenuUI(); + } + + /** + * Get the component's maximum size. + * + * @param c The JComponent for which to get maximum size + * + * @return The maximum size of the component + */ + public Dimension getMaximumSize(JComponent c) + { + return c.getPreferredSize(); + } + + protected String getPropertyPrefix() + { + return null; + } + + /** + * Initializes any default properties that this UI has from the defaults for + * the Basic look and feel. + */ + protected void installDefaults() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + menuItem.setBackground(defaults.getColor("Menu.background")); + menuItem.setBorder(defaults.getBorder("Menu.border")); + menuItem.setFont(defaults.getFont("Menu.font")); + menuItem.setForeground(defaults.getColor("Menu.foreground")); + menuItem.setMargin(defaults.getInsets("Menu.margin")); + acceleratorFont = defaults.getFont("Menu.acceleratorFont"); + acceleratorForeground = defaults.getColor("Menu.acceleratorForeground"); + acceleratorSelectionForeground = defaults.getColor("Menu.acceleratorSelectionForeground"); + selectionBackground = defaults.getColor("Menu.selectionBackground"); + selectionForeground = defaults.getColor("Menu.selectionForeground"); + arrowIcon = defaults.getIcon("Menu.arrowIcon"); + oldBorderPainted = defaults.getBoolean("Menu.borderPainted"); + menuItem.setOpaque(true); + } + + /** + * Installs any keyboard actions. The list of keys that need to be bound are + * listed in Basic look and feel's defaults. + * + */ + protected void installKeyboardActions() + { + // FIXME: Need to implement + } + + /** + * Creates and registers all the listeners for this UI delegate. + */ + protected void installListeners() + { + ((JMenu) menuItem).addMouseListener(mouseInputListener); + ((JMenu) menuItem).addMouseMotionListener(mouseInputListener); + ((JMenu) menuItem).addMenuListener(menuListener); + ((JMenu) menuItem).addMenuDragMouseListener(menuDragMouseListener); + } + + protected void setupPostTimer(JMenu menu) + { + } + + /** + * This method uninstalls the defaults and sets any objects created during + * install to null + */ + protected void uninstallDefaults() + { + menuItem.setBackground(null); + menuItem.setBorder(null); + menuItem.setFont(null); + menuItem.setForeground(null); + menuItem.setMargin(null); + acceleratorFont = null; + acceleratorForeground = null; + acceleratorSelectionForeground = null; + selectionBackground = null; + selectionForeground = null; + arrowIcon = null; + } + + /** + * Uninstalls any keyboard actions. The list of keys used are listed in + * Basic look and feel's defaults. + */ + protected void uninstallKeyboardActions() + { + // FIXME: Need to implement + } + + /** + * Unregisters all the listeners that this UI delegate was using. In + * addition, it will also null any listeners that it was using. + */ + protected void uninstallListeners() + { + ((JMenu) menuItem).removeMouseListener(mouseInputListener); + ((JMenu) menuItem).removeMenuListener(menuListener); + ((JMenu) menuItem).removePropertyChangeListener(propertyChangeListener); + } + + /** + * This class is used by menus to handle mouse events occuring in the + * menu. + */ + protected class MouseInputHandler implements MouseInputListener + { + public void mouseClicked(MouseEvent e) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.processMouseEvent(e); + } + + public void mouseDragged(MouseEvent e) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.processMouseEvent(e); + } + + private boolean popupVisible() + { + JMenuBar mb = (JMenuBar) ((JMenu)menuItem).getParent(); + // check if mb.isSelected because if no menus are selected + // we don't have to look through the list for popup menus + if (!mb.isSelected()) + return false; + for (int i=0;i<mb.getMenuCount();i++) + if (((JMenu)mb.getComponent(i)).isPopupMenuVisible()) + return true; + return false; + } + + public void mouseEntered(MouseEvent e) + { + /* When mouse enters menu item, it should be considered selected + + if (i) if this menu is a submenu in some other menu + (ii) or if this menu is in a menu bar and some other menu in a + menu bar was just selected and has its popup menu visible. + (If nothing was selected, menu should be pressed before + it will be selected) + */ + JMenu menu = (JMenu) menuItem; + + // NOTE: the following if used to require !menu.isArmed but I could find + // no reason for this and it was preventing some JDK-compatible behaviour. + // Specifically, if a menu is selected but its popup menu not visible, + // and then another menu is selected whose popup menu IS visible, when + // the mouse is moved over the first menu, its popup menu should become + // visible. + + if (! menu.isTopLevelMenu() || popupVisible()) + { + // set new selection and forward this event to MenuSelectionManager + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.setSelectedPath(getPath()); + manager.processMouseEvent(e); + } + } + + public void mouseExited(MouseEvent e) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.processMouseEvent(e); + } + + public void mouseMoved(MouseEvent e) + { + } + + public void mousePressed(MouseEvent e) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + JMenu menu = (JMenu) menuItem; + manager.processMouseEvent(e); + + // Menu should be displayed when the menu is pressed only if + // it is top-level menu + if (menu.isTopLevelMenu()) + { + if (menu.getPopupMenu().isVisible()) + // If menu is visible and menu button was pressed.. + // then need to cancel the menu + manager.clearSelectedPath(); + else + { + // Display the menu + int x = 0; + int y = menu.getHeight(); + + manager.setSelectedPath(getPath()); + + JMenuBar mb = (JMenuBar) menu.getParent(); + + // set selectedIndex of the selectionModel of a menuBar + mb.getSelectionModel().setSelectedIndex(mb.getComponentIndex(menu)); + } + } + } + + public void mouseReleased(MouseEvent e) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.processMouseEvent(e); + } + } + + /** + * This class handles MenuEvents fired by the JMenu + */ + protected class MenuHandler implements MenuListener + { + /** + * This method is called when menu is cancelled. The menu is cancelled + * when its popup menu is closed without selection. It clears selected index + * in the selectionModel of the menu parent. + * + * @param e The MenuEvent. + */ + public void menuCanceled(MenuEvent e) + { + menuDeselected(e); + } + + /** + * This method is called when menu is deselected. It clears selected index + * in the selectionModel of the menu parent. + * + * @param e The MenuEvent. + */ + public void menuDeselected(MenuEvent e) + { + JMenu menu = (JMenu) menuItem; + if (menu.isTopLevelMenu()) + ((JMenuBar) menu.getParent()).getSelectionModel().clearSelection(); + else + ((JPopupMenu) menu.getParent()).getSelectionModel().clearSelection(); + } + + /** + * This method is called when menu is selected. It sets selected index + * in the selectionModel of the menu parent. + * + * @param e The MenuEvent. + */ + public void menuSelected(MenuEvent e) + { + JMenu menu = (JMenu) menuItem; + if (menu.isTopLevelMenu()) + ((JMenuBar) menu.getParent()).setSelected(menu); + else + ((JPopupMenu) menu.getParent()).setSelected(menu); + } + } + + /** + * This class handles PropertyChangeEvents fired from the JMenu + */ + protected class PropertyChangeHandler implements PropertyChangeListener + { + /** + * This method is called whenever one of the properties of the menu item + * changes. + * + * @param e The PropertyChangeEvent. + */ + public void propertyChange(PropertyChangeEvent e) + { + } + } + + /** + * @deprecated + */ + public class ChangeHandler implements ChangeListener + { + public void stateChanged(ChangeEvent e) + { + // FIXME: It seems that this class is not used anywhere + } + } + + /** + * This class handles mouse dragged events occuring in the menu. + */ + protected class MenuDragMouseHandler implements MenuDragMouseListener + { + /** + * This method is invoked when mouse is dragged over the menu item. + * + * @param e The MenuDragMouseEvent + */ + public void menuDragMouseDragged(MenuDragMouseEvent e) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.setSelectedPath(e.getPath()); + } + + /** + * This method is invoked when mouse enters the menu item while it is + * being dragged. + * + * @param e The MenuDragMouseEvent + */ + public void menuDragMouseEntered(MenuDragMouseEvent e) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.setSelectedPath(e.getPath()); + } + + /** + * This method is invoked when mouse exits the menu item while + * it is being dragged + * + * @param e The MenuDragMouseEvent + */ + public void menuDragMouseExited(MenuDragMouseEvent e) + { + } + + /** + * This method is invoked when mouse was dragged and released + * inside the menu item. + * + * @param e The MenuDragMouseEvent + */ + public void menuDragMouseReleased(MenuDragMouseEvent e) + { + } + } + + /** + * This class handles key events occuring when menu item is visible on the + * screen. + */ + protected class MenuKeyHandler implements MenuKeyListener + { + /** + * This method is invoked when key has been pressed + * + * @param e A {@link MenuKeyEvent}. + */ + public void menuKeyPressed(MenuKeyEvent e) + { + } + + /** + * This method is invoked when key has been pressed + * + * @param e A {@link MenuKeyEvent}. + */ + public void menuKeyReleased(MenuKeyEvent e) + { + } + + /** + * This method is invoked when key has been typed + * It handles the mnemonic key for the menu item. + * + * @param e A {@link MenuKeyEvent}. + */ + public void menuKeyTyped(MenuKeyEvent e) + { + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicOptionPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicOptionPaneUI.java new file mode 100644 index 0000000..ce29f24 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicOptionPaneUI.java @@ -0,0 +1,1329 @@ +/* BasicOptionPaneUI.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.LayoutManager; +import java.awt.Polygon; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyVetoException; + +import javax.swing.BorderFactory; +import javax.swing.Box; +import javax.swing.BoxLayout; +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JInternalFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.border.Border; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.OptionPaneUI; + +/** + * This class is the UI delegate for JOptionPane in the Basic Look and Feel. + */ +public class BasicOptionPaneUI extends OptionPaneUI +{ + /** + * This is a helper class that listens to the buttons located at the bottom + * of the JOptionPane. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class ButtonActionListener implements ActionListener + { + /** The index of the option this button represents. */ + protected int buttonIndex; + + /** + * Creates a new ButtonActionListener object with the given buttonIndex. + * + * @param buttonIndex The index of the option this button represents. + */ + public ButtonActionListener(int buttonIndex) + { + this.buttonIndex = buttonIndex; + } + + /** + * This method is called when one of the option buttons are pressed. + * + * @param e The ActionEvent. + */ + public void actionPerformed(ActionEvent e) + { + Object value = new Integer(JOptionPane.CLOSED_OPTION); + Object[] options = optionPane.getOptions(); + if (options != null) + value = new Integer(buttonIndex); + else + { + String text = ((JButton) e.getSource()).getText(); + if (text.equals(OK_STRING)) + value = new Integer(JOptionPane.OK_OPTION); + if (text.equals(CANCEL_STRING)) + value = new Integer(JOptionPane.CANCEL_OPTION); + if (text.equals(YES_STRING)) + value = new Integer(JOptionPane.YES_OPTION); + if (text.equals(NO_STRING)) + value = new Integer(JOptionPane.NO_OPTION); + } + optionPane.setValue(value); + resetInputValue(); + + Window owner = SwingUtilities.windowForComponent(optionPane); + + if (owner instanceof JDialog) + ((JDialog) owner).dispose(); + + //else we probably have some kind of internal frame. + JInternalFrame inf = (JInternalFrame) SwingUtilities.getAncestorOfClass(JInternalFrame.class, + optionPane); + if (inf != null) + { + try + { + inf.setClosed(true); + } + catch (PropertyVetoException pve) + { + } + } + } + } + + /** + * This helper layout manager is responsible for the layout of the button + * area. The button area is the panel that holds the buttons which + * represent the options. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public static class ButtonAreaLayout implements LayoutManager + { + /** Whether this layout will center the buttons. */ + protected boolean centersChildren = true; + + /** The space between the buttons. */ + protected int padding; + + /** Whether the buttons will share the same widths. */ + protected boolean syncAllWidths; + + /** The width of the widest button. */ + private transient int widthOfWidestButton; + + /** The height of the tallest button. */ + private transient int tallestButton; + + /** + * Creates a new ButtonAreaLayout object with the given sync widths + * property and padding. + * + * @param syncAllWidths Whether the buttons will share the same widths. + * @param padding The padding between the buttons. + */ + public ButtonAreaLayout(boolean syncAllWidths, int padding) + { + this.syncAllWidths = syncAllWidths; + this.padding = padding; + } + + /** + * This method is called when a component is added to the container. + * + * @param string The constraints string. + * @param comp The component added. + */ + public void addLayoutComponent(String string, Component comp) + { + // Do nothing. + } + + /** + * This method returns whether the children will be centered. + * + * @return Whether the children will be centered. + */ + public boolean getCentersChildren() + { + return centersChildren; + } + + /** + * This method returns the amount of space between components. + * + * @return The amount of space between components. + */ + public int getPadding() + { + return padding; + } + + /** + * This method returns whether all components will share widths (set to + * largest width). + * + * @return Whether all components will share widths. + */ + public boolean getSyncAllWidths() + { + return syncAllWidths; + } + + /** + * This method lays out the given container. + * + * @param container The container to lay out. + */ + public void layoutContainer(Container container) + { + Component[] buttonList = container.getComponents(); + int x = container.getInsets().left; + if (getCentersChildren()) + x += (int) ((double) (container.getSize().width) / 2 + - (double) (buttonRowLength(container)) / 2); + for (int i = 0; i < buttonList.length; i++) + { + Dimension dims = buttonList[i].getPreferredSize(); + if (syncAllWidths) + { + buttonList[i].setBounds(x, 0, widthOfWidestButton, dims.height); + x += widthOfWidestButton + getPadding(); + } + else + { + buttonList[i].setBounds(x, 0, dims.width, dims.height); + x += dims.width + getPadding(); + } + } + } + + /** + * This method returns the width of the given container taking into + * consideration the padding and syncAllWidths. + * + * @param c The container to calculate width for. + * + * @return The width of the given container. + */ + private int buttonRowLength(Container c) + { + Component[] buttonList = c.getComponents(); + + int buttonLength = 0; + int widest = 0; + int tallest = 0; + + for (int i = 0; i < buttonList.length; i++) + { + Dimension dims = buttonList[i].getPreferredSize(); + buttonLength += dims.width + getPadding(); + widest = Math.max(widest, dims.width); + tallest = Math.max(tallest, dims.height); + } + + widthOfWidestButton = widest; + tallestButton = tallest; + + int width; + if (getSyncAllWidths()) + width = widest * buttonList.length + + getPadding() * (buttonList.length - 1); + else + width = buttonLength; + + Insets insets = c.getInsets(); + width += insets.left + insets.right; + + return width; + } + + /** + * This method returns the minimum layout size for the given container. + * + * @param c The container to measure. + * + * @return The minimum layout size. + */ + public Dimension minimumLayoutSize(Container c) + { + return preferredLayoutSize(c); + } + + /** + * This method returns the preferred size of the given container. + * + * @param c The container to measure. + * + * @return The preferred size. + */ + public Dimension preferredLayoutSize(Container c) + { + int w = buttonRowLength(c); + + return new Dimension(w, tallestButton); + } + + /** + * This method removes the given component from the layout manager's + * knowledge. + * + * @param c The component to remove. + */ + public void removeLayoutComponent(Component c) + { + // Do nothing. + } + + /** + * This method sets whether the children will be centered. + * + * @param newValue Whether the children will be centered. + */ + public void setCentersChildren(boolean newValue) + { + centersChildren = newValue; + } + + /** + * This method sets the amount of space between each component. + * + * @param newPadding The padding between components. + */ + public void setPadding(int newPadding) + { + padding = newPadding; + } + + /** + * This method sets whether the widths will be synced. + * + * @param newValue Whether the widths will be synced. + */ + public void setSyncAllWidths(boolean newValue) + { + syncAllWidths = newValue; + } + } + + /** + * This helper class handles property change events from the JOptionPane. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class PropertyChangeHandler implements PropertyChangeListener + { + /** + * This method is called when one of the properties of the JOptionPane + * changes. + * + * @param e The PropertyChangeEvent. + */ + public void propertyChange(PropertyChangeEvent e) + { + if (e.getPropertyName().equals(JOptionPane.ICON_PROPERTY) + || e.getPropertyName().equals(JOptionPane.MESSAGE_TYPE_PROPERTY)) + addIcon(messageAreaContainer); + else if (e.getPropertyName().equals(JOptionPane.INITIAL_SELECTION_VALUE_PROPERTY)) + resetSelectedValue(); + else if (e.getPropertyName().equals(JOptionPane.INITIAL_VALUE_PROPERTY) + || e.getPropertyName().equals(JOptionPane.OPTIONS_PROPERTY) + || e.getPropertyName().equals(JOptionPane.OPTION_TYPE_PROPERTY)) + { + Container newButtons = createButtonArea(); + optionPane.remove(buttonContainer); + optionPane.add(newButtons); + buttonContainer = newButtons; + } + + else if (e.getPropertyName().equals(JOptionPane.MESSAGE_PROPERTY) + || e.getPropertyName().equals(JOptionPane.WANTS_INPUT_PROPERTY) + || e.getPropertyName().equals(JOptionPane.SELECTION_VALUES_PROPERTY)) + { + optionPane.removeAll(); + messageAreaContainer = createMessageArea(); + optionPane.add(messageAreaContainer); + optionPane.add(buttonContainer); + } + optionPane.invalidate(); + optionPane.repaint(); + } + } + + /** Whether the JOptionPane contains custom components. */ + protected boolean hasCustomComponents = false; + + // The initialFocusComponent seems to always be set to a button (even if + // I try to set initialSelectionValue). This is different from what the + // javadocs state (which should switch this reference to the input component + // if one is present since that is what's going to get focus). + + /** + * The button that will receive focus based on initialValue when no input + * component is present. If an input component is present, then the input + * component will receive focus instead. + */ + protected Component initialFocusComponent; + + /** The component that receives input when the JOptionPane needs it. */ + protected JComponent inputComponent; + + /** The minimum height of the JOptionPane. */ + public static int minimumHeight; + + /** The minimum width of the JOptionPane. */ + public static int minimumWidth; + + /** The minimum dimensions of the JOptionPane. */ + protected Dimension minimumSize; + + /** The propertyChangeListener for the JOptionPane. */ + protected PropertyChangeListener propertyChangeListener; + + /** The JOptionPane this UI delegate is used for. */ + protected JOptionPane optionPane; + + /** The size of the icons. */ + // FIXME: wrong name for a constant. + private static final int iconSize = 36; + + /** The foreground color for the message area. */ + private transient Color messageForeground; + + /** The border around the message area. */ + private transient Border messageBorder; + + /** The border around the button area. */ + private transient Border buttonBorder; + + /** The string used to describe OK buttons. */ + private static final String OK_STRING = "OK"; + + /** The string used to describe Yes buttons. */ + private static final String YES_STRING = "Yes"; + + /** The string used to describe No buttons. */ + private static final String NO_STRING = "No"; + + /** The string used to describe Cancel buttons. */ + private static final String CANCEL_STRING = "Cancel"; + + /** The container for the message area. + * This is package-private to avoid an accessor method. */ + transient Container messageAreaContainer; + + /** The container for the buttons. + * This is package-private to avoid an accessor method. */ + transient Container buttonContainer; + + /** + * A helper class that implements Icon. This is used temporarily until + * ImageIcons are fixed. + */ + private static class MessageIcon implements Icon + { + /** + * This method returns the width of the icon. + * + * @return The width of the icon. + */ + public int getIconWidth() + { + return iconSize; + } + + /** + * This method returns the height of the icon. + * + * @return The height of the icon. + */ + public int getIconHeight() + { + return iconSize; + } + + /** + * This method paints the icon as a part of the given component using the + * given graphics and the given x and y position. + * + * @param c The component that owns this icon. + * @param g The Graphics object to paint with. + * @param x The x coordinate. + * @param y The y coordinate. + */ + public void paintIcon(Component c, Graphics g, int x, int y) + { + } + } + + /** The icon displayed for ERROR_MESSAGE. */ + private static MessageIcon errorIcon = new MessageIcon() + { + public void paintIcon(Component c, Graphics g, int x, int y) + { + Polygon oct = new Polygon(new int[] { 0, 0, 9, 27, 36, 36, 27, 9 }, + new int[] { 9, 27, 36, 36, 27, 9, 0, 0 }, 8); + g.translate(x, y); + + Color saved = g.getColor(); + g.setColor(Color.RED); + + g.fillPolygon(oct); + + g.setColor(Color.BLACK); + g.drawRect(13, 16, 10, 4); + + g.setColor(saved); + g.translate(-x, -y); + } + }; + + /** The icon displayed for INFORMATION_MESSAGE. */ + private static MessageIcon infoIcon = new MessageIcon() + { + public void paintIcon(Component c, Graphics g, int x, int y) + { + g.translate(x, y); + Color saved = g.getColor(); + + // Should be purple. + g.setColor(Color.RED); + + g.fillOval(0, 0, iconSize, iconSize); + + g.setColor(Color.BLACK); + g.drawOval(16, 6, 4, 4); + + Polygon bottomI = new Polygon(new int[] { 15, 15, 13, 13, 23, 23, 21, 21 }, + new int[] { 12, 28, 28, 30, 30, 28, 28, 12 }, + 8); + g.drawPolygon(bottomI); + + g.setColor(saved); + g.translate(-x, -y); + } + }; + + /** The icon displayed for WARNING_MESSAGE. */ + private static MessageIcon warningIcon = new MessageIcon() + { + public void paintIcon(Component c, Graphics g, int x, int y) + { + g.translate(x, y); + Color saved = g.getColor(); + g.setColor(Color.YELLOW); + + Polygon triangle = new Polygon(new int[] { 0, 18, 36 }, + new int[] { 36, 0, 36 }, 3); + g.fillPolygon(triangle); + + g.setColor(Color.BLACK); + + Polygon excl = new Polygon(new int[] { 15, 16, 20, 21 }, + new int[] { 8, 26, 26, 8 }, 4); + g.drawPolygon(excl); + g.drawOval(16, 30, 4, 4); + + g.setColor(saved); + g.translate(-x, -y); + } + }; + + /** The icon displayed for MESSAGE_ICON. */ + private static MessageIcon questionIcon = new MessageIcon() + { + public void paintIcon(Component c, Graphics g, int x, int y) + { + g.translate(x, y); + Color saved = g.getColor(); + g.setColor(Color.GREEN); + + g.fillRect(0, 0, iconSize, iconSize); + + g.setColor(Color.BLACK); + + g.drawOval(11, 2, 16, 16); + g.drawOval(14, 5, 10, 10); + + g.setColor(Color.GREEN); + g.fillRect(0, 10, iconSize, iconSize - 10); + + g.setColor(Color.BLACK); + + g.drawLine(11, 10, 14, 10); + + g.drawLine(24, 10, 17, 22); + g.drawLine(27, 10, 20, 22); + g.drawLine(17, 22, 20, 22); + + g.drawOval(17, 25, 3, 3); + + g.setColor(saved); + g.translate(-x, -y); + } + }; + + // FIXME: Uncomment when the ImageIcons are fixed. + + /* IconUIResource warningIcon, questionIcon, infoIcon, errorIcon;*/ + + /** + * Creates a new BasicOptionPaneUI object. + */ + public BasicOptionPaneUI() + { + } + + /** + * This method is messaged to add the buttons to the given container. + * + * @param container The container to add components to. + * @param buttons The buttons to add. (If it is an instance of component, + * the Object is added directly. If it is an instance of Icon, it is + * packed into a label and added. For all other cases, the string + * representation of the Object is retreived and packed into a + * label.) + * @param initialIndex The index of the component that is the initialValue. + */ + protected void addButtonComponents(Container container, Object[] buttons, + int initialIndex) + { + if (buttons == null) + return; + for (int i = 0; i < buttons.length; i++) + { + if (buttons[i] != null) + { + Component toAdd; + if (buttons[i] instanceof Component) + toAdd = (Component) buttons[i]; + else + { + if (buttons[i] instanceof Icon) + toAdd = new JButton((Icon) buttons[i]); + else + toAdd = new JButton(buttons[i].toString()); + hasCustomComponents = true; + } + if (toAdd instanceof JButton) + ((JButton) toAdd).addActionListener(createButtonActionListener(i)); + if (i == initialIndex) + initialFocusComponent = toAdd; + container.add(toAdd); + } + } + selectInitialValue(optionPane); + } + + /** + * This method adds the appropriate icon the given container. + * + * @param top The container to add an icon to. + */ + protected void addIcon(Container top) + { + JLabel iconLabel = null; + Icon icon = getIcon(); + if (icon != null) + { + iconLabel = new JLabel(icon); + top.add(iconLabel, BorderLayout.WEST); + } + } + + /** + * A helper method that returns an instance of GridBagConstraints to be used + * for creating the message area. + * + * @return An instance of GridBagConstraints. + */ + private static GridBagConstraints createConstraints() + { + GridBagConstraints constraints = new GridBagConstraints(); + constraints.gridx = GridBagConstraints.REMAINDER; + constraints.gridy = GridBagConstraints.REMAINDER; + constraints.gridwidth = 0; + constraints.anchor = GridBagConstraints.LINE_START; + constraints.fill = GridBagConstraints.NONE; + constraints.insets = new Insets(0, 0, 3, 0); + + return constraints; + } + + /** + * This method creates the proper object (if necessary) to represent msg. + * (If msg is an instance of Component, it will add it directly. If it is + * an icon, then it will pack it in a label and add it. Otherwise, it gets + * treated as a string. If the string is longer than maxll, a box is + * created and the burstStringInto is called with the box as the container. + * The box is then added to the given container. Otherwise, the string is + * packed in a label and placed in the given container.) This method is + * also used for adding the inputComponent to the container. + * + * @param container The container to add to. + * @param cons The constraints when adding. + * @param msg The message to add. + * @param maxll The max line length. + * @param internallyCreated Whether the msg is internally created. + */ + protected void addMessageComponents(Container container, + GridBagConstraints cons, Object msg, + int maxll, boolean internallyCreated) + { + if (msg == null) + return; + hasCustomComponents = internallyCreated; + if (msg instanceof Object[]) + { + Object[] arr = (Object[]) msg; + for (int i = 0; i < arr.length; i++) + addMessageComponents(container, cons, arr[i], maxll, + internallyCreated); + return; + } + else if (msg instanceof Component) + { + container.add((Component) msg, cons); + cons.gridy++; + } + else if (msg instanceof Icon) + { + container.add(new JLabel((Icon) msg), cons); + cons.gridy++; + } + else + { + // Undocumented behaviour. + // if msg.toString().length greater than maxll + // it will create a box and burst the string. + // otherwise, it will just create a label and re-call + // this method with the label o.O + if (msg.toString().length() > maxll) + { + Box tmp = new Box(BoxLayout.Y_AXIS); + burstStringInto(tmp, msg.toString(), maxll); + addMessageComponents(container, cons, tmp, maxll, true); + } + else + addMessageComponents(container, cons, new JLabel(msg.toString()), + maxll, true); + } + } + + /** + * This method creates instances of d (recursively if necessary based on + * maxll) and adds to c. + * + * @param c The container to add to. + * @param d The string to burst. + * @param maxll The max line length. + */ + protected void burstStringInto(Container c, String d, int maxll) + { + // FIXME: Verify that this is the correct behaviour. + // One interpretation of the spec is that this method + // should recursively call itself to create (and add) + // JLabels to the container if the length of the String d + // is greater than maxll. + // but in practice, even with a really long string, this is + // all that happens. + if (d == null || c == null) + return; + JLabel label = new JLabel(d); + c.add(label); + } + + /** + * This method returns true if the given JOptionPane contains custom + * components. + * + * @param op The JOptionPane to check. + * + * @return True if the JOptionPane contains custom components. + */ + public boolean containsCustomComponents(JOptionPane op) + { + return hasCustomComponents; + } + + /** + * This method creates a button action listener for the given button index. + * + * @param buttonIndex The index of the button in components. + * + * @return A new ButtonActionListener. + */ + protected ActionListener createButtonActionListener(int buttonIndex) + { + return new ButtonActionListener(buttonIndex); + } + + /** + * This method creates the button area. + * + * @return A new Button Area. + */ + protected Container createButtonArea() + { + JPanel buttonPanel = new JPanel(); + + buttonPanel.setLayout(createLayoutManager()); + addButtonComponents(buttonPanel, getButtons(), getInitialValueIndex()); + + return buttonPanel; + } + + /** + * This method creates a new LayoutManager for the button area. + * + * @return A new LayoutManager for the button area. + */ + protected LayoutManager createLayoutManager() + { + return new ButtonAreaLayout(getSizeButtonsToSameWidth(), 6); + } + + /** + * This method creates the message area. + * + * @return A new message area. + */ + protected Container createMessageArea() + { + JPanel messageArea = new JPanel(); + messageArea.setLayout(new BorderLayout()); + addIcon(messageArea); + + JPanel rightSide = new JPanel(); + rightSide.setBorder(BorderFactory.createEmptyBorder(0, 11, 17, 0)); + rightSide.setLayout(new GridBagLayout()); + GridBagConstraints con = createConstraints(); + + addMessageComponents(rightSide, con, getMessage(), + getMaxCharactersPerLineCount(), false); + + if (optionPane.getWantsInput()) + { + Object[] selection = optionPane.getSelectionValues(); + + if (selection == null) + inputComponent = new JTextField(15); + else if (selection.length < 20) + inputComponent = new JComboBox(selection); + else + inputComponent = new JList(selection); + if (inputComponent != null) + { + addMessageComponents(rightSide, con, inputComponent, + getMaxCharactersPerLineCount(), false); + resetSelectedValue(); + selectInitialValue(optionPane); + } + } + + messageArea.add(rightSide, BorderLayout.EAST); + + return messageArea; + } + + /** + * This method creates a new PropertyChangeListener for listening to the + * JOptionPane. + * + * @return A new PropertyChangeListener. + */ + protected PropertyChangeListener createPropertyChangeListener() + { + return new PropertyChangeHandler(); + } + + /** + * This method creates a Container that will separate the message and button + * areas. + * + * @return A Container that will separate the message and button areas. + */ + protected Container createSeparator() + { + return (Container) Box.createVerticalStrut(17); + } + + /** + * This method creates a new BasicOptionPaneUI for the given component. + * + * @param x The component to create a UI for. + * + * @return A new BasicOptionPaneUI. + */ + public static ComponentUI createUI(JComponent x) + { + return new BasicOptionPaneUI(); + } + + /** + * This method returns the buttons for the JOptionPane. If no options are + * set, a set of options will be created based upon the optionType. + * + * @return The buttons that will be added. + */ + protected Object[] getButtons() + { + if (optionPane.getOptions() != null) + return optionPane.getOptions(); + switch (optionPane.getOptionType()) + { + case JOptionPane.YES_NO_OPTION: + return new Object[] { YES_STRING, NO_STRING }; + case JOptionPane.YES_NO_CANCEL_OPTION: + return new Object[] { YES_STRING, NO_STRING, CANCEL_STRING }; + case JOptionPane.OK_CANCEL_OPTION: + case JOptionPane.DEFAULT_OPTION: + return new Object[] { OK_STRING, CANCEL_STRING }; + } + return null; + } + + /** + * This method will return the icon the user has set or the icon that will + * be used based on message type. + * + * @return The icon to use in the JOptionPane. + */ + protected Icon getIcon() + { + if (optionPane.getIcon() != null) + return optionPane.getIcon(); + else + return getIconForType(optionPane.getMessageType()); + } + + /** + * This method returns the icon for the given messageType. + * + * @param messageType The type of message. + * + * @return The icon for the given messageType. + */ + protected Icon getIconForType(int messageType) + { + Icon tmp = null; + switch (messageType) + { + case JOptionPane.ERROR_MESSAGE: + tmp = errorIcon; + break; + case JOptionPane.INFORMATION_MESSAGE: + tmp = infoIcon; + break; + case JOptionPane.WARNING_MESSAGE: + tmp = warningIcon; + break; + case JOptionPane.QUESTION_MESSAGE: + tmp = questionIcon; + break; + } + return tmp; + // FIXME: Don't cast till the default icons are in. + // return new IconUIResource(tmp); + } + + /** + * This method returns the index of the initialValue in the options array. + * + * @return The index of the initalValue. + */ + protected int getInitialValueIndex() + { + Object[] buttons = getButtons(); + + if (buttons == null) + return -1; + + Object select = optionPane.getInitialValue(); + + for (int i = 0; i < buttons.length; i++) + { + if (select == buttons[i]) + return i; + } + return 0; + } + + /** + * This method returns the maximum number of characters that should be + * placed on a line. + * + * @return The maximum number of characteres that should be placed on a + * line. + */ + protected int getMaxCharactersPerLineCount() + { + return optionPane.getMaxCharactersPerLineCount(); + } + + /** + * This method returns the maximum size. + * + * @param c The JComponent to measure. + * + * @return The maximum size. + */ + public Dimension getMaximumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the message of the JOptionPane. + * + * @return The message. + */ + protected Object getMessage() + { + return optionPane.getMessage(); + } + + /** + * This method returns the minimum size of the JOptionPane. + * + * @return The minimum size. + */ + public Dimension getMinimumOptionPaneSize() + { + return minimumSize; + } + + /** + * This method returns the minimum size. + * + * @param c The JComponent to measure. + * + * @return The minimum size. + */ + public Dimension getMinimumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the preferred size of the JOptionPane. The preferred + * size is the maximum of the size desired by the layout and the minimum + * size. + * + * @param c The JComponent to measure. + * + * @return The preferred size. + */ + public Dimension getPreferredSize(JComponent c) + { + Dimension d = optionPane.getLayout().preferredLayoutSize(optionPane); + Dimension d2 = getMinimumOptionPaneSize(); + + int w = Math.max(d.width, d2.width); + int h = Math.max(d.height, d2.height); + return new Dimension(w, h); + } + + /** + * This method returns whether all buttons should have the same width. + * + * @return Whether all buttons should have the same width. + */ + protected boolean getSizeButtonsToSameWidth() + { + return true; + } + + /** + * This method installs components for the JOptionPane. + */ + protected void installComponents() + { + // reset it. + hasCustomComponents = false; + Container msg = createMessageArea(); + if (msg != null) + { + ((JComponent) msg).setBorder(messageBorder); + msg.setForeground(messageForeground); + messageAreaContainer = msg; + optionPane.add(msg); + } + + Container sep = createSeparator(); + if (sep != null) + optionPane.add(sep); + + Container button = createButtonArea(); + if (button != null) + { + ((JComponent) button).setBorder(buttonBorder); + buttonContainer = button; + optionPane.add(button); + } + + optionPane.setBorder(BorderFactory.createEmptyBorder(12, 12, 11, 11)); + optionPane.invalidate(); + } + + /** + * This method installs defaults for the JOptionPane. + */ + protected void installDefaults() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + optionPane.setFont(defaults.getFont("OptionPane.font")); + optionPane.setBackground(defaults.getColor("OptionPane.background")); + optionPane.setForeground(defaults.getColor("OptionPane.foreground")); + optionPane.setBorder(defaults.getBorder("OptionPane.border")); + optionPane.setOpaque(true); + + messageBorder = defaults.getBorder("OptionPane.messageAreaBorder"); + messageForeground = defaults.getColor("OptionPane.messageForeground"); + buttonBorder = defaults.getBorder("OptionPane.buttonAreaBorder"); + + minimumSize = defaults.getDimension("OptionPane.minimumSize"); + minimumWidth = minimumSize.width; + minimumHeight = minimumSize.height; + + // FIXME: Image icons don't seem to work properly right now. + // Once they do, replace the synthetic icons with these ones. + + /* + warningIcon = (IconUIResource) defaults.getIcon("OptionPane.warningIcon"); + infoIcon = (IconUIResource) defaults.getIcon("OptionPane.informationIcon"); + errorIcon = (IconUIResource) defaults.getIcon("OptionPane.errorIcon"); + questionIcon = (IconUIResource) defaults.getIcon("OptionPane.questionIcon"); + */ + } + + /** + * This method installs keyboard actions for the JOptionpane. + */ + protected void installKeyboardActions() + { + // FIXME: implement. + } + + /** + * This method installs listeners for the JOptionPane. + */ + protected void installListeners() + { + propertyChangeListener = createPropertyChangeListener(); + + optionPane.addPropertyChangeListener(propertyChangeListener); + } + + /** + * This method installs the UI for the JOptionPane. + * + * @param c The JComponent to install the UI for. + */ + public void installUI(JComponent c) + { + if (c instanceof JOptionPane) + { + optionPane = (JOptionPane) c; + + installDefaults(); + installComponents(); + installListeners(); + installKeyboardActions(); + } + } + + /** + * Changes the inputValue property in the JOptionPane based on the current + * value of the inputComponent. + */ + protected void resetInputValue() + { + if (optionPane.getWantsInput() && inputComponent != null) + { + Object output = null; + if (inputComponent instanceof JTextField) + output = ((JTextField) inputComponent).getText(); + else if (inputComponent instanceof JComboBox) + output = ((JComboBox) inputComponent).getSelectedItem(); + else if (inputComponent instanceof JList) + output = ((JList) inputComponent).getSelectedValue(); + + if (output != null) + optionPane.setInputValue(output); + } + } + + /** + * This method requests focus to the inputComponent (if one is present) and + * the initialFocusComponent otherwise. + * + * @param op The JOptionPane. + */ + public void selectInitialValue(JOptionPane op) + { + if (inputComponent != null) + { + inputComponent.requestFocus(); + return; + } + if (initialFocusComponent != null) + initialFocusComponent.requestFocus(); + } + + /** + * This method resets the value in the inputComponent to the + * initialSelectionValue property. + * This is package-private to avoid an accessor method. + */ + void resetSelectedValue() + { + if (inputComponent != null) + { + Object init = optionPane.getInitialSelectionValue(); + if (init == null) + return; + if (inputComponent instanceof JTextField) + ((JTextField) inputComponent).setText((String) init); + else if (inputComponent instanceof JComboBox) + ((JComboBox) inputComponent).setSelectedItem(init); + else if (inputComponent instanceof JList) + { + // ((JList) inputComponent).setSelectedValue(init, true); + } + } + } + + /** + * This method uninstalls all the components in the JOptionPane. + */ + protected void uninstallComponents() + { + optionPane.removeAll(); + buttonContainer = null; + messageAreaContainer = null; + } + + /** + * This method uninstalls the defaults for the JOptionPane. + */ + protected void uninstallDefaults() + { + optionPane.setFont(null); + optionPane.setForeground(null); + optionPane.setBackground(null); + + minimumSize = null; + + messageBorder = null; + buttonBorder = null; + messageForeground = null; + + // FIXME: ImageIcons don't seem to work properly + + /* + warningIcon = null; + errorIcon = null; + questionIcon = null; + infoIcon = null; + */ + } + + /** + * This method uninstalls keyboard actions for the JOptionPane. + */ + protected void uninstallKeyboardActions() + { + // FIXME: implement. + } + + /** + * This method uninstalls listeners for the JOptionPane. + */ + protected void uninstallListeners() + { + optionPane.removePropertyChangeListener(propertyChangeListener); + propertyChangeListener = null; + } + + /** + * This method uninstalls the UI for the given JComponent. + * + * @param c The JComponent to uninstall for. + */ + public void uninstallUI(JComponent c) + { + uninstallKeyboardActions(); + uninstallListeners(); + uninstallComponents(); + uninstallDefaults(); + + optionPane = null; + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicPanelUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicPanelUI.java new file mode 100644 index 0000000..0896721 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicPanelUI.java @@ -0,0 +1,67 @@ +/* BasicPanelUI.java + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.PanelUI; + +public class BasicPanelUI extends PanelUI +{ + public static ComponentUI createUI(JComponent x) + { + return new BasicPanelUI(); + } + + public void installUI(JComponent c) + { + super.installUI(c); + if (c instanceof JPanel) + { + JPanel p = (JPanel) c; + installDefaults(p); + } + } + + public void installDefaults(JPanel p) + { + p.setOpaque(true); + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicPasswordFieldUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicPasswordFieldUI.java new file mode 100644 index 0000000..044027b --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicPasswordFieldUI.java @@ -0,0 +1,67 @@ +/* BasicPasswordFieldUI.java + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.text.Element; +import javax.swing.text.PasswordView; +import javax.swing.text.View; + +public class BasicPasswordFieldUI extends BasicTextFieldUI +{ + public BasicPasswordFieldUI() + { + } + + public View create(Element elem) + { + return new PasswordView(elem); + } + + public static ComponentUI createUI(JComponent c) + { + return new BasicPasswordFieldUI(); + } + + protected String getPropertyPrefix() + { + return "PasswordField"; + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuSeparatorUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuSeparatorUI.java new file mode 100644 index 0000000..b629477 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuSeparatorUI.java @@ -0,0 +1,114 @@ +/* BasicPopupMenuSeparatorUI.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Rectangle; + +import javax.swing.JComponent; +import javax.swing.JPopupMenu; +import javax.swing.SwingUtilities; +import javax.swing.plaf.ComponentUI; + +/** + * The Basic Look and Feel UI delegate for JPopupMenu.Separator. + */ +public class BasicPopupMenuSeparatorUI extends BasicSeparatorUI +{ + /** + * Creates a new BasicPopupMenuSeparatorUI object. + */ + public BasicPopupMenuSeparatorUI() + { + super(); + } + + /** + * Creates a new UI delegate for the given JComponent. + * + * @param c The JComponent to create a delegate for. + * + * @return A new BasicPopupMenuSeparatorUI + */ + public static ComponentUI createUI(JComponent c) + { + return new BasicPopupMenuSeparatorUI(); + } + + /** + * The Popup Menu Separator has two lines. The top line will be + * painted using highlight color and the bottom using shadow color. + * + * @param g The Graphics object to paint with + * @param c The JComponent to paint. + */ + public void paint(Graphics g, JComponent c) + { + if (! (c instanceof JPopupMenu.Separator)) + return; + + Rectangle r = new Rectangle(); + SwingUtilities.calculateInnerArea(c, r); + Color saved = g.getColor(); + + int midAB = r.width / 2 + r.x; + int midAD = r.height / 2 + r.y; + + g.setColor(highlight); + g.drawLine(r.x, midAD, r.x + r.width, midAD); + + g.setColor(shadow); + g.drawLine(r.x, midAD + 1, r.x + r.width, midAD + 1); + } + + /** + * This method returns the preferred size of the + * JComponent. + * + * @param c The JComponent to measure. + * + * @return The preferred size. + */ + public Dimension getPreferredSize(JComponent c) + { + return super.getPreferredSize(c); + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuUI.java new file mode 100644 index 0000000..247117b --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuUI.java @@ -0,0 +1,674 @@ +/* BasicPopupMenuUI.java + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf.basic; + +import java.awt.AWTEvent; +import java.awt.Component; +import java.awt.Container; +import java.awt.Cursor; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.awt.event.MouseEvent; + +import javax.swing.BoxLayout; +import javax.swing.JComponent; +import javax.swing.JLayeredPane; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.MenuElement; +import javax.swing.MenuSelectionManager; +import javax.swing.RootPaneContainer; +import javax.swing.SwingUtilities; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.event.MouseInputListener; +import javax.swing.event.PopupMenuEvent; +import javax.swing.event.PopupMenuListener; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.PopupMenuUI; + + +/** + * UI Delegate for JPopupMenu + */ +public class BasicPopupMenuUI extends PopupMenuUI +{ + /* popupMenu for which this UI delegate is for*/ + protected JPopupMenu popupMenu; + + /* MouseInputListener listens to mouse events. Package private for inner classes. */ + static transient MouseInputListener mouseInputListener; + + /* PopupMenuListener listens to popup menu events fired by JPopupMenu*/ + private transient PopupMenuListener popupMenuListener; + + /* ComponentListener listening to popupMenu's invoker. + * This is package-private to avoid an accessor method. */ + TopWindowListener topWindowListener; + + /** + * Creates a new BasicPopupMenuUI object. + */ + public BasicPopupMenuUI() + { + popupMenuListener = new PopupMenuHandler(); + topWindowListener = new TopWindowListener(); + } + + /** + * Factory method to create a BasicPopupMenuUI for the given {@link + * JComponent}, which should be a {@link JMenuItem}. + * + * @param x The {@link JComponent} a UI is being created for. + * + * @return A BasicPopupMenuUI for the {@link JComponent}. + */ + public static ComponentUI createUI(JComponent x) + { + return new BasicPopupMenuUI(); + } + + /** + * Installs and initializes all fields for this UI delegate. Any properties + * of the UI that need to be initialized and/or set to defaults will be + * done now. It will also install any listeners necessary. + * + * @param c The {@link JComponent} that is having this UI installed. + */ + public void installUI(JComponent c) + { + super.installUI(c); + popupMenu = (JPopupMenu) c; + popupMenu.setLayout(new DefaultMenuLayout(popupMenu, BoxLayout.Y_AXIS)); + popupMenu.setBorderPainted(true); + JPopupMenu.setDefaultLightWeightPopupEnabled(true); + + installDefaults(); + installListeners(); + } + + /** + * This method installs the defaults that are defined in the Basic look + * and feel for this {@link JPopupMenu}. + */ + public void installDefaults() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + popupMenu.setBackground(defaults.getColor("PopupMenu.background")); + popupMenu.setBorder(defaults.getBorder("PopupMenu.border")); + popupMenu.setFont(defaults.getFont("PopupMenu.font")); + popupMenu.setForeground(defaults.getColor("PopupMenu.foreground")); + popupMenu.setOpaque(true); + } + + /** + * This method installs the listeners for the {@link JMenuItem}. + */ + protected void installListeners() + { + popupMenu.addPopupMenuListener(popupMenuListener); + } + + /** + * This method installs the keyboard actions for this {@link JPopupMenu}. + */ + protected void installKeyboardActions() + { + // FIXME: Need to implement + } + + /** + * Performs the opposite of installUI. Any properties or resources that need + * to be cleaned up will be done now. It will also uninstall any listeners + * it has. In addition, any properties of this UI will be nulled. + * + * @param c The {@link JComponent} that is having this UI uninstalled. + */ + public void uninstallUI(JComponent c) + { + uninstallListeners(); + uninstallDefaults(); + popupMenu = null; + } + + /** + * This method uninstalls the defaults and sets any objects created during + * install to null + */ + protected void uninstallDefaults() + { + popupMenu.setBackground(null); + popupMenu.setBorder(null); + popupMenu.setFont(null); + popupMenu.setForeground(null); + } + + /** + * Unregisters all the listeners that this UI delegate was using. + */ + protected void uninstallListeners() + { + popupMenu.removePopupMenuListener(popupMenuListener); + } + + /** + * Uninstalls any keyboard actions. + */ + protected void uninstallKeyboardActions() + { + // FIXME: Need to implement + } + + /** + * This method returns the minimum size of the JPopupMenu. + * + * @param c The JComponent to find a size for. + * + * @return The minimum size. + */ + public Dimension getMinimumSize(JComponent c) + { + return null; + } + + /** + * This method returns the preferred size of the JPopupMenu. + * + * @param c The JComponent to find a size for. + * + * @return The preferred size. + */ + public Dimension getPreferredSize(JComponent c) + { + return null; + } + + /** + * This method returns the minimum size of the JPopupMenu. + * + * @param c The JComponent to find a size for. + * + * @return The minimum size. + */ + public Dimension getMaximumSize(JComponent c) + { + return null; + } + + /** + * Return true if given mouse event is a platform popup trigger, and false + * otherwise + * + * @param e MouseEvent that is to be checked for popup trigger event + * + * @return true if given mouse event is a platform popup trigger, and false + * otherwise + */ + public boolean isPopupTrigger(MouseEvent e) + { + return false; + } + + /** + * This listener handles PopupMenuEvents fired by JPopupMenu + */ + private class PopupMenuHandler implements PopupMenuListener + { + /** + * This method is invoked when JPopupMenu is cancelled. + * + * @param event the PopupMenuEvent + */ + public void popupMenuCanceled(PopupMenuEvent event) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.clearSelectedPath(); + } + + /** + * This method is invoked when JPopupMenu becomes invisible + * + * @param event the PopupMenuEvent + */ + public void popupMenuWillBecomeInvisible(PopupMenuEvent event) + { + // remove listener that listens to component events fired + // by the top - level window that this popup belongs to. + Component invoker = popupMenu.getInvoker(); + + RootPaneContainer rootContainer = (RootPaneContainer) SwingUtilities + .getRoot(invoker); + ((Container) rootContainer).removeComponentListener(topWindowListener); + + // If this popup menu is the last popup menu visible on the screen, then + // stop interrupting mouse events in the glass pane before hiding this + // last popup menu. + boolean topLevelMenu = (popupMenu.getInvoker() instanceof JMenu) + && ((JMenu) popupMenu.getInvoker()) + .isTopLevelMenu(); + + if (topLevelMenu || ! (popupMenu.getInvoker() instanceof MenuElement)) + { + // set glass pane not to interrupt mouse events and remove + // mouseInputListener + Container glassPane = (Container) rootContainer.getGlassPane(); + glassPane.setVisible(false); + glassPane.removeMouseListener(mouseInputListener); + mouseInputListener = null; + } + } + + /** + * This method is invoked when JPopupMenu becomes visible + * + * @param event the PopupMenuEvent + */ + public void popupMenuWillBecomeVisible(PopupMenuEvent event) + { + // Adds topWindowListener to top-level window to listener to + // ComponentEvents fired by it. We need to cancel this popup menu + // if topWindow to which this popup belongs was resized or moved. + Component invoker = popupMenu.getInvoker(); + RootPaneContainer rootContainer = (RootPaneContainer) SwingUtilities + .getRoot(invoker); + ((Container) rootContainer).addComponentListener(topWindowListener); + + // Set the glass pane to interrupt all mouse events originating in root + // container + if (mouseInputListener == null) + { + Container glassPane = (Container) rootContainer.getGlassPane(); + glassPane.setVisible(true); + mouseInputListener = new MouseInputHandler(rootContainer); + glassPane.addMouseListener(mouseInputListener); + glassPane.addMouseMotionListener(mouseInputListener); + } + + // if this popup menu is a free floating popup menu, + // then by default its first element should be always selected when + // this popup menu becomes visible. + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + + if (manager.getSelectedPath().length == 0) + { + // Set selected path to point to the first item in the popup menu + MenuElement[] path = new MenuElement[2]; + path[0] = popupMenu; + Component[] comps = popupMenu.getComponents(); + if (comps.length != 0 && comps[0] instanceof MenuElement) + { + path[1] = (MenuElement) comps[0]; + manager.setSelectedPath(path); + } + } + } + } + + /** + * ComponentListener that listens to Component Events fired by the top - + * level window to which popup menu belongs. If top-level window was + * resized, moved or hidded then popup menu will be hidded and selected + * path of current menu hierarchy will be set to null. + */ + private class TopWindowListener implements ComponentListener + { + /** + * This method is invoked when top-level window is resized. This method + * closes current menu hierarchy. + * + * @param e The ComponentEvent + */ + public void componentResized(ComponentEvent e) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.clearSelectedPath(); + } + + /** + * This method is invoked when top-level window is moved. This method + * closes current menu hierarchy. + * + * @param e The ComponentEvent + */ + public void componentMoved(ComponentEvent e) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.clearSelectedPath(); + } + + /** + * This method is invoked when top-level window is shown This method + * does nothing by default. + * + * @param e The ComponentEvent + */ + public void componentShown(ComponentEvent e) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.clearSelectedPath(); + } + + /** + * This method is invoked when top-level window is hidden This method + * closes current menu hierarchy. + * + * @param e The ComponentEvent + */ + public void componentHidden(ComponentEvent e) + { + MenuSelectionManager manager = MenuSelectionManager.defaultManager(); + manager.clearSelectedPath(); + } + } + + /** + * MouseInputHandler listens to all mouse events originated in the root + * container. This class is responsible for closing menu hierarchy when the + * user presses mouse over any component that do not belong to the current + * menu hierarchy. This is acomplished by interrupting all mouse event in + * the glass pane and checking if other component was pressed while menu + * was open, before redestributing events further to intended components + */ + private class MouseInputHandler implements MouseInputListener + { + private JLayeredPane layeredPane; + private Container glassPane; + private Cursor nativeCursor; + private transient Component mouseEventTarget; + private transient Component pressedComponent; + private transient Component lastComponentEntered; + private transient Component tempComponent; + private transient int pressCount; + + /** + * Creates a new MouseInputHandler object. + * + * @param c the top most root container + */ + public MouseInputHandler(RootPaneContainer c) + { + layeredPane = c.getLayeredPane(); + glassPane = (Container) c.getGlassPane(); + } + + /** + * Handles mouse clicked event + * + * @param e Mouse event + */ + public void mouseClicked(MouseEvent e) + { + handleEvent(e); + } + + /** + * Handles mouseDragged event + * + * @param e MouseEvent + */ + public void mouseDragged(MouseEvent e) + { + handleEvent(e); + } + + /** + * Handles mouseEntered event + * + * @param e MouseEvent + */ + public void mouseEntered(MouseEvent e) + { + handleEvent(e); + } + + /** + * Handles mouseExited event + * + * @param e MouseEvent + */ + public void mouseExited(MouseEvent e) + { + handleEvent(e); + } + + /** + * Handles mouse moved event + * + * @param e MouseEvent + */ + public void mouseMoved(MouseEvent e) + { + handleEvent(e); + } + + /** + * Handles mouse pressed event + * + * @param e MouseEvent + */ + public void mousePressed(MouseEvent e) + { + handleEvent(e); + } + + /** + * Handles mouse released event + * + * @param e MouseEvent + */ + public void mouseReleased(MouseEvent e) + { + handleEvent(e); + } + + /* + * This method determines component that was intended to received mouse + * event, before it was interrupted within the glass pane. This method + * also redispatches mouse entered and mouse exited events to the + * appropriate components. This code is slightly modified code from + * Container.LightweightDispatcher class, which is private inside + * Container class and cannot be used here. + */ + public void acquireComponentForMouseEvent(MouseEvent me) + { + int x = me.getX(); + int y = me.getY(); + + // Find the candidate which should receive this event. + Component parent = layeredPane; + Component candidate = null; + Point p = me.getPoint(); + while ((candidate == null) && (parent != null)) + { + p = SwingUtilities.convertPoint(glassPane, p.x, p.y, parent); + candidate = SwingUtilities.getDeepestComponentAt(parent, p.x, p.y); + + if (candidate == null) + { + p = SwingUtilities.convertPoint(parent, p.x, p.y, + parent.getParent()); + parent = parent.getParent(); + } + } + + // If the only candidate we found was the native container itself, + // don't dispatch any event at all. We only care about the lightweight + // children here. + if (candidate == layeredPane) + candidate = null; + + // If our candidate is new, inform the old target we're leaving. + if ((lastComponentEntered != null) && lastComponentEntered.isShowing() + && (lastComponentEntered != candidate)) + { + // Old candidate could have been removed from + // the layeredPane so we check first. + if (SwingUtilities.isDescendingFrom(lastComponentEntered, layeredPane)) + { + Point tp = SwingUtilities.convertPoint(layeredPane, x, y, + lastComponentEntered); + MouseEvent exited = new MouseEvent(lastComponentEntered, + MouseEvent.MOUSE_EXITED, + me.getWhen(), + me.getModifiersEx(), tp.x, + tp.y, me.getClickCount(), + me.isPopupTrigger(), + me.getButton()); + + tempComponent = lastComponentEntered; + lastComponentEntered = null; + tempComponent.dispatchEvent(exited); + } + + lastComponentEntered = null; + } + + // If we have a candidate, maybe enter it. + if (candidate != null) + { + mouseEventTarget = candidate; + + if (candidate.isLightweight() && candidate.isShowing() + && (candidate != layeredPane) + && (candidate != lastComponentEntered)) + { + lastComponentEntered = mouseEventTarget; + + Point cp = SwingUtilities.convertPoint(layeredPane, x, y, + lastComponentEntered); + MouseEvent entered = new MouseEvent(lastComponentEntered, + MouseEvent.MOUSE_ENTERED, + me.getWhen(), + me.getModifiersEx(), cp.x, + cp.y, me.getClickCount(), + me.isPopupTrigger(), + me.getButton()); + lastComponentEntered.dispatchEvent(entered); + } + } + + if ((me.getID() == MouseEvent.MOUSE_RELEASED) + || ((me.getID() == MouseEvent.MOUSE_PRESSED) && (pressCount > 0)) + || (me.getID() == MouseEvent.MOUSE_DRAGGED)) + { + // If any of the following events occur while a button is held down, + // they should be dispatched to the same component to which the + // original MOUSE_PRESSED event was dispatched: + // - MOUSE_RELEASED + // - MOUSE_PRESSED: another button pressed while the first is held down + // - MOUSE_DRAGGED + if (SwingUtilities.isDescendingFrom(pressedComponent, layeredPane)) + mouseEventTarget = pressedComponent; + else if (me.getID() == MouseEvent.MOUSE_CLICKED) + { + // Don't dispatch CLICKED events whose target is not the same as the + // target for the original PRESSED event. + if (candidate != pressedComponent) + mouseEventTarget = null; + else if (pressCount == 0) + pressedComponent = null; + } + } + } + + /* + * This method handles mouse events interrupted by glassPane. It + * redispatches the mouse events appropriately to the intended components. + * The code in this method is also taken from + * Container.LightweightDispatcher class. The code is slightly modified + * to handle the case when mouse is released over non-menu component. In + * this case this method closes current menu hierarchy before + * redispatching the event further. + */ + public void handleEvent(AWTEvent e) + { + if (e instanceof MouseEvent) + { + MouseEvent me = (MouseEvent) e; + + acquireComponentForMouseEvent(me); + + // Avoid dispatching ENTERED and EXITED events twice. + if (mouseEventTarget != null && mouseEventTarget.isShowing() + && (e.getID() != MouseEvent.MOUSE_ENTERED) + && (e.getID() != MouseEvent.MOUSE_EXITED)) + { + MouseEvent newEvt = SwingUtilities.convertMouseEvent(glassPane, + me, + mouseEventTarget); + + mouseEventTarget.dispatchEvent(newEvt); + + // If mouse was clicked over the component that is not part + // of menu hierarchy,then must close the menu hierarchy */ + if (e.getID() == MouseEvent.MOUSE_RELEASED) + { + boolean partOfMenuHierarchy = false; + MenuSelectionManager manager = MenuSelectionManager + .defaultManager(); + + partOfMenuHierarchy = manager.isComponentPartOfCurrentMenu(mouseEventTarget); + + if (! partOfMenuHierarchy) + manager.clearSelectedPath(); + } + + switch (e.getID()) + { + case MouseEvent.MOUSE_PRESSED: + if (pressCount++ == 0) + pressedComponent = mouseEventTarget; + break; + case MouseEvent.MOUSE_RELEASED: + // Clear our memory of the original PRESSED event, only if + // we're not expecting a CLICKED event after this. If + // there is a CLICKED event after this, it will do clean up. + if ((--pressCount == 0) + && (mouseEventTarget != pressedComponent)) + pressedComponent = null; + break; + } + } + } + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicProgressBarUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicProgressBarUI.java new file mode 100644 index 0000000..d00628f --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicProgressBarUI.java @@ -0,0 +1,827 @@ +/* BasicProgressBarUI.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.font.FontRenderContext; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.JComponent; +import javax.swing.JProgressBar; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.Timer; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.ProgressBarUI; + +/** + * The Basic Look and Feel UI delegate for the + * JProgressBar. + */ +public class BasicProgressBarUI extends ProgressBarUI +{ + /** + * A helper class that listens for ChangeEvents + * from the progressBar's model. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class ChangeHandler implements ChangeListener + { + /** + * Called every time the state of the model changes. + * + * @param e The ChangeEvent given by the model. + */ + public void stateChanged(ChangeEvent e) + { + // Nothing to do but repaint. + progressBar.repaint(); + } + } + + /** + * This helper class is used to listen for + * PropertyChangeEvents from the progressBar. + */ + private class PropertyChangeHandler implements PropertyChangeListener + { + /** + * Called every time the properties of the + * progressBar change. + * + * @param e The PropertyChangeEvent given by the progressBar. + */ + public void propertyChange(PropertyChangeEvent e) + { + // Only need to listen for indeterminate changes. + // All other things are done on a repaint. + if (e.getPropertyName().equals("inderterminate")) + if (((Boolean) e.getNewValue()).booleanValue()) + startAnimationTimer(); + else + stopAnimationTimer(); + else + progressBar.repaint(); + } + } + + /** + * This helper class is used to listen for + * the animationTimer's intervals. On every interval, + * the bouncing box should move. + */ + private class Animator implements ActionListener + { + /** + * Called every time the animationTimer reaches + * its interval. + * + * @param e The ActionEvent given by the timer. + */ + public void actionPerformed(ActionEvent e) + { + // Incrementing the animation index will cause + // a repaint. + incrementAnimationIndex(); + } + } + + /** The timer used to move the bouncing box. */ + private transient Timer animationTimer; + + // The total number of frames must be an even number. + // The total number of frames is calculated from + // the cycleTime and repaintInterval given by + // the basic Look and Feel defaults. + // + // +-----------------------------------------------+ + // | frame0 | frame1 | frame2 | frame 3 | frame 4 | + // | | frame7 | frame6 | frame 5 | | + // +-----------------------------------------------+ + + /** The current animation index. */ + private transient int animationIndex; + + /** The total number of frames.*/ + private transient int numFrames; + + /** The helper that moves the bouncing box. */ + private transient Animator animation; + + /** The helper that listens for property change events. */ + private transient PropertyChangeHandler propertyListener; + + /** The Listener for the model. */ + protected ChangeListener changeListener; + + /** The progressBar for this UI. */ + protected JProgressBar progressBar; + + /** The length of the cell. The cell is the painted part. */ + private transient int cellLength; + + /** The gap between cells. */ + private transient int cellSpacing; + + /** The color of the text when the bar is not over it.*/ + private transient Color selectionBackground; + + /** The color of the text when the bar is over it. */ + private transient Color selectionForeground; + + /** + * Creates a new BasicProgressBarUI object. + */ + public BasicProgressBarUI() + { + super(); + } + + /** + * Creates a new BasicProgressBarUI for the component. + * + * @param x The JComponent to create the UI for. + * + * @return A new BasicProgressBarUI. + */ + public static ComponentUI createUI(JComponent x) + { + return new BasicProgressBarUI(); + } + + /** + * This method returns the length of the bar (from the minimum) + * in pixels (or units that the Graphics object draws in) based + * on the progressBar's getPercentComplete() value. + * + * @param b The insets of the progressBar. + * @param width The width of the progressBar. + * @param height The height of the progressBar. + * + * @return The length of the bar that should be painted in pixels. + */ + protected int getAmountFull(Insets b, int width, int height) + { + double percentDone = progressBar.getPercentComplete(); + if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) + return (int) (percentDone * (width - b.left - b.right)); + else + return (int) (percentDone * (height - b.top - b.bottom)); + } + + /** + * The current animation index. + * + * @return The current animation index. + */ + protected int getAnimationIndex() + { + return animationIndex; + } + + /** + * This method returns the size and position of the bouncing box + * for the current animation index. It stores the values in the + * given rectangle and returns it. It returns null if no box should + * be drawn. + * + * @param r The bouncing box rectangle. + * + * @return The bouncing box rectangle. + */ + protected Rectangle getBox(Rectangle r) + { + if (!progressBar.isIndeterminate()) + return null; + //numFrames has to be an even number as defined by spec. + int iterations = numFrames / 2 + 1; + + double boxDependent; + double boxIndependent; + + if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) + { + Dimension dims = getPreferredInnerHorizontal(); + boxDependent = (double) dims.width / iterations; + boxIndependent = dims.height; + } + else + { + Dimension dims = getPreferredInnerVertical(); + boxDependent = (double) dims.height / iterations; + boxIndependent = dims.width; + } + + Rectangle vr = new Rectangle(); + SwingUtilities.calculateInnerArea(progressBar, vr); + + int index = getAnimationIndex(); + if (animationIndex > (numFrames + 1) / 2) + index = numFrames - getAnimationIndex(); + + if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) + { + r.x = vr.x + (int) (index * boxDependent); + r.y = vr.y; + r.width = (int) boxDependent; + r.height = (int) boxIndependent; + } + else + { + index++; + r.x = vr.x; + r.y = vr.height - (int) (index * boxDependent) + vr.y; + r.width = (int) boxIndependent; + r.height = (int) boxDependent; + } + + return r; + } + + /** + * This method returns the length of the cells. + * + * @return The cell length. + */ + protected int getCellLength() + { + return cellLength; + } + + /** + * This method returns the spacing between cells. + * + * @return The cell gap. + */ + protected int getCellSpacing() + { + return cellSpacing; + } + + /** + * This method returns the maximum size of the JComponent. + * If it returns null, it is up to the LayoutManager + * to give it a size. + * + * @param c The component to find a maximum size for. + * + * @return The maximum size. + */ + public Dimension getMaximumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the minimum size of the JComponent. + * If it returns null, it is up to the LayoutManager to + * give it a size. + * + * @param c The component to find a minimum size for. + * + * @return The minimum size. + */ + public Dimension getMinimumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the preferred size of the inner + * rectangle (the bounds without the insets) if the + * progressBar is horizontal. + * + * @return The preferred size of the progressBar minus + * insets if it's horizontal. + */ + protected Dimension getPreferredInnerHorizontal() + { + Rectangle vr = new Rectangle(); + + SwingUtilities.calculateInnerArea(progressBar, vr); + + return new Dimension(vr.width, vr.height); + } + + /** + * This method returns the preferred size of the inner + * rectangle (the bounds without insets) if the + * progressBar is vertical. + * + * @return The preferred size of the progressBar minus + * insets if it's vertical. + */ + protected Dimension getPreferredInnerVertical() + { + Rectangle vr = new Rectangle(); + + SwingUtilities.calculateInnerArea(progressBar, vr); + + return new Dimension(vr.width, vr.height); + } + + /** + * This method returns the preferred size of the + * given JComponent. If it returns null, then it + * is up to the LayoutManager to give it a size. + * + * @param c The component to find the preferred size for. + * + * @return The preferred size of the component. + */ + public Dimension getPreferredSize(JComponent c) + { + // The only thing we need to worry about is + // the text size. + Insets insets = c.getInsets(); + + // make a fontrenderer context so that we can make assumptions about + // the string bounds + FontRenderContext ctx = new FontRenderContext(new AffineTransform(), + false, false); + Rectangle2D bounds = c.getFont().getStringBounds(progressBar.getString(), + ctx); + int textW = (int) bounds.getWidth(); + int textH = (int) bounds.getHeight(); + + if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) + { + if (textH < 20) + textH = 20; + if (textW < 200) + textW = 200; + } + else + { + if (textH < 200) + textH = 200; + if (textW < 20) + textW = 20; + } + textW += insets.left + insets.right; + textH += insets.top + insets.bottom; + return new Dimension(textW, textH); + } + + /** + * This method returns the Color that the text is shown in when the bar is + * not over the text. + * + * @return The color of the text when the bar is not over it. + */ + protected Color getSelectionBackground() + { + return selectionBackground; + } + + /** + * This method returns the Color that the text is shown in when the bar is + * over the text. + * + * @return The color of the text when the bar is over it. + */ + protected Color getSelectionForeground() + { + return selectionForeground; + } + + /** + * This method returns the point (the top left of the bounding box) + * where the text should be painted. + * + * @param g The Graphics object to measure FontMetrics with. + * @param progressString The string to paint. + * @param x The x coordinate of the overall bounds box. + * @param y The y coordinate of the overall bounds box. + * @param width The width of the overall bounds box. + * @param height The height of the overall bounds box. + * + * @return The top left of the bounding box where text should be painted. + */ + protected Point getStringPlacement(Graphics g, String progressString, int x, + int y, int width, int height) + { + Rectangle tr = new Rectangle(); + Rectangle vr = new Rectangle(x, y, width, height); + Rectangle ir = new Rectangle(); + + Font f = g.getFont(); + FontMetrics fm = g.getFontMetrics(f); + + SwingUtilities.layoutCompoundLabel(progressBar, fm, progressString, null, + SwingConstants.CENTER, + SwingConstants.CENTER, + SwingConstants.CENTER, + SwingConstants.CENTER, vr, ir, tr, 0); + return new Point(tr.x, tr.y); + } + + /** + * This method increments the animation index. + */ + protected void incrementAnimationIndex() + { + animationIndex++; + //numFrames is like string length, it should be named numFrames or something + if (animationIndex >= numFrames) + animationIndex = 0; + progressBar.repaint(); + } + + /** + * This method paints the progressBar. It delegates its responsibilities + * to paintDeterminate and paintIndeterminate. + * + * @param g The Graphics object to paint with. + * @param c The JComponent to paint. + */ + public void paint(Graphics g, JComponent c) + { + if (! progressBar.isIndeterminate()) + paintDeterminate(g, c); + else + paintIndeterminate(g, c); + } + + /** + * This method is called if the painting to be done is + * for a determinate progressBar. + * + * @param g The Graphics object to paint with. + * @param c The JComponent to paint. + */ + protected void paintDeterminate(Graphics g, JComponent c) + { + Color saved = g.getColor(); + int space = getCellSpacing(); + int len = getCellLength(); + int max = progressBar.getMaximum(); + int min = progressBar.getMinimum(); + int value = progressBar.getValue(); + + Rectangle vr = new Rectangle(); + SwingUtilities.calculateInnerArea(c, vr); + + Rectangle or = c.getBounds(); + + Insets insets = c.getInsets(); + + int amountFull = getAmountFull(insets, or.width, or.height); + + g.setColor(c.getBackground()); + g.fill3DRect(vr.x, vr.y, vr.width, vr.height, false); + + if (max != min && len != 0 && value > min) + { + int iterations = value / (space + len); + + if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) + { + double spaceInUnits = space * (double) vr.width / (max - min); + double lenInUnits = len * (double) vr.width / (max - min); + double currX = vr.x; + + g.setColor(c.getForeground()); + g.fill3DRect(vr.x, vr.y, amountFull, vr.height, true); + + g.setColor(c.getBackground()); + if (spaceInUnits != 0) + { + for (int i = 0; i < iterations; i++) + { + currX += lenInUnits; + g.fill3DRect((int) currX, vr.y, (int) spaceInUnits, + vr.height, true); + currX += spaceInUnits; + } + } + } + else + { + double currY = vr.y; + double spaceInUnits = space * (double) vr.height / (max - min); + double lenInUnits = len * (double) vr.height / (max - min); + + g.setColor(c.getForeground()); + g.fill3DRect(vr.x, vr.y + vr.height - amountFull, vr.width, + amountFull, true); + + g.setColor(c.getBackground()); + + if (spaceInUnits != 0) + { + for (int i = 0; i < iterations; i++) + { + currY -= lenInUnits + spaceInUnits; + g.fill3DRect(vr.x, (int) currY, vr.width, + (int) spaceInUnits, true); + } + } + } + } + + if (progressBar.isStringPainted() && !progressBar.getString().equals("")) + paintString(g, 0, 0, or.width, or.height, amountFull, insets); + g.setColor(saved); + } + + /** + * This method is called if the painting to be done is for + * an indeterminate progressBar. + * + * @param g The Graphics object to paint with. + * @param c The JComponent to paint. + */ + protected void paintIndeterminate(Graphics g, JComponent c) + { + //need to paint the box at it's current position. no text is painted since + //all we're doing is bouncing back and forth + Color saved = g.getColor(); + Insets insets = c.getInsets(); + + Rectangle or = c.getBounds(); + Rectangle vr = new Rectangle(); + SwingUtilities.calculateInnerArea(c, vr); + + g.setColor(c.getBackground()); + g.fill3DRect(vr.x, vr.y, vr.width, vr.height, false); + + Rectangle box = new Rectangle(); + getBox(box); + + g.setColor(c.getForeground()); + g.fill3DRect(box.x, box.y, box.width, box.height, true); + + if (progressBar.isStringPainted() && !progressBar.getString().equals("")) + paintString(g, 0, 0, or.width, or.height, + getAmountFull(insets, or.width, or.height), insets); + + g.setColor(saved); + } + + /** + * This method paints the string for the progressBar. + * + * @param g The Graphics object to paint with. + * @param x The x coordinate of the progressBar. + * @param y The y coordinate of the progressBar. + * @param width The width of the progressBar. + * @param height The height of the progressBar. + * @param amountFull The amount of the progressBar that has its bar filled. + * @param b The insets of the progressBar. + */ + protected void paintString(Graphics g, int x, int y, int width, int height, + int amountFull, Insets b) + { + // We want to place in the exact center of the bar. + Point placement = getStringPlacement(g, progressBar.getString(), + x + b.left, y + b.top, + width - b.left - b.right, + height - b.top - b.bottom); + Color saved = g.getColor(); + + // FIXME: The Color of the text should use selectionForeground and selectionBackground + // but that can't be done right now, so we'll use white in the mean time. + g.setColor(Color.WHITE); + + FontMetrics fm = g.getFontMetrics(progressBar.getFont()); + + g.drawString(progressBar.getString(), placement.x, + placement.y + fm.getAscent()); + + g.setColor(saved); + } + + /** + * This method sets the current animation index. If the index + * is greater than the number of frames, it resets to 0. + * + * @param newValue The new animation index. + */ + protected void setAnimationIndex(int newValue) + { + animationIndex = (newValue <= numFrames) ? newValue : 0; + progressBar.repaint(); + } + + /** + * This method sets the cell length. + * + * @param cellLen The cell length. + */ + protected void setCellLength(int cellLen) + { + cellLength = cellLen; + } + + /** + * This method sets the cell spacing. + * + * @param cellSpace The cell spacing. + */ + protected void setCellSpacing(int cellSpace) + { + cellSpacing = cellSpace; + } + + /** + * This method starts the animation timer. It is called + * when the propertyChangeListener detects that the progressBar + * has changed to indeterminate mode. + * + * @since 1.4 + */ + protected void startAnimationTimer() + { + if (animationTimer != null) + animationTimer.start(); + } + + /** + * This method stops the animation timer. It is called when + * the propertyChangeListener detects that the progressBar + * has changed to determinate mode. + * + * @since 1.4 + */ + protected void stopAnimationTimer() + { + if (animationTimer != null) + animationTimer.stop(); + setAnimationIndex(0); + } + + /** + * This method changes the settings for the progressBar to + * the defaults provided by the current Look and Feel. + */ + protected void installDefaults() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + progressBar.setFont(defaults.getFont("ProgressBar.font")); + progressBar.setForeground(defaults.getColor("ProgressBar.foreground")); + progressBar.setBackground(defaults.getColor("ProgressBar.background")); + progressBar.setBorder(defaults.getBorder("ProgressBar.border")); + progressBar.setOpaque(true); + + selectionForeground = defaults.getColor("ProgressBar.selectionForeground"); + selectionBackground = defaults.getColor("ProgressBar.selectionBackground"); + cellLength = defaults.getInt("ProgressBar.cellLength"); + cellSpacing = defaults.getInt("ProgressBar.cellSpacing"); + + int repaintInterval = defaults.getInt("ProgressBar.repaintInterval"); + int cycleTime = defaults.getInt("ProgressBar.cycleTime"); + + if (cycleTime % repaintInterval != 0 + && (cycleTime / repaintInterval) % 2 != 0) + { + int div = (cycleTime / repaintInterval) + 2; + div /= 2; + div *= 2; + cycleTime = div * repaintInterval; + } + setAnimationIndex(0); + numFrames = cycleTime / repaintInterval; + animationTimer.setDelay(repaintInterval); + } + + /** + * The method uninstalls any defaults that were + * set by the current Look and Feel. + */ + protected void uninstallDefaults() + { + progressBar.setFont(null); + progressBar.setForeground(null); + progressBar.setBackground(null); + + selectionForeground = null; + selectionBackground = null; + } + + /** + * This method registers listeners to all the + * components that this UI delegate needs to listen to. + */ + protected void installListeners() + { + changeListener = new ChangeHandler(); + propertyListener = new PropertyChangeHandler(); + animation = new Animator(); + + progressBar.addChangeListener(changeListener); + progressBar.addPropertyChangeListener(propertyListener); + animationTimer.addActionListener(animation); + } + + /** + * This method unregisters listeners to all the + * components that were listened to. + */ + protected void uninstallListeners() + { + progressBar.removeChangeListener(changeListener); + progressBar.removePropertyChangeListener(propertyListener); + animationTimer.removeActionListener(animation); + + changeListener = null; + propertyListener = null; + animation = null; + } + + /** + * This method installs the UI for the given JComponent. + * This includes setting up defaults and listeners as + * well as initializing any values or objects that + * the UI may need. + * + * @param c The JComponent that is having this UI installed. + */ + public void installUI(JComponent c) + { + super.installUI(c); + if (c instanceof JProgressBar) + { + progressBar = (JProgressBar) c; + + animationTimer = new Timer(200, null); + animationTimer.setRepeats(true); + + installDefaults(); + installListeners(); + } + } + + /** + * This method removes the UI for the given JComponent. + * This includes removing any listeners or defaults + * that the installUI may have set up. + * + * @param c The JComponent that is having this UI uninstalled. + */ + public void uninstallUI(JComponent c) + { + super.uninstallUI(c); + uninstallListeners(); + uninstallDefaults(); + + animationTimer = null; + progressBar = null; + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonMenuItemUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonMenuItemUI.java new file mode 100644 index 0000000..d5cd7f4 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonMenuItemUI.java @@ -0,0 +1,102 @@ +/* BasicRadioButtonMenuItemUI.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.event.MouseEvent; + +import javax.swing.JComponent; +import javax.swing.JMenuItem; +import javax.swing.MenuElement; +import javax.swing.MenuSelectionManager; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.ComponentUI; + +/** + * UI Delegator for JRadioButtonMenuItem + */ +public class BasicRadioButtonMenuItemUI extends BasicMenuItemUI +{ + /** + * Creates a new BasicRadioButtonMenuItemUI object. + */ + public BasicRadioButtonMenuItemUI() + { + super(); + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + checkIcon = defaults.getIcon("RadioButtonMenuItem.checkIcon"); + } + + /** + * Factory method to create a BasicRadioButtonMenuItemUI for the given {@link + * JComponent}, which should be a JRadioButtonMenuItem. + * + * @param b The {@link JComponent} a UI is being created for. + * + * @return A BasicRadioButtonMenuItemUI for the {@link JComponent}. + */ + public static ComponentUI createUI(JComponent b) + { + return new BasicRadioButtonMenuItemUI(); + } + + /** + * DOCUMENT ME! + * + * @return $returnType$ DOCUMENT ME! + */ + protected String getPropertyPrefix() + { + return null; + } + + /** + * DOCUMENT ME! + * + * @param item DOCUMENT ME! + * @param e DOCUMENT ME! + * @param path DOCUMENT ME! + * @param manager DOCUMENT ME! + */ + public void processMouseEvent(JMenuItem item, MouseEvent e, + MenuElement[] path, + MenuSelectionManager manager) + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonUI.java new file mode 100644 index 0000000..38e117b --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonUI.java @@ -0,0 +1,87 @@ +/* BasicRadioButtonUI.java + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import javax.swing.AbstractButton; +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.ComponentUI; + +public class BasicRadioButtonUI extends BasicToggleButtonUI +{ + + protected Icon icon; + + public static ComponentUI createUI(final JComponent c) { + return new BasicRadioButtonUI(); + } + + public BasicRadioButtonUI() + { + icon = getDefaultIcon(); + } + + public void installUI(final JComponent c) { + super.installUI(c); + if (c instanceof AbstractButton) + { + AbstractButton b = (AbstractButton) c; + b.setIcon(icon); + } + } + + public Icon getDefaultIcon() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + return defaults.getIcon("RadioButton.icon"); + } + +} + + + + + + + + + + diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicRootPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicRootPaneUI.java new file mode 100644 index 0000000..d97f7ba --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicRootPaneUI.java @@ -0,0 +1,66 @@ +/* BasicPanelUI.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.JComponent; +import javax.swing.UIManager; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.RootPaneUI; + +public class BasicRootPaneUI extends RootPaneUI + implements PropertyChangeListener +{ + public static ComponentUI createUI(JComponent x) + { + return new BasicRootPaneUI(); + } + + public void installUI(JComponent c) + { + c.setBackground(UIManager.getColor("control")); + super.installUI(c); + } + + public void propertyChange(PropertyChangeEvent event) + { + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicScrollBarUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicScrollBarUI.java new file mode 100644 index 0000000..892db2b --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicScrollBarUI.java @@ -0,0 +1,1271 @@ +/* BasicScrollBarUI.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.LayoutManager; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.BoundedRangeModel; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JScrollBar; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.Timer; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.ScrollBarUI; + +/** + * The Basic Look and Feel UI delegate for JScrollBar. + */ +public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, + SwingConstants +{ + /** + * A helper class that listens to the two JButtons on each end of the + * JScrollBar. + */ + protected class ArrowButtonListener extends MouseAdapter + { + /** + * Move the thumb in the direction specified by the button's arrow. If + * this button is held down, then it should keep moving the thumb. + * + * @param e The MouseEvent fired by the JButton. + */ + public void mousePressed(MouseEvent e) + { + scrollTimer.stop(); + scrollListener.setScrollByBlock(false); + if (e.getSource() == incrButton) + scrollListener.setDirection(POSITIVE_SCROLL); + else + scrollListener.setDirection(NEGATIVE_SCROLL); + scrollTimer.start(); + } + + /** + * Stops the thumb when the JButton is released. + * + * @param e The MouseEvent fired by the JButton. + */ + public void mouseReleased(MouseEvent e) + { + scrollTimer.stop(); + } + } + + /** + * A helper class that listens to the ScrollBar's model for ChangeEvents. + */ + protected class ModelListener implements ChangeListener + { + /** + * Called when the model changes. + * + * @param e The ChangeEvent fired by the model. + */ + public void stateChanged(ChangeEvent e) + { + // System.err.println(this + ".stateChanged()"); + calculatePreferredSize(); + getThumbBounds(); + scrollbar.repaint(); + } + } + + /** + * A helper class that listens to the ScrollBar's properties. + */ + public class PropertyChangeHandler implements PropertyChangeListener + { + /** + * Called when one of the ScrollBar's properties change. + * + * @param e The PropertyChangeEvent fired by the ScrollBar. + */ + public void propertyChange(PropertyChangeEvent e) + { + if (e.getPropertyName().equals("model")) + { + ((BoundedRangeModel) e.getOldValue()).removeChangeListener(modelListener); + scrollbar.getModel().addChangeListener(modelListener); + getThumbBounds(); + } + else if (e.getPropertyName().equals("orientation")) + { + incrButton.removeMouseListener(buttonListener); + decrButton.removeMouseListener(buttonListener); + int orientation = scrollbar.getOrientation(); + switch (orientation) + { + case (JScrollBar.HORIZONTAL): + incrButton = createIncreaseButton(EAST); + decrButton = createDecreaseButton(WEST); + break; + default: + incrButton = createIncreaseButton(SOUTH); + decrButton = createDecreaseButton(NORTH); + break; + } + incrButton.addMouseListener(buttonListener); + decrButton.addMouseListener(buttonListener); + calculatePreferredSize(); + } + scrollbar.repaint(); + } + } + + /** + * A helper class that listens for events from the timer that is used to + * move the thumb. + */ + protected class ScrollListener implements ActionListener + { + /** The direction the thumb moves in. */ + private transient int direction; + + /** Whether movement will be in blocks. */ + private transient boolean block; + + /** + * Creates a new ScrollListener object. The default is scrolling + * positively with block movement. + */ + public ScrollListener() + { + direction = POSITIVE_SCROLL; + block = true; + } + + /** + * Creates a new ScrollListener object using the given direction and + * block. + * + * @param dir The direction to move in. + * @param block Whether movement will be in blocks. + */ + public ScrollListener(int dir, boolean block) + { + direction = dir; + this.block = block; + } + + /** + * Sets the direction to scroll in. + * + * @param direction The direction to scroll in. + */ + public void setDirection(int direction) + { + this.direction = direction; + } + + /** + * Sets whether scrolling will be done in blocks. + * + * @param block Whether scrolling will be in blocks. + */ + public void setScrollByBlock(boolean block) + { + this.block = block; + } + + /** + * Called every time the timer reaches its interval. + * + * @param e The ActionEvent fired by the timer. + */ + public void actionPerformed(ActionEvent e) + { + if (block) + { + // Only need to check it if it's block scrolling + // We only block scroll if the click occurs + // in the track. + if (! trackListener.shouldScroll(direction)) + { + trackHighlight = NO_HIGHLIGHT; + scrollbar.repaint(); + return; + } + scrollByBlock(direction); + } + else + scrollByUnit(direction); + } + } + + /** + * Helper class that listens for movement on the track. + */ + protected class TrackListener extends MouseAdapter + implements MouseMotionListener + { + /** The current X coordinate of the mouse. */ + protected int currentMouseX; + + /** The current Y coordinate of the mouse. */ + protected int currentMouseY; + + /** + * The offset between the current mouse cursor and the current value of + * the scrollbar. + */ + protected int offset; + + /** + * This method is called when the mouse is being dragged. + * + * @param e The MouseEvent given. + */ + public void mouseDragged(MouseEvent e) + { + currentMouseX = e.getX(); + currentMouseY = e.getY(); + if (scrollbar.getValueIsAdjusting()) + { + int value; + if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL) + value = valueForXPosition(currentMouseX) - offset; + else + value = valueForYPosition(currentMouseY) - offset; + + scrollbar.setValue(value); + } + } + + /** + * This method is called when the mouse is moved. + * + * @param e The MouseEvent given. + */ + public void mouseMoved(MouseEvent e) + { + // Not interested in where the mouse + // is unless it is being dragged. + } + + /** + * This method is called when the mouse is pressed. When it is pressed, + * the thumb should move in blocks towards the cursor. + * + * @param e The MouseEvent given. + */ + public void mousePressed(MouseEvent e) + { + currentMouseX = e.getX(); + currentMouseY = e.getY(); + + int value; + if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL) + value = valueForXPosition(currentMouseX); + else + value = valueForYPosition(currentMouseY); + + if (value == scrollbar.getValue()) + return; + + if (! thumbRect.contains(e.getPoint())) + { + scrollTimer.stop(); + scrollListener.setScrollByBlock(true); + if (value > scrollbar.getValue()) + { + trackHighlight = INCREASE_HIGHLIGHT; + scrollListener.setDirection(POSITIVE_SCROLL); + } + else + { + trackHighlight = DECREASE_HIGHLIGHT; + scrollListener.setDirection(NEGATIVE_SCROLL); + } + scrollTimer.start(); + } + else + { + // We'd like to keep track of where the cursor + // is inside the thumb. + // This works because the scrollbar's value represents + // "lower" edge of the thumb. The value at which + // the cursor is at must be greater or equal + // to that value. + scrollbar.setValueIsAdjusting(true); + offset = value - scrollbar.getValue(); + } + scrollbar.repaint(); + } + + /** + * This method is called when the mouse is released. It should stop + * movement on the thumb + * + * @param e The MouseEvent given. + */ + public void mouseReleased(MouseEvent e) + { + trackHighlight = NO_HIGHLIGHT; + scrollTimer.stop(); + + if (scrollbar.getValueIsAdjusting()) + scrollbar.setValueIsAdjusting(false); + scrollbar.repaint(); + } + + /** + * A helper method that decides whether we should keep scrolling in the + * given direction. + * + * @param direction The direction to check for. + * + * @return Whether the thumb should keep scrolling. + */ + public boolean shouldScroll(int direction) + { + int value; + if (scrollbar.getOrientation() == HORIZONTAL) + value = valueForXPosition(currentMouseX); + else + value = valueForYPosition(currentMouseY); + + if (direction == POSITIVE_SCROLL) + return (value > scrollbar.getValue()); + else + return (value < scrollbar.getValue()); + } + } + + /** The listener that listens to the JButtons. */ + protected ArrowButtonListener buttonListener; + + /** The listener that listens to the model. */ + protected ModelListener modelListener; + + /** The listener that listens to the scrollbar for property changes. */ + protected PropertyChangeListener propertyChangeListener; + + /** The listener that listens to the timer. */ + protected ScrollListener scrollListener; + + /** The listener that listens for MouseEvents on the track. */ + protected TrackListener trackListener; + + /** The JButton that decrements the scrollbar's value. */ + protected JButton decrButton; + + /** The JButton that increments the scrollbar's value. */ + protected JButton incrButton; + + /** The dimensions of the maximum thumb size. */ + protected Dimension maximumThumbSize; + + /** The dimensions of the minimum thumb size. */ + protected Dimension minimumThumbSize; + + /** The color of the thumb. */ + protected Color thumbColor; + + /** The outer shadow of the thumb. */ + protected Color thumbDarkShadowColor; + + /** The top and left edge color for the thumb. */ + protected Color thumbHighlightColor; + + /** The outer light shadow for the thumb. */ + protected Color thumbLightShadowColor; + + /** The color that is used when the mouse press occurs in the track. */ + protected Color trackHighlightColor; + + /** The color of the track. */ + protected Color trackColor; + + /** The size and position of the track. */ + protected Rectangle trackRect; + + /** The size and position of the thumb. */ + protected Rectangle thumbRect; + + /** Indicates that the decrease highlight should be painted. */ + protected static final int DECREASE_HIGHLIGHT = 1; + + /** Indicates that the increase highlight should be painted. */ + protected static final int INCREASE_HIGHLIGHT = 2; + + /** Indicates that no highlight should be painted. */ + protected static final int NO_HIGHLIGHT = 0; + + /** Indicates that the scrolling direction is positive. */ + private static final int POSITIVE_SCROLL = 1; + + /** Indicates that the scrolling direction is negative. */ + private static final int NEGATIVE_SCROLL = -1; + + /** The cached preferred size for the scrollbar. */ + private transient Dimension preferredSize; + + /** The current highlight status. */ + protected int trackHighlight; + + /** FIXME: Use this for something (presumably mouseDragged) */ + protected boolean isDragging; + + /** The timer used to move the thumb when the mouse is held. */ + protected Timer scrollTimer; + + /** The scrollbar this UI is acting for. */ + protected JScrollBar scrollbar; + + /** + * This method adds a component to the layout. + * + * @param name The name to associate with the component that is added. + * @param child The Component to add. + */ + public void addLayoutComponent(String name, Component child) + { + // You should not be adding stuff to this component. + // The contents are fixed. + } + + /** + * This method configures the scrollbar's colors. This can be done by + * looking up the standard colors from the Look and Feel defaults. + */ + protected void configureScrollBarColors() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + trackColor = defaults.getColor("ScrollBar.track"); + trackHighlightColor = defaults.getColor("ScrollBar.trackHighlight"); + thumbColor = defaults.getColor("ScrollBar.thumb"); + thumbHighlightColor = defaults.getColor("ScrollBar.thumbHighlight"); + thumbDarkShadowColor = defaults.getColor("ScrollBar.thumbDarkShadow"); + thumbLightShadowColor = defaults.getColor("ScrollBar.thumbShadow"); + } + + /** + * This method creates an ArrowButtonListener. + * + * @return A new ArrowButtonListener. + */ + protected ArrowButtonListener createArrowButtonListener() + { + return new ArrowButtonListener(); + } + + /** + * This method creates a new JButton with the appropriate icon for the + * orientation. + * + * @param orientation The orientation this JButton uses. + * + * @return The increase JButton. + */ + protected JButton createIncreaseButton(int orientation) + { + if (incrButton == null) + incrButton = new BasicArrowButton(orientation); + else + ((BasicArrowButton) incrButton).setDirection(orientation); + return incrButton; + } + + /** + * This method creates a new JButton with the appropriate icon for the + * orientation. + * + * @param orientation The orientation this JButton uses. + * + * @return The decrease JButton. + */ + protected JButton createDecreaseButton(int orientation) + { + if (decrButton == null) + decrButton = new BasicArrowButton(orientation); + else + ((BasicArrowButton) decrButton).setDirection(orientation); + return decrButton; + } + + /** + * This method creates a new ModelListener. + * + * @return A new ModelListener. + */ + protected ModelListener createModelListener() + { + return new ModelListener(); + } + + /** + * This method creates a new PropertyChangeListener. + * + * @return A new PropertyChangeListener. + */ + protected PropertyChangeListener createPropertyChangeListener() + { + return new PropertyChangeHandler(); + } + + /** + * This method creates a new ScrollListener. + * + * @return A new ScrollListener. + */ + protected ScrollListener createScrollListener() + { + return new ScrollListener(); + } + + /** + * This method creates a new TrackListener. + * + * @return A new TrackListener. + */ + protected TrackListener createTrackListener() + { + return new TrackListener(); + } + + /** + * This method returns a new BasicScrollBarUI. + * + * @param c The JComponent to create a UI for. + * + * @return A new BasicScrollBarUI. + */ + public static ComponentUI createUI(JComponent c) + { + return new BasicScrollBarUI(); + } + + /** + * This method returns the maximum size for this JComponent. + * + * @param c The JComponent to measure the maximum size for. + * + * @return The maximum size for the component. + */ + public Dimension getMaximumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the maximum thumb size. + * + * @return The maximum thumb size. + */ + protected Dimension getMaximumThumbSize() + { + return maximumThumbSize; + } + + /** + * This method returns the minimum size for this JComponent. + * + * @param c The JComponent to measure the minimum size for. + * + * @return The minimum size for the component. + */ + public Dimension getMinimumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the minimum thumb size. + * + * @return The minimum thumb size. + */ + protected Dimension getMinimumThumbSize() + { + return minimumThumbSize; + } + + /** + * This method calculates the preferred size since calling + * getPreferredSize() returns a cached value. + * This is package-private to avoid an accessor method. + */ + void calculatePreferredSize() + { + // System.err.println(this + ".calculatePreferredSize()"); + int height; + int width; + height = width = 0; + + if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL) + { + width += incrButton.getPreferredSize().getWidth(); + width += decrButton.getPreferredSize().getWidth(); + + width += (scrollbar.getMaximum() - scrollbar.getMinimum()); + + height = Math.max(incrButton.getPreferredSize().height, + decrButton.getPreferredSize().height); + height = Math.max(getMinimumThumbSize().height, height); + height = Math.max(20, height); + height = Math.min(getMaximumThumbSize().height, height); + } + else + { + height += incrButton.getPreferredSize().getHeight(); + height += decrButton.getPreferredSize().getHeight(); + + height += (scrollbar.getMaximum() - scrollbar.getMinimum()); + + width = Math.max(incrButton.getPreferredSize().width, + decrButton.getPreferredSize().width); + width = Math.max(getMinimumThumbSize().width, width); + width = Math.max(20, width); + width = Math.min(getMaximumThumbSize().width, width); + } + + Insets insets = scrollbar.getInsets(); + + height += insets.top + insets.bottom; + width += insets.left + insets.right; + + preferredSize = new Dimension(width, height); + } + + /** + * This method returns a cached value of the preferredSize. The only + * restrictions are: If the scrollbar is horizontal, the height should be + * the maximum of the height of the JButtons and the minimum width of the + * thumb. For vertical scrollbars, the calculation is similar (swap width + * for height and vice versa). + * + * @param c The JComponent to measure. + * + * @return The preferredSize. + */ + public Dimension getPreferredSize(JComponent c) + { + calculatePreferredSize(); + return preferredSize; + } + + /** + * This method returns the thumb's bounds based on the current value of the + * scrollbar. This method updates the cached value and returns that. + * + * @return The thumb bounds. + */ + protected Rectangle getThumbBounds() + { + int max = scrollbar.getMaximum(); + int min = scrollbar.getMinimum(); + int value = scrollbar.getValue(); + int extent = scrollbar.getVisibleAmount(); + + // System.err.println(this + ".getThumbBounds()"); + if (max == min) + { + thumbRect.x = trackRect.x; + thumbRect.y = trackRect.y; + if (scrollbar.getOrientation() == HORIZONTAL) + { + thumbRect.width = getMinimumThumbSize().width; + thumbRect.height = trackRect.height; + } + else + { + thumbRect.width = trackRect.width; + thumbRect.height = getMinimumThumbSize().height; + } + return thumbRect; + } + + if (scrollbar.getOrientation() == HORIZONTAL) + { + thumbRect.x = trackRect.x; + thumbRect.x += (value - min) * trackRect.width / (max - min); + thumbRect.y = trackRect.y; + + thumbRect.width = Math.max(extent * trackRect.width / (max - min), + getMinimumThumbSize().width); + thumbRect.height = trackRect.height; + } + else + { + thumbRect.x = trackRect.x; + thumbRect.y = trackRect.y + value * trackRect.height / (max - min); + + thumbRect.width = trackRect.width; + thumbRect.height = Math.max(extent * trackRect.height / (max - min), + getMinimumThumbSize().height); + } + return thumbRect; + } + + /** + * This method calculates the bounds of the track. This method updates the + * cached value and returns it. + * + * @return The track's bounds. + */ + protected Rectangle getTrackBounds() + { + SwingUtilities.calculateInnerArea(scrollbar, trackRect); + + if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL) + { + trackRect.width -= incrButton.getPreferredSize().getWidth(); + trackRect.width -= decrButton.getPreferredSize().getWidth(); + + trackRect.x += decrButton.getPreferredSize().getWidth(); + } + else + { + trackRect.height -= incrButton.getPreferredSize().getHeight(); + trackRect.height -= decrButton.getPreferredSize().getHeight(); + + trackRect.y += incrButton.getPreferredSize().getHeight(); + } + return trackRect; + } + + /** + * This method installs any addition Components that are a part of or + * related to this scrollbar. + */ + protected void installComponents() + { + int orientation = scrollbar.getOrientation(); + switch (orientation) + { + case (JScrollBar.HORIZONTAL): + incrButton = createIncreaseButton(EAST); + decrButton = createDecreaseButton(WEST); + break; + default: + incrButton = createIncreaseButton(SOUTH); + decrButton = createDecreaseButton(NORTH); + break; + } + scrollbar.add(incrButton); + scrollbar.add(decrButton); + } + + /** + * This method installs the defaults for the scrollbar specified by the + * Basic Look and Feel. + */ + protected void installDefaults() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + scrollbar.setForeground(defaults.getColor("ScrollBar.foreground")); + scrollbar.setBackground(defaults.getColor("ScrollBar.background")); + scrollbar.setBorder(defaults.getBorder("ScrollBar.border")); + scrollbar.setOpaque(true); + scrollbar.setLayout(this); + + thumbColor = defaults.getColor("ScrollBar.thumb"); + thumbDarkShadowColor = defaults.getColor("ScrollBar.thumbDarkShadow"); + thumbHighlightColor = defaults.getColor("ScrollBar.thumbHighlight"); + thumbLightShadowColor = defaults.getColor("ScrollBar.thumbShadow"); + + maximumThumbSize = defaults.getDimension("ScrollBar.maximumThumbSize"); + minimumThumbSize = defaults.getDimension("ScrollBar.minimumThumbSize"); + } + + /** + * This method installs the keyboard actions for the scrollbar. + */ + protected void installKeyboardActions() + { + // FIXME: implement. + } + + /** + * This method installs any listeners for the scrollbar. This method also + * installs listeners for things such as the JButtons and the timer. + */ + protected void installListeners() + { + scrollListener = createScrollListener(); + trackListener = createTrackListener(); + buttonListener = createArrowButtonListener(); + modelListener = createModelListener(); + propertyChangeListener = createPropertyChangeListener(); + + scrollbar.addMouseMotionListener(trackListener); + scrollbar.addMouseListener(trackListener); + + incrButton.addMouseListener(buttonListener); + decrButton.addMouseListener(buttonListener); + + scrollbar.addPropertyChangeListener(propertyChangeListener); + scrollbar.getModel().addChangeListener(modelListener); + + scrollTimer.addActionListener(scrollListener); + } + + /** + * This method installs the UI for the component. This can include setting + * up listeners, defaults, and components. This also includes initializing + * any data objects. + * + * @param c The JComponent to install. + */ + public void installUI(JComponent c) + { + super.installUI(c); + if (c instanceof JScrollBar) + { + scrollbar = (JScrollBar) c; + + trackRect = new Rectangle(); + thumbRect = new Rectangle(); + + scrollTimer = new Timer(200, null); + scrollTimer.setRepeats(true); + + installComponents(); + installDefaults(); + configureScrollBarColors(); + installListeners(); + + calculatePreferredSize(); + } + } + + /** + * This method lays out the scrollbar. + * + * @param scrollbarContainer The Container to layout. + */ + public void layoutContainer(Container scrollbarContainer) + { + if (scrollbarContainer instanceof JScrollBar) + { + if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL) + layoutHScrollbar((JScrollBar) scrollbarContainer); + else + layoutVScrollbar((JScrollBar) scrollbarContainer); + } + } + + /** + * This method lays out the scrollbar horizontally. + * + * @param sb The JScrollBar to layout. + */ + protected void layoutHScrollbar(JScrollBar sb) + { + // All we have to do is layout the 2 buttons? + Rectangle vr = new Rectangle(); + SwingUtilities.calculateInnerArea(scrollbar, vr); + + // Update the rectangles. + getTrackBounds(); + getThumbBounds(); + + Dimension incrDims = incrButton.getPreferredSize(); + Dimension decrDims = decrButton.getPreferredSize(); + + decrButton.setBounds(vr.x, vr.y, decrDims.width, trackRect.height); + incrButton.setBounds(trackRect.x + trackRect.width, vr.y, incrDims.width, + trackRect.height); + } + + /** + * This method lays out the scrollbar vertically. + * + * @param sb The JScrollBar to layout. + */ + protected void layoutVScrollbar(JScrollBar sb) + { + Rectangle vr = new Rectangle(); + SwingUtilities.calculateInnerArea(scrollbar, vr); + + // Update rectangles + getTrackBounds(); + getThumbBounds(); + + Dimension incrDims = incrButton.getPreferredSize(); + Dimension decrDims = decrButton.getPreferredSize(); + + decrButton.setBounds(vr.x, vr.y, trackRect.width, decrDims.height); + incrButton.setBounds(vr.x, trackRect.y + trackRect.height, + trackRect.width, incrDims.height); + } + + /** + * This method returns the minimum size required for the layout. + * + * @param scrollbarContainer The Container that is laid out. + * + * @return The minimum size. + */ + public Dimension minimumLayoutSize(Container scrollbarContainer) + { + return preferredLayoutSize(scrollbarContainer); + } + + /** + * This method is called when the component is painted. + * + * @param g The Graphics object to paint with. + * @param c The JComponent to paint. + */ + public void paint(Graphics g, JComponent c) + { + paintTrack(g, c, getTrackBounds()); + paintThumb(g, c, getThumbBounds()); + + if (trackHighlight == INCREASE_HIGHLIGHT) + paintIncreaseHighlight(g); + else if (trackHighlight == DECREASE_HIGHLIGHT) + paintDecreaseHighlight(g); + } + + /** + * This method is called when repainting and the mouse is pressed in the + * track. It paints the track below the thumb with the trackHighlight + * color. + * + * @param g The Graphics object to paint with. + */ + protected void paintDecreaseHighlight(Graphics g) + { + Color saved = g.getColor(); + + g.setColor(trackHighlightColor); + if (scrollbar.getOrientation() == HORIZONTAL) + g.fillRect(trackRect.x, trackRect.y, thumbRect.x - trackRect.x, + trackRect.height); + else + g.fillRect(trackRect.x, trackRect.y, trackRect.width, + thumbRect.y - trackRect.y); + g.setColor(saved); + } + + /** + * This method is called when repainting and the mouse is pressed in the + * track. It paints the track above the thumb with the trackHighlight + * color. + * + * @param g The Graphics objet to paint with. + */ + protected void paintIncreaseHighlight(Graphics g) + { + Color saved = g.getColor(); + + g.setColor(trackHighlightColor); + if (scrollbar.getOrientation() == HORIZONTAL) + g.fillRect(thumbRect.x + thumbRect.width, trackRect.y, + trackRect.x + trackRect.width - thumbRect.x - thumbRect.width, + trackRect.height); + else + g.fillRect(trackRect.x, thumbRect.y + thumbRect.height, trackRect.width, + trackRect.y + trackRect.height - thumbRect.y + - thumbRect.height); + g.setColor(saved); + } + + /** + * This method paints the thumb. + * + * @param g The Graphics object to paint with. + * @param c The Component that is being painted. + * @param thumbBounds The thumb bounds. + */ + protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) + { + g.setColor(thumbColor); + g.fillRect(thumbBounds.x, thumbBounds.y, thumbBounds.width, + thumbBounds.height); + + BasicGraphicsUtils.drawBezel(g, thumbBounds.x, thumbBounds.y, + thumbBounds.width, thumbBounds.height, + false, false, thumbDarkShadowColor, + thumbDarkShadowColor, thumbHighlightColor, + thumbHighlightColor); + } + + /** + * This method paints the track. + * + * @param g The Graphics object to paint with. + * @param c The JComponent being painted. + * @param trackBounds The track's bounds. + */ + protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds) + { + Color saved = g.getColor(); + g.setColor(trackColor); + g.fill3DRect(trackBounds.x, trackBounds.y, trackBounds.width, + trackBounds.height, false); + g.setColor(saved); + } + + /** + * This method returns the preferred size for the layout. + * + * @param scrollbarContainer The Container to find a size for. + * + * @return The preferred size for the layout. + */ + public Dimension preferredLayoutSize(Container scrollbarContainer) + { + if (scrollbarContainer instanceof JComponent) + return getPreferredSize((JComponent) scrollbarContainer); + else + return null; + } + + /** + * This method removes a child component from the layout. + * + * @param child The child to remove. + */ + public void removeLayoutComponent(Component child) + { + // You should not be removing stuff from this component. + } + + /** + * The method scrolls the thumb by a block in the direction specified. + * + * @param direction The direction to scroll. + */ + protected void scrollByBlock(int direction) + { + scrollbar.setValue(scrollbar.getValue() + + scrollbar.getBlockIncrement(direction)); + } + + /** + * The method scrolls the thumb by a unit in the direction specified. + * + * @param direction The direction to scroll. + */ + protected void scrollByUnit(int direction) + { + scrollbar.setValue(scrollbar.getValue() + + scrollbar.getUnitIncrement(direction)); + } + + /** + * This method sets the thumb's bounds. + * + * @param x The X position of the thumb. + * @param y The Y position of the thumb. + * @param width The width of the thumb. + * @param height The height of the thumb. + */ + protected void setThumbBounds(int x, int y, int width, int height) + { + thumbRect.x = x; + thumbRect.y = y; + thumbRect.width = width; + thumbRect.height = height; + } + + /** + * This method uninstalls any components that are a part of or related to + * this scrollbar. + */ + protected void uninstallComponents() + { + scrollbar.remove(incrButton); + scrollbar.remove(decrButton); + incrButton = null; + decrButton = null; + } + + /** + * This method uninstalls any defaults that this scrollbar acquired from the + * Basic Look and Feel defaults. + */ + protected void uninstallDefaults() + { + scrollbar.setForeground(null); + scrollbar.setBackground(null); + scrollbar.setBorder(null); + } + + /** + * This method uninstalls any keyboard actions this scrollbar acquired + * during install. + */ + protected void uninstallKeyboardActions() + { + // FIXME: implement. + } + + /** + * This method uninstalls any listeners that were registered during install. + */ + protected void uninstallListeners() + { + scrollTimer.removeActionListener(scrollListener); + + scrollbar.getModel().removeChangeListener(modelListener); + scrollbar.removePropertyChangeListener(propertyChangeListener); + + decrButton.removeMouseListener(buttonListener); + incrButton.removeMouseListener(buttonListener); + + scrollbar.removeMouseListener(trackListener); + scrollbar.removeMouseMotionListener(trackListener); + + propertyChangeListener = null; + modelListener = null; + buttonListener = null; + trackListener = null; + scrollListener = null; + } + + /** + * This method uninstalls the UI. This includes removing any defaults, + * listeners, and components that this UI may have initialized. It also + * nulls any instance data. + * + * @param c The Component to uninstall for. + */ + public void uninstallUI(JComponent c) + { + uninstallDefaults(); + uninstallListeners(); + uninstallComponents(); + + scrollTimer = null; + + thumbRect = null; + trackRect = null; + + trackColor = null; + trackHighlightColor = null; + thumbColor = null; + thumbHighlightColor = null; + thumbDarkShadowColor = null; + thumbLightShadowColor = null; + + scrollbar = null; + } + + /** + * This method returns the value in the scrollbar's range given the y + * coordinate. If the value is out of range, it will return the closest + * legal value. + * This is package-private to avoid an accessor method. + * + * @param yPos The y coordinate to calculate a value for. + * + * @return The value for the y coordinate. + */ + int valueForYPosition(int yPos) + { + int min = scrollbar.getMinimum(); + int max = scrollbar.getMaximum(); + int len = trackRect.height; + + int value; + + // If the length is 0, you shouldn't be able to even see where the thumb is. + // This really shouldn't ever happen, but just in case, we'll return the middle. + if (len == 0) + return ((max - min) / 2); + + value = ((yPos - trackRect.y) * (max - min) / len + min); + + // If this isn't a legal value, then we'll have to move to one now. + if (value > max) + value = max; + else if (value < min) + value = min; + return value; + } + + /** + * This method returns the value in the scrollbar's range given the x + * coordinate. If the value is out of range, it will return the closest + * legal value. + * This is package-private to avoid an accessor method. + * + * @param xPos The x coordinate to calculate a value for. + * + * @return The value for the x coordinate. + */ + int valueForXPosition(int xPos) + { + int min = scrollbar.getMinimum(); + int max = scrollbar.getMaximum(); + int len = trackRect.width; + + int value; + + // If the length is 0, you shouldn't be able to even see where the slider is. + // This really shouldn't ever happen, but just in case, we'll return the middle. + if (len == 0) + return ((max - min) / 2); + + value = ((xPos - trackRect.x) * (max - min) / len + min); + + // If this isn't a legal value, then we'll have to move to one now. + if (value > max) + value = max; + else if (value < min) + value = min; + return value; + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicScrollPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicScrollPaneUI.java new file mode 100644 index 0000000..7bb7acf --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicScrollPaneUI.java @@ -0,0 +1,130 @@ +/* BasicScrollPaneUI.java + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Dimension; +import java.awt.Graphics; + +import javax.swing.JComponent; +import javax.swing.JScrollPane; +import javax.swing.ScrollPaneConstants; +import javax.swing.ScrollPaneLayout; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.ScrollPaneUI; + +public class BasicScrollPaneUI extends ScrollPaneUI + implements ScrollPaneConstants +{ + + /** The Scrollpane for which the UI is provided by this class. */ + protected JScrollPane scrollpane; + + public static ComponentUI createUI(final JComponent c) + { + return new BasicScrollPaneUI(); + } + + protected void installDefaults(JScrollPane p) + { + scrollpane = p; + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + p.setForeground(defaults.getColor("ScrollPane.foreground")); + p.setBackground(defaults.getColor("ScrollPane.background")); + p.setFont(defaults.getFont("ScrollPane.font")); + p.setBorder(defaults.getBorder("ScrollPane.border")); + p.setOpaque(true); + } + + protected void uninstallDefaults(JScrollPane p) + { + p.setForeground(null); + p.setBackground(null); + p.setFont(null); + p.setBorder(null); + scrollpane = null; + } + + public void installUI(final JComponent c) + { + super.installUI(c); + this.installDefaults((JScrollPane)c); + } + + public void uninstallUI(final JComponent c) + { + super.uninstallUI(c); + this.uninstallDefaults((JScrollPane)c); + } + + + public Dimension getMinimumSize(JComponent c) + { + JScrollPane p = (JScrollPane ) c; + ScrollPaneLayout sl = (ScrollPaneLayout) p.getLayout(); + return sl.minimumLayoutSize(c); + } + + public Dimension getPreferredSize(JComponent c) + { + JScrollPane p = (JScrollPane ) c; + ScrollPaneLayout sl = (ScrollPaneLayout) p.getLayout(); + return sl.preferredLayoutSize(c); + } + + + public void paint(Graphics g, JComponent c) + { + // do nothing; the normal painting-of-children algorithm, along with + // ScrollPaneLayout, does all the relevant work. + } +} + + + + + + + + + + + + diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicSeparatorUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicSeparatorUI.java new file mode 100644 index 0000000..38c9c7a --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicSeparatorUI.java @@ -0,0 +1,269 @@ +/* BasicSeparatorUI.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Rectangle; + +import javax.swing.JComponent; +import javax.swing.JSeparator; +import javax.swing.SwingUtilities; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.SeparatorUI; + +/** + * The Basic Look and Feel UI delegate for JSeparator. + */ +public class BasicSeparatorUI extends SeparatorUI +{ + /** The shadow color. */ + protected Color shadow; + + /** The highlight color. */ + protected Color highlight; + + /** + * Creates a new UI delegate for the given JComponent. + * + * @param c The JComponent to create a delegate for. + * + * @return A new BasicSeparatorUI. + */ + public static ComponentUI createUI(JComponent c) + { + return new BasicSeparatorUI(); + } + + /** + * This method installs the UI for the given JComponent. + * This can include installing defaults, listeners, and + * initializing any instance data. + * + * @param c The JComponent that is having this UI installed. + */ + public void installUI(JComponent c) + { + super.installUI(c); + + if (c instanceof JSeparator) + { + JSeparator s = (JSeparator) c; + + installDefaults(s); + installListeners(s); + } + } + + /** + * Uninstalls the UI for the given JComponent. This + * method reverses what was done when installing + * the UI on the JComponent. + * + * @param c The JComponent that is having this UI uninstalled. + */ + public void uninstallUI(JComponent c) + { + if (c instanceof JSeparator) + { + JSeparator s = (JSeparator) c; + + uninstallListeners(s); + uninstallDefaults(s); + } + } + + /** + * This method installs the defaults that are given by + * the Basic Look and Feel. + * + * @param s The JSeparator that is being installed. + */ + protected void installDefaults(JSeparator s) + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + shadow = defaults.getColor("Separator.shadow"); + highlight = defaults.getColor("Separator.highlight"); + s.setOpaque(false); + } + + /** + * This method removes the defaults that were given + * by the Basic Look and Feel. + * + * @param s The JSeparator that is being uninstalled. + */ + protected void uninstallDefaults(JSeparator s) + { + shadow = null; + highlight = null; + } + + /** + * This method installs any listeners that need + * to be attached to the JSeparator or any of its + * components. + * + * @param s The JSeparator that is being installed. + */ + protected void installListeners(JSeparator s) + { + // Separators don't receive events. + } + + /** + * This method uninstalls any listeners that + * were installed during the install UI process. + * + * @param s The JSeparator that is being uninstalled. + */ + protected void uninstallListeners(JSeparator s) + { + // Separators don't receive events. + } + + /** + * The separator is made of two lines. The top line will be + * the highlight color (or left line if it's vertical). The bottom + * or right line will be the shadow color. The two lines will + * be centered inside the bounds box. If the separator is horizontal, + * then it will be vertically centered, or if it's vertical, it will + * be horizontally centered. + * + * @param g The Graphics object to paint with + * @param c The JComponent to paint. + */ + public void paint(Graphics g, JComponent c) + { + Rectangle r = new Rectangle(); + SwingUtilities.calculateInnerArea(c, r); + Color saved = g.getColor(); + + int midAB = r.width / 2 + r.x; + int midAD = r.height / 2 + r.y; + + JSeparator s; + if (c instanceof JSeparator) + s = (JSeparator) c; + else + return; + + if (s.getOrientation() == JSeparator.HORIZONTAL) + { + g.setColor(highlight); + g.drawLine(r.x, midAD, r.x + r.width, midAD); + + g.setColor(shadow); + g.drawLine(r.x, midAD + 1, r.x + r.width, midAD + 1); + } + else + { + g.setColor(highlight); + g.drawLine(midAB, r.y, midAB, r.y + r.height); + + g.setColor(shadow); + g.drawLine(midAB + 1, r.y, midAB + 1, r.y + r.height); + } + } + + /** + * This method returns the preferred size of the + * JComponent. + * + * @param c The JComponent to measure. + * + * @return The preferred size. + */ + public Dimension getPreferredSize(JComponent c) + { + Dimension dims = new Dimension(0, 0); + Insets insets = c.getInsets(); + + if (c instanceof JSeparator) + { + JSeparator s = (JSeparator) c; + + if (s.getOrientation() == JSeparator.HORIZONTAL) + { + dims.height = 2; + dims.width = 40; + } + else + { + dims.width = 2; + dims.height = 40; + } + } + dims.width += insets.left + insets.right; + dims.height += insets.top + insets.bottom; + + return dims; + } + + /** + * This method returns the minimum size of the + * JComponent. + * + * @param c The JComponent to measure. + * + * @return The minimum size. + */ + public Dimension getMinimumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the maximum size of the + * JComponent. + * + * @param c The JComponent to measure. + * + * @return The maximum size. + */ + public Dimension getMaximumSize(JComponent c) + { + return getPreferredSize(c); + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicSliderUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicSliderUI.java new file mode 100644 index 0000000..0a72a62 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicSliderUI.java @@ -0,0 +1,2239 @@ +/* BasicSliderUI.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Component; +import java.awt.ComponentOrientation; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Polygon; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.Dictionary; +import java.util.Enumeration; + +import javax.swing.BoundedRangeModel; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JSlider; +import javax.swing.SwingUtilities; +import javax.swing.Timer; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.event.MouseInputAdapter; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.SliderUI; + +/** + * <p> + * BasicSliderUI.java This is the UI delegate in the Basic look and feel that + * paints JSliders. + * </p> + * + * <p> + * The UI delegate keeps track of 6 rectangles that place the various parts of + * the JSlider inside the component. + * </p> + * + * <p> + * The rectangles are organized as follows: + * </p> + * <pre> + * +-------------------------------------------------------+ <-- focusRect + * | | + * | +==+-------------------+==+--------------------+==+<------ contentRect + * | | | | |<---thumbRect | | | + * | | | TRACK | | |<--------- trackRect + * | | +-------------------+==+--------------------+ | | + * | | | | | | + * | | | TICKS GO HERE |<-------- tickRect + * | | | | | | + * | +==+-------------------------------------------+==+ | + * | | | | | | + * | | | | |<----- labelRect + * | | | LABELS GO HERE | | | + * | | | | | | + * | | | | | | + * | | | | | | + * | | | | | | + * | | | | | + * </pre> + * + * <p> + * The space between the contentRect and the focusRect are the FocusInsets. + * </p> + * + * <p> + * The space between the focusRect and the component bounds is the insetCache + * which are the component's insets. + * </p> + * + * <p> + * The top of the thumb is the top of the contentRect. The trackRect has to be + * as tall as the thumb. + * </p> + * + * <p> + * The trackRect and tickRect do not start from the left edge of the + * focusRect. They are trackBuffer away from each side of the focusRect. This + * is so that the thumb has room to move. + * </p> + * + * <p> + * The labelRect does start right against the contentRect's left and right + * edges and it gets all remaining space. + * </p> + */ +public class BasicSliderUI extends SliderUI +{ + /** + * Helper class that listens to the {@link JSlider}'s model for changes. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class ChangeHandler implements ChangeListener + { + /** + * Called when the slider's model has been altered. The UI delegate should + * recalculate any rectangles that are dependent on the model for their + * positions and repaint. + * + * @param e A static {@link ChangeEvent} passed from the model. + */ + public void stateChanged(ChangeEvent e) + { + // Maximum, minimum, and extent values will be taken + // care of automatically when the slider is repainted. + // Only thing that needs recalculation is the thumb. + calculateThumbLocation(); + slider.repaint(); + } + } + + /** + * Helper class that listens for resize events. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class ComponentHandler extends ComponentAdapter + { + /** + * Called when the size of the component changes. The UI delegate should + * recalculate any rectangles that are dependent on the model for their + * positions and repaint. + * + * @param e A {@link ComponentEvent}. + */ + public void componentResized(ComponentEvent e) + { + calculateGeometry(); + + slider.revalidate(); + slider.repaint(); + } + } + + /** + * Helper class that listens for focus events. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class FocusHandler implements FocusListener + { + /** + * Called when the {@link JSlider} has gained focus. It should repaint + * the slider with the focus drawn. + * + * @param e A {@link FocusEvent}. + */ + public void focusGained(FocusEvent e) + { + // FIXME: implement. + } + + /** + * Called when the {@link JSlider} has lost focus. It should repaint the + * slider without the focus drawn. + * + * @param e A {@link FocusEvent}. + */ + public void focusLost(FocusEvent e) + { + // FIXME: implement. + } + } + + /** + * Helper class that listens for changes to the properties of the {@link + * JSlider}. + */ + public class PropertyChangeHandler implements PropertyChangeListener + { + /** + * Called when one of the properties change. The UI should recalculate any + * rectangles if necessary and repaint. + * + * @param e A {@link PropertyChangeEvent}. + */ + public void propertyChange(PropertyChangeEvent e) + { + // Check for orientation changes. + if (e.getPropertyName().equals("orientation")) + recalculateIfOrientationChanged(); + else if (e.getPropertyName().equals("model")) + { + BoundedRangeModel oldModel = (BoundedRangeModel) e.getOldValue(); + oldModel.removeChangeListener(changeListener); + slider.getModel().addChangeListener(changeListener); + calculateThumbLocation(); + } + + // elif the componentOrientation changes (this is a bound property, + // just undocumented) we change leftToRightCache. In Sun's + // implementation, the LTR cache changes on a repaint. This is strange + // since there is no need to do so. We could events here and + // update the cache. + // elif the border/insets change, we recalculateInsets. + slider.repaint(); + } + } + + /** + * Helper class that listens to our swing timer. This class is responsible + * for listening to the timer and moving the thumb in the proper direction + * every interval. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class ScrollListener implements ActionListener + { + /** Indicates which direction the thumb should scroll. */ + private transient int direction; + + /** Indicates whether we should scroll in blocks or in units. */ + private transient boolean block; + + /** + * Creates a new ScrollListener object. + */ + public ScrollListener() + { + direction = POSITIVE_SCROLL; + block = false; + } + + /** + * Creates a new ScrollListener object. + * + * @param dir The direction to scroll in. + * @param block If movement will be in blocks. + */ + public ScrollListener(int dir, boolean block) + { + direction = dir; + this.block = block; + } + + /** + * Called every time the swing timer reaches its interval. If the thumb + * needs to move, then this method will move the thumb one block or unit + * in the direction desired. Otherwise, the timer can be stopped. + * + * @param e An {@link ActionEvent}. + */ + public void actionPerformed(ActionEvent e) + { + if (! trackListener.shouldScroll(direction)) + { + scrollTimer.stop(); + return; + } + + if (block) + scrollByBlock(direction); + else + scrollByUnit(direction); + } + + /** + * Sets the direction to scroll in. + * + * @param direction The direction to scroll in. + */ + public void setDirection(int direction) + { + this.direction = direction; + } + + /** + * Sets whether movement will be in blocks. + * + * @param block If movement will be in blocks. + */ + public void setScrollByBlock(boolean block) + { + this.block = block; + } + } + + /** + * Helper class that listens for mouse events. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class TrackListener extends MouseInputAdapter + { + /** The current X position of the mouse. */ + protected int currentMouseX; + + /** The current Y position of the mouse. */ + protected int currentMouseY; + + /** + * The offset between the current slider value and the cursor's position. + */ + protected int offset; + + /** + * Called when the mouse has been dragged. This should find the mouse's + * current position and adjust the value of the {@link JSlider} + * accordingly. + * + * @param e A {@link MouseEvent} + */ + public void mouseDragged(MouseEvent e) + { + currentMouseX = e.getX(); + currentMouseY = e.getY(); + if (slider.getValueIsAdjusting()) + { + int value; + if (slider.getOrientation() == JSlider.HORIZONTAL) + value = valueForXPosition(currentMouseX) - offset; + else + value = valueForYPosition(currentMouseY) - offset; + + slider.setValue(value); + } + } + + /** + * Called when the mouse has moved over a component but no buttons have + * been pressed yet. + * + * @param e A {@link MouseEvent} + */ + public void mouseMoved(MouseEvent e) + { + // Don't care that we're moved unless we're dragging. + } + + /** + * Called when the mouse is pressed. When the press occurs on the thumb + * itself, the {@link JSlider} should have its value set to where the + * mouse was pressed. If the press occurs on the track, then the thumb + * should move one block towards the direction of the mouse. + * + * @param e A {@link MouseEvent} + */ + public void mousePressed(MouseEvent e) + { + currentMouseX = e.getX(); + currentMouseY = e.getY(); + + int value; + if (slider.getOrientation() == JSlider.HORIZONTAL) + value = valueForXPosition(currentMouseX); + else + value = valueForYPosition(currentMouseY); + + if (slider.getSnapToTicks()) + value = findClosestTick(value); + + // If the thumb is hit, then we don't need to set the timers to move it. + if (! thumbRect.contains(e.getPoint())) + { + // The mouse has hit some other part of the slider. + // The value moves no matter where in the slider you hit. + if (value > slider.getValue()) + scrollDueToClickInTrack(POSITIVE_SCROLL); + else + scrollDueToClickInTrack(NEGATIVE_SCROLL); + } + else + { + slider.setValueIsAdjusting(true); + offset = value - slider.getValue(); + } + } + + /** + * Called when the mouse is released. This should stop the timer that + * scrolls the thumb. + * + * @param e A {@link MouseEvent} + */ + public void mouseReleased(MouseEvent e) + { + currentMouseX = e.getX(); + currentMouseY = e.getY(); + + if (slider.getValueIsAdjusting()) + { + slider.setValueIsAdjusting(false); + if (slider.getSnapToTicks()) + slider.setValue(findClosestTick(slider.getValue())); + } + if (scrollTimer != null) + scrollTimer.stop(); + } + + /** + * Indicates whether the thumb should scroll in the given direction. + * + * @param direction The direction to check. + * + * @return True if the thumb should move in that direction. + */ + public boolean shouldScroll(int direction) + { + int value; + if (slider.getOrientation() == JSlider.HORIZONTAL) + value = valueForXPosition(currentMouseX); + else + value = valueForYPosition(currentMouseY); + + if (direction == POSITIVE_SCROLL) + return (value > slider.getValue()); + else + return (value < slider.getValue()); + } + } + + /** The preferred height of the thumb. */ + private transient int thumbHeight; + + /** The preferred width of the thumb. */ + private transient int thumbWidth; + + /** The preferred height of the tick rectangle. */ + private transient int tickHeight; + + /** Listener for changes from the model. */ + protected ChangeListener changeListener; + + /** Listener for changes to the {@link JSlider}. */ + protected PropertyChangeListener propertyChangeListener; + + /** Listener for the scrollTimer. */ + protected ScrollListener scrollListener; + + /** Listener for component resizing. */ + protected ComponentListener componentListener; + + /** Listener for focus handling. */ + protected FocusListener focusListener; + + /** Listener for mouse events. */ + protected TrackListener trackListener; + + /** The insets between the FocusRectangle and the ContentRectangle. */ + protected Insets focusInsets; + + /** The {@link JSlider}'s insets. */ + protected Insets insetCache; + + /** Rectangle describing content bounds. See diagram above. */ + protected Rectangle contentRect; + + /** Rectangle describing focus bounds. See diagram above. */ + protected Rectangle focusRect; + + /** Rectangle describing the thumb's bounds. See diagram above. */ + protected Rectangle thumbRect; + + /** Rectangle describing the tick bounds. See diagram above. */ + protected Rectangle tickRect; + + /** Rectangle describing the label bounds. See diagram above. */ + protected Rectangle labelRect; + + /** Rectangle describing the track bounds. See diagram above. */ + protected Rectangle trackRect; + + /** FIXME: use this somewhere. */ + public static final int MAX_SCROLL = 2; + + /** FIXME: use this somewhere. */ + public static final int MIN_SCROLL = -2; + + /** A constant describing scrolling towards the minimum. */ + public static final int NEGATIVE_SCROLL = -1; + + /** A constant describing scrolling towards the maximum. */ + public static final int POSITIVE_SCROLL = 1; + + /** The gap between the edges of the contentRect and trackRect. */ + protected int trackBuffer; + + /** Whether this slider is actually drawn left to right. */ + protected boolean leftToRightCache; + + /** A timer that periodically moves the thumb. */ + protected Timer scrollTimer; + + /** A reference to the {@link JSlider} that this UI was created for. */ + protected JSlider slider; + + /** The shadow color. */ + private transient Color shadowColor; + + /** The highlight color. */ + private transient Color highlightColor; + + /** The focus color. */ + private transient Color focusColor; + + /** + * Creates a new Basic look and feel Slider UI. + * + * @param b The {@link JSlider} that this UI was created for. + */ + public BasicSliderUI(JSlider b) + { + super(); + } + + /** + * Gets the shadow color to be used for this slider. The shadow color is the + * color used for drawing the top and left edges of the track. + * + * @return The shadow color. + */ + protected Color getShadowColor() + { + return shadowColor; + } + + /** + * Gets the highlight color to be used for this slider. The highlight color + * is the color used for drawing the bottom and right edges of the track. + * + * @return The highlight color. + */ + protected Color getHighlightColor() + { + return highlightColor; + } + + /** + * Gets the focus color to be used for this slider. The focus color is the + * color used for drawing the focus rectangle when the component gains + * focus. + * + * @return The focus color. + */ + protected Color getFocusColor() + { + return focusColor; + } + + /** + * Factory method to create a BasicSliderUI for the given {@link + * JComponent}, which should be a {@link JSlider}. + * + * @param b The {@link JComponent} a UI is being created for. + * + * @return A BasicSliderUI for the {@link JComponent}. + */ + public static ComponentUI createUI(JComponent b) + { + return new BasicSliderUI((JSlider) b); + } + + /** + * Installs and initializes all fields for this UI delegate. Any properties + * of the UI that need to be initialized and/or set to defaults will be + * done now. It will also install any listeners necessary. + * + * @param c The {@link JComponent} that is having this UI installed. + */ + public void installUI(JComponent c) + { + super.installUI(c); + if (c instanceof JSlider) + { + slider = (JSlider) c; + + focusRect = new Rectangle(); + contentRect = new Rectangle(); + thumbRect = new Rectangle(); + trackRect = new Rectangle(); + tickRect = new Rectangle(); + labelRect = new Rectangle(); + + insetCache = slider.getInsets(); + leftToRightCache = ! slider.getInverted(); + + scrollTimer = new Timer(200, null); + scrollTimer.setRepeats(true); + + installDefaults(slider); + installListeners(slider); + installKeyboardActions(slider); + + calculateFocusRect(); + + calculateContentRect(); + calculateThumbSize(); + calculateTrackBuffer(); + calculateTrackRect(); + calculateThumbLocation(); + + calculateTickRect(); + calculateLabelRect(); + } + } + + /** + * Performs the opposite of installUI. Any properties or resources that need + * to be cleaned up will be done now. It will also uninstall any listeners + * it has. In addition, any properties of this UI will be nulled. + * + * @param c The {@link JComponent} that is having this UI uninstalled. + */ + public void uninstallUI(JComponent c) + { + super.uninstallUI(c); + + uninstallKeyboardActions(slider); + uninstallListeners(slider); + + scrollTimer = null; + + focusRect = null; + contentRect = null; + thumbRect = null; + trackRect = null; + tickRect = null; + labelRect = null; + + focusInsets = null; + } + + /** + * Initializes any default properties that this UI has from the defaults for + * the Basic look and feel. + * + * @param slider The {@link JSlider} that is having this UI installed. + */ + protected void installDefaults(JSlider slider) + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + slider.setForeground(defaults.getColor("Slider.foreground")); + slider.setBackground(defaults.getColor("Slider.background")); + shadowColor = defaults.getColor("Slider.shadow"); + highlightColor = defaults.getColor("Slider.highlight"); + focusColor = defaults.getColor("Slider.focus"); + slider.setBorder(defaults.getBorder("Slider.border")); + slider.setOpaque(true); + + thumbHeight = defaults.getInt("Slider.thumbHeight"); + thumbWidth = defaults.getInt("Slider.thumbWidth"); + tickHeight = defaults.getInt("Slider.tickHeight"); + + focusInsets = defaults.getInsets("Slider.focusInsets"); + } + + /** + * Creates a new {@link TrackListener}. + * + * @param slider The {@link JSlider} that this {@link TrackListener} is + * created for. + * + * @return A new {@link TrackListener}. + */ + protected TrackListener createTrackListener(JSlider slider) + { + return new TrackListener(); + } + + /** + * Creates a new {@link ChangeListener}. + * + * @param slider The {@link JSlider} that this {@link ChangeListener} is + * created for. + * + * @return A new {@link ChangeListener}. + */ + protected ChangeListener createChangeListener(JSlider slider) + { + return new ChangeHandler(); + } + + /** + * Creates a new {@link ComponentListener}. + * + * @param slider The {@link JSlider} that this {@link ComponentListener} is + * created for. + * + * @return A new {@link ComponentListener}. + */ + protected ComponentListener createComponentListener(JSlider slider) + { + return new ComponentHandler(); + } + + /** + * Creates a new {@link FocusListener}. + * + * @param slider The {@link JSlider} that this {@link FocusListener} is + * created for. + * + * @return A new {@link FocusListener}. + */ + protected FocusListener createFocusListener(JSlider slider) + { + return new FocusHandler(); + } + + /** + * Creates a new {@link ScrollListener}. + * + * @param slider The {@link JSlider} that this {@link ScrollListener} is + * created for. + * + * @return A new {@link ScrollListener}. + */ + protected ScrollListener createScrollListener(JSlider slider) + { + return new ScrollListener(); + } + + /** + * Creates a new {@link PropertyChangeListener}. + * + * @param slider The {@link JSlider} that this {@link + * PropertyChangeListener} is created for. + * + * @return A new {@link PropertyChangeListener}. + */ + protected PropertyChangeListener createPropertyChangeListener(JSlider slider) + { + return new PropertyChangeHandler(); + } + + /** + * Creates and registers all the listeners for this UI delegate. This + * includes creating the ScrollListener and registering it to the timer. + * + * @param slider The {@link JSlider} is having listeners installed. + */ + protected void installListeners(JSlider slider) + { + propertyChangeListener = createPropertyChangeListener(slider); + componentListener = createComponentListener(slider); + trackListener = createTrackListener(slider); + focusListener = createFocusListener(slider); + changeListener = createChangeListener(slider); + scrollListener = createScrollListener(slider); + + slider.addPropertyChangeListener(propertyChangeListener); + slider.addComponentListener(componentListener); + slider.addMouseListener(trackListener); + slider.addMouseMotionListener(trackListener); + slider.addFocusListener(focusListener); + slider.getModel().addChangeListener(changeListener); + + scrollTimer.addActionListener(scrollListener); + } + + /** + * Unregisters all the listeners that this UI delegate was using. In + * addition, it will also null any listeners that it was using. + * + * @param slider The {@link JSlider} that is having listeners removed. + */ + protected void uninstallListeners(JSlider slider) + { + slider.removePropertyChangeListener(propertyChangeListener); + slider.removeComponentListener(componentListener); + slider.removeMouseListener(trackListener); + slider.removeMouseMotionListener(trackListener); + slider.removeFocusListener(focusListener); + slider.getModel().removeChangeListener(changeListener); + + scrollTimer.removeActionListener(scrollListener); + + propertyChangeListener = null; + componentListener = null; + trackListener = null; + focusListener = null; + changeListener = null; + scrollListener = null; + } + + /** + * Installs any keyboard actions. The list of keys that need to be bound are + * listed in Basic look and feel's defaults. + * + * @param slider The {@link JSlider} that is having keyboard actions + * installed. + */ + protected void installKeyboardActions(JSlider slider) + { + // FIXME: implement. + } + + /** + * Uninstalls any keyboard actions. The list of keys used are listed in + * Basic look and feel's defaults. + * + * @param slider The {@link JSlider} that is having keyboard actions + * uninstalled. + */ + protected void uninstallKeyboardActions(JSlider slider) + { + // FIXME: implement. + } + + /* XXX: This is all after experimentation with SUN's implementation. + + PreferredHorizontalSize seems to be 200x21. + PreferredVerticalSize seems to be 21x200. + + MinimumHorizontalSize seems to be 36x21. + MinimumVerticalSize seems to be 21x36. + + PreferredSize seems to be 200x63. Or Components.getBounds? + + MinimumSize seems to be 36x63. + + MaximumSize seems to be 32767x63. + */ + + /** + * This method returns the preferred size when the slider is horizontally + * oriented. + * + * @return The dimensions of the preferred horizontal size. + */ + public Dimension getPreferredHorizontalSize() + { + Insets insets = slider.getInsets(); + + // The width should cover all the labels (which are usually the + // deciding factor of the width) + int width = getWidthOfWidestLabel() * (slider.getLabelTable() == null ? 0 + : slider.getLabelTable() + .size()); + + // If there are not enough labels. + // This number is pretty much arbitrary, but it looks nice. + if (width < 200) + width = 200; + + // We can only draw inside of the focusRectangle, so we have to + // pad it with insets. + width += insets.left + insets.right + focusInsets.left + focusInsets.right; + + // Height is determined by the thumb, the ticks and the labels. + int height = thumbHeight; + + if (slider.getPaintTicks() && slider.getMajorTickSpacing() > 0 + || slider.getMinorTickSpacing() > 0) + height += tickHeight; + + if (slider.getPaintLabels()) + height += getHeightOfTallestLabel(); + + height += insets.top + insets.bottom + focusInsets.top + + focusInsets.bottom; + + return new Dimension(width, height); + } + + /** + * This method returns the preferred size when the slider is vertically + * oriented. + * + * @return The dimensions of the preferred vertical size. + */ + public Dimension getPreferredVerticalSize() + { + Insets insets = slider.getInsets(); + + int height = getHeightOfTallestLabel() * (slider.getLabelTable() == null + ? 0 : slider.getLabelTable() + .size()); + + if (height < 200) + height = 200; + + height += insets.top + insets.bottom + focusInsets.top + + focusInsets.bottom; + + int width = thumbHeight; + + if (slider.getPaintTicks() && slider.getMajorTickSpacing() > 0 + || slider.getMinorTickSpacing() > 0) + width += tickHeight; + + if (slider.getPaintLabels()) + width += getWidthOfWidestLabel(); + + width += insets.left + insets.right + focusInsets.left + focusInsets.right; + + return new Dimension(width, height); + } + + /** + * This method returns the minimum size when the slider is horizontally + * oriented. + * + * @return The dimensions of the minimum horizontal size. + */ + public Dimension getMinimumHorizontalSize() + { + return getPreferredHorizontalSize(); + } + + /** + * This method returns the minimum size of the slider when it is vertically + * oriented. + * + * @return The dimensions of the minimum vertical size. + */ + public Dimension getMinimumVerticalSize() + { + return getPreferredVerticalSize(); + } + + /** + * This method returns the preferred size of the component. If it returns + * null, then it is up to the Layout Manager to give the {@link JComponent} + * a size. + * + * @param c The {@link JComponent} to find the preferred size for. + * + * @return The dimensions of the preferred size. + */ + public Dimension getPreferredSize(JComponent c) + { + if (slider.getOrientation() == JSlider.HORIZONTAL) + return getPreferredHorizontalSize(); + else + return getPreferredVerticalSize(); + } + + /** + * This method returns the minimum size for this {@link JSlider} for this + * look and feel. If it returns null, then it is up to the Layout Manager + * to give the {@link JComponent} a size. + * + * @param c The {@link JComponent} to find the minimum size for. + * + * @return The dimensions of the minimum size. + */ + public Dimension getMinimumSize(JComponent c) + { + if (slider.getOrientation() == JSlider.HORIZONTAL) + return getPreferredHorizontalSize(); + else + return getPreferredVerticalSize(); + } + + /** + * This method returns the maximum size for this {@link JSlider} for this + * look and feel. If it returns null, then it is up to the Layout Manager + * to give the {@link JComponent} a size. + * + * @param c The {@link JComponent} to find a maximum size for. + * + * @return The dimensions of the maximum size. + */ + public Dimension getMaximumSize(JComponent c) + { + if (slider.getOrientation() == JSlider.HORIZONTAL) + return getPreferredHorizontalSize(); + else + return getPreferredVerticalSize(); + } + + /** + * This method calculates all the sizes of the rectangles by delegating to + * the helper methods calculateXXXRect. + */ + protected void calculateGeometry() + { + calculateFocusRect(); + calculateContentRect(); + calculateThumbSize(); + calculateTrackBuffer(); + calculateTrackRect(); + calculateTickRect(); + calculateLabelRect(); + calculateThumbLocation(); + } + + /** + * This method calculates the size and position of the focusRect. This + * method does not need to be called if the orientation changes. + */ + protected void calculateFocusRect() + { + insetCache = slider.getInsets(); + focusRect = SwingUtilities.calculateInnerArea(slider, focusRect); + + if (focusRect.width < 0) + focusRect.width = 0; + if (focusRect.height < 0) + focusRect.height = 0; + } + + /** + * This method calculates the size but not the position of the thumbRect. It + * must take into account the orientation of the slider. + */ + protected void calculateThumbSize() + { + if (slider.getOrientation() == JSlider.HORIZONTAL) + { + if (thumbWidth > contentRect.width) + thumbRect.width = contentRect.width / 4; + else + thumbRect.width = thumbWidth; + if (thumbHeight > contentRect.height) + thumbRect.height = contentRect.height; + else + thumbRect.height = thumbHeight; + } + else + { + // The thumb gets flipped when inverted, so thumbWidth + // actually is the height and vice versa. + if (thumbWidth > contentRect.height) + thumbRect.height = contentRect.height / 4; + else + thumbRect.height = thumbWidth; + if (thumbHeight > contentRect.width) + thumbRect.width = contentRect.width; + else + thumbRect.width = thumbHeight; + } + } + + /** + * This method calculates the size and position of the contentRect. This + * method does not need to be called if the orientation changes. + */ + protected void calculateContentRect() + { + contentRect.x = focusRect.x + focusInsets.left; + contentRect.y = focusRect.y + focusInsets.top; + contentRect.width = focusRect.width - focusInsets.left - focusInsets.right; + contentRect.height = focusRect.height - focusInsets.top + - focusInsets.bottom; + + if (contentRect.width < 0) + contentRect.width = 0; + if (contentRect.height < 0) + contentRect.height = 0; + } + + /** + * Calculates the position of the thumbRect based on the current value of + * the slider. It must take into account the orientation of the slider. + */ + protected void calculateThumbLocation() + { + int value = slider.getValue(); + + if (slider.getOrientation() == JSlider.HORIZONTAL) + { + thumbRect.x = xPositionForValue(value) - thumbRect.width / 2; + thumbRect.y = contentRect.y; + } + else + { + thumbRect.x = contentRect.x; + thumbRect.y = yPositionForValue(value) - thumbRect.height / 2; + } + } + + /** + * Calculates the gap size between the left edge of the contentRect and the + * left edge of the trackRect. + */ + protected void calculateTrackBuffer() + { + if (slider.getOrientation() == JSlider.HORIZONTAL) + trackBuffer = thumbRect.width; + else + trackBuffer = thumbRect.height; + } + + /** + * This method returns the size of the thumbRect. + * + * @return The dimensions of the thumb. + */ + protected Dimension getThumbSize() + { + // This is really just the bounds box for the thumb. + // The thumb will actually be pointed (like a rectangle + triangle at bottom) + return thumbRect.getSize(); + } + + /** + * Calculates the size and position of the trackRect. It must take into + * account the orientation of the slider. + */ + protected void calculateTrackRect() + { + if (slider.getOrientation() == JSlider.HORIZONTAL) + { + trackRect.x = contentRect.x + trackBuffer; + trackRect.y = contentRect.y; + trackRect.width = contentRect.width - 2 * trackBuffer; + trackRect.height = thumbRect.height; + } + else + { + trackRect.x = contentRect.x; + trackRect.y = contentRect.y + trackBuffer; + trackRect.width = thumbRect.width; + trackRect.height = contentRect.height - 2 * trackBuffer; + } + } + + /** + * This method returns the height of the tick area box if the slider is + * horizontal and the width of the tick area box is the slider is vertical. + * It not necessarily how long the ticks will be. If a gap between the edge + * of tick box and the actual tick is desired, then that will need to be + * handled in the tick painting methods. + * + * @return The height (or width if the slider is vertical) of the tick + * rectangle. + */ + protected int getTickLength() + { + return tickHeight; + } + + /** + * This method calculates the size and position of the tickRect. It must + * take into account the orientation of the slider. + */ + protected void calculateTickRect() + { + if (slider.getOrientation() == JSlider.HORIZONTAL) + { + tickRect.x = trackRect.x; + tickRect.y = trackRect.y + trackRect.height; + tickRect.width = trackRect.width; + tickRect.height = getTickLength(); + + if (tickRect.y + tickRect.height > contentRect.y + contentRect.height) + tickRect.height = contentRect.y + contentRect.height - tickRect.y; + } + else + { + tickRect.x = trackRect.x + trackRect.width; + tickRect.y = trackRect.y; + tickRect.width = getTickLength(); + tickRect.height = trackRect.height; + + if (tickRect.x + tickRect.width > contentRect.x + contentRect.width) + tickRect.width = contentRect.x + contentRect.width - tickRect.x; + } + } + + /** + * This method calculates the size and position of the labelRect. It must + * take into account the orientation of the slider. + */ + protected void calculateLabelRect() + { + if (slider.getOrientation() == JSlider.HORIZONTAL) + { + labelRect.x = contentRect.x; + labelRect.y = tickRect.y + tickRect.height; + labelRect.width = contentRect.width; + labelRect.height = contentRect.height - labelRect.y; + } + else + { + labelRect.x = tickRect.x + tickRect.width; + labelRect.y = contentRect.y; + labelRect.width = contentRect.width - labelRect.x; + labelRect.height = contentRect.height; + } + } + + /** + * This method returns the width of the widest label in the slider's label + * table. + * + * @return The width of the widest label or 0 if no label table exists. + */ + protected int getWidthOfWidestLabel() + { + int widest = 0; + Component label; + + if (slider.getLabelTable() == null) + return 0; + + Dimension pref; + for (Enumeration list = slider.getLabelTable().elements(); + list.hasMoreElements();) + { + Object comp = list.nextElement(); + if (! (comp instanceof Component)) + continue; + label = (Component) comp; + pref = label.getPreferredSize(); + if (pref != null && pref.width > widest) + widest = pref.width; + } + return widest; + } + + /** + * This method returns the height of the tallest label in the slider's label + * table. + * + * @return The height of the tallest label or 0 if no label table exists. + */ + protected int getHeightOfTallestLabel() + { + int tallest = 0; + Component label; + + if (slider.getLabelTable() == null) + return 0; + Dimension pref; + for (Enumeration list = slider.getLabelTable().elements(); + list.hasMoreElements();) + { + Object comp = list.nextElement(); + if (! (comp instanceof Component)) + continue; + label = (Component) comp; + pref = label.getPreferredSize(); + if (pref != null && pref.height > tallest) + tallest = pref.height; + } + return tallest; + } + + /** + * This method returns the width of the label whose key has the highest + * value. + * + * @return The width of the high value label or 0 if no label table exists. + */ + protected int getWidthOfHighValueLabel() + { + Component highValueLabel = getHighestValueLabel(); + if (highValueLabel != null) + return highValueLabel.getWidth(); + else + return 0; + } + + /** + * This method returns the width of the label whose key has the lowest + * value. + * + * @return The width of the low value label or 0 if no label table exists. + */ + protected int getWidthOfLowValueLabel() + { + Component lowValueLabel = getLowestValueLabel(); + if (lowValueLabel != null) + return lowValueLabel.getWidth(); + else + return 0; + } + + /** + * This method returns the height of the label whose key has the highest + * value. + * + * @return The height of the high value label or 0 if no label table exists. + */ + protected int getHeightOfHighValueLabel() + { + Component highValueLabel = getHighestValueLabel(); + if (highValueLabel != null) + return highValueLabel.getHeight(); + else + return 0; + } + + /** + * This method returns the height of the label whose key has the lowest + * value. + * + * @return The height of the low value label or 0 if no label table exists. + */ + protected int getHeightOfLowValueLabel() + { + Component lowValueLabel = getLowestValueLabel(); + if (lowValueLabel != null) + return lowValueLabel.getHeight(); + else + return 0; + } + + /** + * This method returns whether the slider is to be drawn inverted. + * + * @return True is the slider is to be drawn inverted. + */ + protected boolean drawInverted() + { + return ! (slider.getInverted() ^ leftToRightCache); + } + + /** + * This method returns the label whose key has the lowest value. + * + * @return The low value label or null if no label table exists. + */ + protected Component getLowestValueLabel() + { + Integer key = new Integer(Integer.MAX_VALUE); + Integer tmpKey; + Dictionary labelTable = slider.getLabelTable(); + + if (labelTable == null) + return null; + + for (Enumeration list = labelTable.keys(); list.hasMoreElements();) + { + Object value = list.nextElement(); + if (! (value instanceof Integer)) + continue; + tmpKey = (Integer) value; + if (tmpKey.intValue() < key.intValue()) + key = tmpKey; + } + Object comp = labelTable.get(key); + if (! (comp instanceof Component)) + return null; + return (Component) comp; + } + + /** + * This method returns the label whose key has the highest value. + * + * @return The high value label or null if no label table exists. + */ + protected Component getHighestValueLabel() + { + Integer key = new Integer(Integer.MIN_VALUE); + Integer tmpKey; + Dictionary labelTable = slider.getLabelTable(); + + if (labelTable == null) + return null; + + for (Enumeration list = labelTable.keys(); list.hasMoreElements();) + { + Object value = list.nextElement(); + if (! (value instanceof Integer)) + continue; + tmpKey = (Integer) value; + if (tmpKey.intValue() > key.intValue()) + key = tmpKey; + } + Object comp = labelTable.get(key); + if (! (comp instanceof Component)) + return null; + return (Component) comp; + } + + /** + * This method is used to paint the {@link JSlider}. It delegates all its + * duties to the various paint methods like paintTicks(), paintTrack(), + * paintThumb(), etc. + * + * @param g The {@link Graphics} object to paint with. + * @param c The {@link JComponent} that is being painted. + */ + public void paint(Graphics g, JComponent c) + { + // FIXME: Move this to propertyChangeEvent handler, when we get those. + leftToRightCache = slider.getComponentOrientation() != ComponentOrientation.RIGHT_TO_LEFT; + // FIXME: This next line is only here because the above line is here. + calculateThumbLocation(); + + if (slider.getPaintTrack()) + paintTrack(g); + if (slider.getPaintTicks()) + paintTicks(g); + if (slider.getPaintLabels()) + paintLabels(g); + + //FIXME: Paint focus. + paintThumb(g); + } + + /** + * This method recalculates any rectangles that need to be recalculated + * after the insets of the component have changed. + */ + protected void recalculateIfInsetsChanged() + { + // Examining a test program shows that either Sun calls private + // methods that we don't know about, or these don't do anything. + calculateFocusRect(); + + calculateContentRect(); + calculateThumbSize(); + calculateTrackBuffer(); + calculateTrackRect(); + calculateThumbLocation(); + + calculateTickRect(); + calculateLabelRect(); + } + + /** + * This method recalculates any rectangles that need to be recalculated + * after the orientation of the slider changes. + */ + protected void recalculateIfOrientationChanged() + { + // Examining a test program shows that either Sun calls private + // methods that we don't know about, or these don't do anything. + calculateThumbSize(); + calculateTrackBuffer(); + calculateTrackRect(); + calculateThumbLocation(); + + calculateTickRect(); + calculateLabelRect(); + } + + /** + * This method is called during a repaint if the slider has focus. It draws + * an outline of the focusRect using the color returned by + * getFocusColor(). + * + * @param g The {@link Graphics} object to draw with. + */ + public void paintFocus(Graphics g) + { + Color saved_color = g.getColor(); + + g.setColor(getFocusColor()); + + g.drawRect(focusRect.x, focusRect.y, focusRect.width, focusRect.height); + + g.setColor(saved_color); + } + + /** + * <p> + * This method is called during a repaint if the track is to be drawn. It + * draws a 3D rectangle to represent the track. The track is not the size + * of the trackRect. The top and left edges of the track should be outlined + * with the shadow color. The bottom and right edges should be outlined + * with the highlight color. + * </p> + * <pre> + * a---d + * | | + * | | a------------------------d + * | | | | + * | | b------------------------c + * | | + * | | + * b---c + * </pre> + * + * <p> + * The b-a-d path needs to be drawn with the shadow color and the b-c-d path + * needs to be drawn with the highlight color. + * </p> + * + * @param g The {@link Graphics} object to draw with. + */ + public void paintTrack(Graphics g) + { + Color saved_color = g.getColor(); + int width; + int height; + + Point a = new Point(trackRect.x, trackRect.y); + Point b = new Point(a); + Point c = new Point(a); + Point d = new Point(a); + + Polygon high; + Polygon shadow; + + if (slider.getOrientation() == JSlider.HORIZONTAL) + { + width = trackRect.width; + height = (thumbRect.height / 4 == 0) ? 1 : thumbRect.height / 4; + + a.translate(0, (trackRect.height / 2) - (height / 2)); + b.translate(0, (trackRect.height / 2) + (height / 2)); + c.translate(trackRect.width, (trackRect.height / 2) + (height / 2)); + d.translate(trackRect.width, (trackRect.height / 2) - (height / 2)); + } + else + { + width = (thumbRect.width / 4 == 0) ? 1 : thumbRect.width / 4; + height = trackRect.height; + + a.translate((trackRect.width / 2) - (width / 2), 0); + b.translate((trackRect.width / 2) - (width / 2), trackRect.height); + c.translate((trackRect.width / 2) + (width / 2), trackRect.height); + d.translate((trackRect.width / 2) + (width / 2), 0); + } + g.setColor(Color.GRAY); + g.fillRect(a.x, a.y, width, height); + + g.setColor(getHighlightColor()); + g.drawLine(b.x, b.y, c.x, c.y); + g.drawLine(c.x, c.y, d.x, d.y); + + g.setColor(getShadowColor()); + g.drawLine(b.x, b.y, a.x, a.y); + g.drawLine(a.x, a.y, d.x, d.y); + + g.setColor(saved_color); + } + + /** + * This method is called during a repaint if the ticks are to be drawn. This + * method must still verify that the majorTickSpacing and minorTickSpacing + * are greater than zero before drawing the ticks. + * + * @param g The {@link Graphics} object to draw with. + */ + public void paintTicks(Graphics g) + { + int max = slider.getMaximum(); + int min = slider.getMinimum(); + int majorSpace = slider.getMajorTickSpacing(); + int minorSpace = slider.getMinorTickSpacing(); + + if (majorSpace > 0) + { + if (slider.getOrientation() == JSlider.HORIZONTAL) + { + double loc = tickRect.x; + double increment = (max == min) ? 0 + : majorSpace * (double) tickRect.width / (max + - min); + if (drawInverted()) + { + loc += tickRect.width; + increment *= -1; + } + for (int i = min; i <= max; i += majorSpace) + { + paintMajorTickForHorizSlider(g, tickRect, (int) loc); + loc += increment; + } + } + else + { + double loc = tickRect.height + tickRect.y; + double increment = (max == min) ? 0 + : -majorSpace * (double) tickRect.height / (max + - min); + if (drawInverted()) + { + loc = tickRect.y; + increment *= -1; + } + for (int i = min; i <= max; i += majorSpace) + { + paintMajorTickForVertSlider(g, tickRect, (int) loc); + loc += increment; + } + } + } + if (minorSpace > 0) + { + if (slider.getOrientation() == JSlider.HORIZONTAL) + { + double loc = tickRect.x; + double increment = (max == min) ? 0 + : minorSpace * (double) tickRect.width / (max + - min); + if (drawInverted()) + { + loc += tickRect.width; + increment *= -1; + } + for (int i = min; i <= max; i += minorSpace) + { + paintMinorTickForHorizSlider(g, tickRect, (int) loc); + loc += increment; + } + } + else + { + double loc = tickRect.height + tickRect.y; + double increment = (max == min) ? 0 + : -minorSpace * (double) tickRect.height / (max + - min); + if (drawInverted()) + { + loc = tickRect.y; + increment *= -1; + } + for (int i = min; i <= max; i += minorSpace) + { + paintMinorTickForVertSlider(g, tickRect, (int) loc); + loc += increment; + } + } + } + } + + /* Minor ticks start at 1/4 of the height (or width) of the tickRect and extend + to 1/2 of the tickRect. + + Major ticks start at 1/4 of the height and extend to 3/4. + */ + + /** + * This method paints a minor tick for a horizontal slider at the given x + * value. x represents the x coordinate to paint at. + * + * @param g The {@link Graphics} object to draw with. + * @param tickBounds The tickRect rectangle. + * @param x The x coordinate to draw the tick at. + */ + protected void paintMinorTickForHorizSlider(Graphics g, + Rectangle tickBounds, int x) + { + int y = tickRect.y + tickRect.height / 4; + Color saved = g.getColor(); + g.setColor(Color.BLACK); + + g.drawLine(x, y, x, y + tickRect.height / 4); + g.setColor(saved); + } + + /** + * This method paints a major tick for a horizontal slider at the given x + * value. x represents the x coordinate to paint at. + * + * @param g The {@link Graphics} object to draw with. + * @param tickBounds The tickRect rectangle. + * @param x The x coordinate to draw the tick at. + */ + protected void paintMajorTickForHorizSlider(Graphics g, + Rectangle tickBounds, int x) + { + int y = tickRect.y + tickRect.height / 4; + Color saved = g.getColor(); + g.setColor(Color.BLACK); + + g.drawLine(x, y, x, y + tickRect.height / 2); + g.setColor(saved); + } + + /** + * This method paints a minor tick for a vertical slider at the given y + * value. y represents the y coordinate to paint at. + * + * @param g The {@link Graphics} object to draw with. + * @param tickBounds The tickRect rectangle. + * @param y The y coordinate to draw the tick at. + */ + protected void paintMinorTickForVertSlider(Graphics g, Rectangle tickBounds, + int y) + { + int x = tickRect.x + tickRect.width / 4; + Color saved = g.getColor(); + g.setColor(Color.BLACK); + + g.drawLine(x, y, x + tickRect.width / 4, y); + g.setColor(saved); + } + + /** + * This method paints a major tick for a vertical slider at the given y + * value. y represents the y coordinate to paint at. + * + * @param g The {@link Graphics} object to draw with. + * @param tickBounds The tickRect rectangle. + * @param y The y coordinate to draw the tick at. + */ + protected void paintMajorTickForVertSlider(Graphics g, Rectangle tickBounds, + int y) + { + int x = tickRect.x + tickRect.width / 4; + Color saved = g.getColor(); + g.setColor(Color.BLACK); + + g.drawLine(x, y, x + tickRect.width / 2, y); + g.setColor(saved); + } + + /** + * This method paints all the labels from the slider's label table. This + * method must make sure that the label table is not null before painting + * the labels. Each entry in the label table is a (integer, component) + * pair. Every label is painted at the value of the integer. + * + * @param g The {@link Graphics} object to draw with. + */ + public void paintLabels(Graphics g) + { + if (slider.getLabelTable() != null) + { + Dictionary table = slider.getLabelTable(); + Integer tmpKey; + Object key; + Object element; + Component label; + if (slider.getOrientation() == JSlider.HORIZONTAL) + { + for (Enumeration list = table.keys(); list.hasMoreElements();) + { + key = list.nextElement(); + if (! (key instanceof Integer)) + continue; + tmpKey = (Integer) key; + element = table.get(tmpKey); + // We won't paint them if they're not + // JLabels so continue anyway + if (! (element instanceof JLabel)) + continue; + label = (Component) element; + paintHorizontalLabel(g, tmpKey.intValue(), label); + } + } + else + { + for (Enumeration list = table.keys(); list.hasMoreElements();) + { + key = list.nextElement(); + if (! (key instanceof Integer)) + continue; + tmpKey = (Integer) key; + element = table.get(tmpKey); + // We won't paint them if they're not + // JLabels so continue anyway + if (! (element instanceof JLabel)) + continue; + label = (Component) element; + paintVerticalLabel(g, tmpKey.intValue(), label); + } + } + } + } + + /** + * This method paints the label on the horizontal slider at the value + * specified. The value is not a coordinate. It is a value within the range + * of the slider. If the value is not within the range of the slider, this + * method will do nothing. This method should not paint outside the + * boundaries of the labelRect. + * + * @param g The {@link Graphics} object to draw with. + * @param value The value to paint at. + * @param label The label to paint. + */ + protected void paintHorizontalLabel(Graphics g, int value, Component label) + { + // This relies on clipping working properly or we'll end up + // painting all over the place. If our preferred size is ignored, then + // the labels may not fit inside the slider's bounds. Rather than mucking + // with font sizes and possible icon sizes, we'll set the bounds for + // the label and let it get clipped. + Dimension dim = label.getPreferredSize(); + int w = (int) dim.getWidth(); + int h = (int) dim.getHeight(); + + int max = slider.getMaximum(); + int min = slider.getMinimum(); + + if (value > max || value < min) + return; + + // value + // | + // ------------ + // | | + // | | + // | | + // The label must move w/2 to the right to fit directly under the value. + int xpos = xPositionForValue(value) - w / 2; + int ypos = labelRect.y; + + // We want to center the label around the xPositionForValue + // So we use xpos - w / 2. However, if value is min and the label + // is large, we run the risk of going out of bounds. So we bring it back + // to 0 if it becomes negative. + if (xpos < 0) + xpos = 0; + + // If the label + starting x position is greater than + // the x space in the label rectangle, we reset it to the largest + // amount possible in the rectangle. This means ugliness. + if (xpos + w > labelRect.x + labelRect.width) + w = labelRect.x + labelRect.width - xpos; + + // If the label is too tall. We reset it to the height of the label + // rectangle. + if (h > labelRect.height) + h = labelRect.height; + + label.setBounds(xpos, ypos, w, h); + javax.swing.SwingUtilities.paintComponent(g, label, null, label.getBounds()); + } + + /** + * This method paints the label on the vertical slider at the value + * specified. The value is not a coordinate. It is a value within the range + * of the slider. If the value is not within the range of the slider, this + * method will do nothing. This method should not paint outside the + * boundaries of the labelRect. + * + * @param g The {@link Graphics} object to draw with. + * @param value The value to paint at. + * @param label The label to paint. + */ + protected void paintVerticalLabel(Graphics g, int value, Component label) + { + Dimension dim = label.getPreferredSize(); + int w = (int) dim.getWidth(); + int h = (int) dim.getHeight(); + + int max = slider.getMaximum(); + int min = slider.getMinimum(); + + if (value > max || value < min) + return; + + int xpos = labelRect.x; + int ypos = yPositionForValue(value) - h / 2; + + if (ypos < 0) + ypos = 0; + + if (ypos + h > labelRect.y + labelRect.height) + h = labelRect.y + labelRect.height - ypos; + + if (w > labelRect.width) + w = labelRect.width; + + label.setBounds(xpos, ypos, w, h); + javax.swing.SwingUtilities.paintComponent(g, label, null, label.getBounds()); + } + + /** + * <p> + * This method paints a thumb. There are two types of thumb: + * </p> + * <pre> + * Vertical Horizontal + * a---b a-----b + * | | | \ + * e c | c + * \ / | / + * d e-----d + * </pre> + * + * <p> + * In the case of vertical thumbs, we highlight the path b-a-e-d and shadow + * the path b-c-d. In the case of horizontal thumbs, we highlight the path + * c-b-a-e and shadow the path c-d-e. In both cases we fill the path + * a-b-c-d-e before shadows and highlights are drawn. + * </p> + * + * @param g The graphics object to paint with + */ + public void paintThumb(Graphics g) + { + Color saved_color = g.getColor(); + + Polygon thumb = new Polygon(); + + Point a = new Point(thumbRect.x, thumbRect.y); + Point b = new Point(a); + Point c = new Point(a); + Point d = new Point(a); + Point e = new Point(a); + + Polygon bright; + Polygon dark; + Polygon all; + + // This will be in X-dimension if the slider is inverted and y if it isn't. + int turnPoint; + + if (slider.getOrientation() == JSlider.HORIZONTAL) + { + turnPoint = thumbRect.height * 3 / 4; + + b.translate(thumbRect.width, 0); + c.translate(thumbRect.width, turnPoint); + d.translate(thumbRect.width / 2, thumbRect.height); + e.translate(0, turnPoint); + + bright = new Polygon(new int[] { b.x, a.x, e.x, d.x }, + new int[] { b.y, a.y, e.y, d.y }, 4); + + dark = new Polygon(new int[] { b.x, c.x, d.x }, + new int[] { b.y, c.y, d.y }, 3); + all = new Polygon(new int[] { a.x + 1, b.x, c.x, d.x, e.x + 1 }, + new int[] { a.y + 1, b.y + 1, c.y, d.y + 1, e.y }, 5); + } + else + { + turnPoint = thumbRect.width * 3 / 4; + + b.translate(turnPoint, 0); + c.translate(thumbRect.width, thumbRect.height / 2); + d.translate(turnPoint, thumbRect.height); + e.translate(0, thumbRect.height); + + bright = new Polygon(new int[] { c.x, b.x, a.x, e.x }, + new int[] { c.y, b.y, a.y, e.y }, 4); + + dark = new Polygon(new int[] { c.x, d.x, e.x + 1 }, + new int[] { c.y, d.y, e.y }, 3); + + all = new Polygon(new int[] { a.x + 1, b.x, c.x - 1, d.x, e.x + 1 }, + new int[] { a.y + 1, b.y + 1, c.y, d.y, e.y }, 5); + } + + g.setColor(Color.WHITE); + g.drawPolyline(bright.xpoints, bright.ypoints, bright.npoints); + + g.setColor(Color.BLACK); + g.drawPolyline(dark.xpoints, dark.ypoints, dark.npoints); + + g.setColor(Color.GRAY); + g.fillPolygon(all); + + g.setColor(saved_color); + } + + /** + * This method sets the position of the thumbRect. + * + * @param x The new x position. + * @param y The new y position. + */ + public void setThumbLocation(int x, int y) + { + thumbRect.x = x; + thumbRect.y = y; + } + + /** + * This method is used to move the thumb one block in the direction + * specified. If the slider snaps to ticks, this method is responsible for + * snapping it to a tick after the thumb has been moved. + * + * @param direction The direction to move in. + */ + public void scrollByBlock(int direction) + { + // The direction is -1 for backwards and 1 for forwards. + int unit = direction * (slider.getMaximum() - slider.getMinimum()) / 10; + + int moveTo = slider.getValue() + unit; + + if (slider.getSnapToTicks()) + moveTo = findClosestTick(moveTo); + + slider.setValue(moveTo); + } + + /** + * This method is used to move the thumb one unit in the direction + * specified. If the slider snaps to ticks, this method is responsible for + * snapping it to a tick after the thumb has been moved. + * + * @param direction The direction to move in. + */ + public void scrollByUnit(int direction) + { + // The direction is -1 for backwards and 1 for forwards. + int moveTo = slider.getValue() + direction; + + if (slider.getSnapToTicks()) + moveTo = findClosestTick(moveTo); + + slider.setValue(moveTo); + } + + /** + * This method is called when there has been a click in the track and the + * thumb needs to be scrolled on regular intervals. This method is only + * responsible for starting the timer and not for stopping it. + * + * @param dir The direction to move in. + */ + protected void scrollDueToClickInTrack(int dir) + { + scrollTimer.stop(); + + scrollListener.setDirection(dir); + scrollListener.setScrollByBlock(true); + + scrollTimer.start(); + } + + /** + * This method returns the X coordinate for the value passed in. + * + * @param value The value to calculate an x coordinate for. + * + * @return The x coordinate for the value. + */ + protected int xPositionForValue(int value) + { + int min = slider.getMinimum(); + int max = slider.getMaximum(); + int extent = slider.getExtent(); + int len = trackRect.width; + + int xPos = (max == min) ? 0 : (value - min) * len / (max - min); + + if (! drawInverted()) + xPos += trackRect.x; + else + { + xPos = trackRect.width - xPos; + xPos += trackRect.x; + } + return xPos; + } + + /** + * This method returns the y coordinate for the value passed in. + * + * @param value The value to calculate a y coordinate for. + * + * @return The y coordinate for the value. + */ + protected int yPositionForValue(int value) + { + int min = slider.getMinimum(); + int max = slider.getMaximum(); + int extent = slider.getExtent(); + int len = trackRect.height; + + int yPos = (max == min) ? 0 : (value - min) * len / (max - min); + + if (! drawInverted()) + { + yPos = trackRect.height - yPos; + yPos += trackRect.y; + } + else + yPos += trackRect.y; + return yPos; + } + + /** + * This method returns the value in the slider's range given the y + * coordinate. If the value is out of range, it will return the closest + * legal value. + * + * @param yPos The y coordinate to calculate a value for. + * + * @return The value for the y coordinate. + */ + public int valueForYPosition(int yPos) + { + int min = slider.getMinimum(); + int max = slider.getMaximum(); + int len = trackRect.height; + + int value; + + // If the length is 0, you shouldn't be able to even see where the slider is. + // This really shouldn't ever happen, but just in case, we'll return the middle. + if (len == 0) + return ((max - min) / 2); + + if (! drawInverted()) + value = ((len - (yPos - trackRect.y)) * (max - min) / len + min); + else + value = ((yPos - trackRect.y) * (max - min) / len + min); + + // If this isn't a legal value, then we'll have to move to one now. + if (value > max) + value = max; + else if (value < min) + value = min; + return value; + } + + /** + * This method returns the value in the slider's range given the x + * coordinate. If the value is out of range, it will return the closest + * legal value. + * + * @param xPos The x coordinate to calculate a value for. + * + * @return The value for the x coordinate. + */ + public int valueForXPosition(int xPos) + { + int min = slider.getMinimum(); + int max = slider.getMaximum(); + int len = trackRect.width; + + int value; + + // If the length is 0, you shouldn't be able to even see where the slider is. + // This really shouldn't ever happen, but just in case, we'll return the middle. + if (len == 0) + return ((max - min) / 2); + + if (! drawInverted()) + value = ((xPos - trackRect.x) * (max - min) / len + min); + else + value = ((len - (xPos - trackRect.x)) * (max - min) / len + min); + + // If this isn't a legal value, then we'll have to move to one now. + if (value > max) + value = max; + else if (value < min) + value = min; + return value; + } + + /** + * This method finds the closest value that has a tick associated with it. + * This is package-private to avoid an accessor method. + * + * @param value The value to search from. + * + * @return The closest value that has a tick associated with it. + */ + int findClosestTick(int value) + { + int min = slider.getMinimum(); + int max = slider.getMaximum(); + int majorSpace = slider.getMajorTickSpacing(); + int minorSpace = slider.getMinorTickSpacing(); + + // The default value to return is value + minor or + // value + major. + // Initializing at min - value leaves us with a default + // return value of min, which always has tick marks + // (if ticks are painted). + int minor = min - value; + int major = min - value; + + // If there are no major tick marks or minor tick marks + // e.g. snap is set to true but no ticks are set, then + // we can just return the value. + if (majorSpace <= 0 && minorSpace <= 0) + return value; + + // First check the major ticks. + if (majorSpace > 0) + { + int lowerBound = (value - min) / majorSpace; + int majLower = majorSpace * lowerBound + min; + int majHigher = majorSpace * (lowerBound + 1) + min; + + if (majHigher <= max && majHigher - value <= value - majLower) + major = majHigher - value; + else + major = majLower - value; + } + + if (minorSpace > 0) + { + int lowerBound = value / minorSpace; + int minLower = minorSpace * lowerBound; + int minHigher = minorSpace * (lowerBound + 1); + + if (minHigher <= max && minHigher - value <= value - minLower) + minor = minHigher - value; + else + minor = minLower - value; + } + + // Give preference to minor ticks + if (Math.abs(minor) > Math.abs(major)) + return value + major; + else + return value + minor; + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicSpinnerUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicSpinnerUI.java new file mode 100644 index 0000000..97ab97b --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicSpinnerUI.java @@ -0,0 +1,574 @@ +/* SpinnerUI.java -- + Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Insets; +import java.awt.LayoutManager; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JSpinner; +import javax.swing.Timer; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.SpinnerUI; + +/** + * DOCUMENT ME! + * + * @author Ka-Hing Cheung + * + * @see javax.swing.JSpinner + * @since 1.4 + */ +public class BasicSpinnerUI extends SpinnerUI +{ + /** + * Creates a new <code>ComponentUI</code> for the specified + * <code>JComponent</code> + * + * @param c DOCUMENT ME! + * + * @return a ComponentUI + */ + public static ComponentUI createUI(JComponent c) + { + return new BasicSpinnerUI(); + } + + /** + * Creates an editor component. Really, it just returns + * <code>JSpinner.getEditor()</code> + * + * @return a JComponent as an editor + * + * @see javax.swing.JSpinner#getEditor + */ + protected JComponent createEditor() + { + return spinner.getEditor(); + } + + /** + * Creates a <code>LayoutManager</code> that layouts the sub components. The + * subcomponents are identifies by the constraint "Next", "Previous" and + * "Editor" + * + * @return a LayoutManager + * + * @see java.awt.LayoutManager + */ + protected LayoutManager createLayout() + { + return new DefaultLayoutManager(); + } + + /** + * Creates the "Next" button + * + * @return the next button component + */ + protected Component createNextButton() + { + JButton button = new BasicArrowButton(BasicArrowButton.NORTH); + return button; + } + + /** + * Creates the "Previous" button + * + * @return the previous button component + */ + protected Component createPreviousButton() + { + JButton button = new BasicArrowButton(BasicArrowButton.SOUTH); + return button; + } + + /** + * Creates the <code>PropertyChangeListener</code> that will be attached by + * <code>installListeners</code>. It should watch for the "editor" + * property, when it's changed, replace the old editor with the new one, + * probably by calling <code>replaceEditor</code> + * + * @return a PropertyChangeListener + * + * @see #replaceEditor + */ + protected PropertyChangeListener createPropertyChangeListener() + { + return new PropertyChangeListener() + { + public void propertyChange(PropertyChangeEvent evt) + { + // FIXME: Add check for enabled property change. Need to + // disable the buttons. + if ("editor".equals(evt.getPropertyName())) + BasicSpinnerUI.this.replaceEditor((JComponent) evt.getOldValue(), + (JComponent) evt.getNewValue()); + } + }; + } + + /** + * Called by <code>installUI</code>. This should set various defaults + * obtained from <code>UIManager.getLookAndFeelDefaults</code>, as well as + * set the layout obtained from <code>createLayout</code> + * + * @see javax.swing.UIManager#getLookAndFeelDefaults + * @see #createLayout + * @see #installUI + */ + protected void installDefaults() + { + /* most of it copied from BasicLabelUI, I don't know what keys are + available, so someone may want to update this. Hence: TODO + */ + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + /* + spinner.setForeground(defaults.getColor("Spinner.foreground")); + spinner.setBackground(defaults.getColor("Spinner.background")); + spinner.setFont(defaults.getFont("Spinner.font")); + spinner.setBorder(defaults.getBorder("Spinner.border")); + */ + spinner.setLayout(createLayout()); + spinner.setOpaque(true); + } + + /* + * Called by <code>installUI</code>, which basically adds the + * <code>PropertyChangeListener</code> created by + * <code>createPropertyChangeListener</code> + * + * @see #createPropertyChangeListener + * @see #installUI + */ + protected void installListeners() + { + spinner.addPropertyChangeListener(listener); + } + + /* + * Install listeners to the next button so that it increments the model + */ + protected void installNextButtonListeners(Component c) + { + c.addMouseListener(new MouseAdapter() + { + public void mousePressed(MouseEvent evt) + { + if (! spinner.isEnabled()) + return; + increment(); + timer.setInitialDelay(500); + timer.start(); + } + + public void mouseReleased(MouseEvent evt) + { + timer.stop(); + } + + void increment() + { + Object next = BasicSpinnerUI.this.spinner.getNextValue(); + if (next != null) + BasicSpinnerUI.this.spinner.getModel().setValue(next); + } + + volatile boolean mouseDown = false; + Timer timer = new Timer(50, + new ActionListener() + { + public void actionPerformed(ActionEvent event) + { + increment(); + } + }); + }); + } + + /* + * Install listeners to the previous button so that it decrements the model + */ + protected void installPreviousButtonListeners(Component c) + { + c.addMouseListener(new MouseAdapter() + { + public void mousePressed(MouseEvent evt) + { + if (! spinner.isEnabled()) + return; + decrement(); + timer.setInitialDelay(500); + timer.start(); + } + + public void mouseReleased(MouseEvent evt) + { + timer.stop(); + } + + void decrement() + { + Object prev = BasicSpinnerUI.this.spinner.getPreviousValue(); + if (prev != null) + BasicSpinnerUI.this.spinner.getModel().setValue(prev); + } + + volatile boolean mouseDown = false; + Timer timer = new Timer(50, + new ActionListener() + { + public void actionPerformed(ActionEvent event) + { + decrement(); + } + }); + }); + } + + /** + * Install this UI to the <code>JComponent</code>, which in reality, is a + * <code>JSpinner</code>. Calls <code>installDefaults</code>, + * <code>installListeners</code>, and also adds the buttons and editor. + * + * @param c DOCUMENT ME! + * + * @see #installDefaults + * @see #installListeners + * @see #createNextButton + * @see #createPreviousButton + * @see #createEditor + */ + public void installUI(JComponent c) + { + super.installUI(c); + + spinner = (JSpinner) c; + + installDefaults(); + installListeners(); + + Component next = createNextButton(); + Component previous = createPreviousButton(); + + installNextButtonListeners(next); + installPreviousButtonListeners(previous); + + c.add(createEditor(), "Editor"); + c.add(next, "Next"); + c.add(previous, "Previous"); + } + + /** + * Replace the old editor with the new one + * + * @param oldEditor the old editor + * @param newEditor the new one to replace with + */ + protected void replaceEditor(JComponent oldEditor, JComponent newEditor) + { + spinner.remove(oldEditor); + spinner.add(newEditor); + } + + /** + * The reverse of <code>installDefaults</code>. Called by + * <code>uninstallUI</code> + */ + protected void uninstallDefaults() + { + spinner.setLayout(null); + } + + /** + * The reverse of <code>installListeners</code>, called by + * <code>uninstallUI</code> + */ + protected void uninstallListeners() + { + spinner.removePropertyChangeListener(listener); + } + + /** + * Called when the current L&F is replaced with another one, should call + * <code>uninstallDefaults</code> and <code>uninstallListeners</code> as + * well as remove the next/previous buttons and the editor + * + * @param c DOCUMENT ME! + */ + public void uninstallUI(JComponent c) + { + super.uninstallUI(c); + + uninstallDefaults(); + uninstallListeners(); + c.removeAll(); + } + + /** The spinner for this UI */ + protected JSpinner spinner; + + /** DOCUMENT ME! */ + private PropertyChangeListener listener = createPropertyChangeListener(); + + /** + * DOCUMENT ME! + */ + private class DefaultLayoutManager implements LayoutManager + { + /** + * DOCUMENT ME! + * + * @param parent DOCUMENT ME! + */ + public void layoutContainer(Container parent) + { + synchronized (parent.getTreeLock()) + { + Insets i = parent.getInsets(); + boolean l2r = parent.getComponentOrientation().isLeftToRight(); + /* + -------------- -------------- + | | n | | n | | + | e | - | or | - | e | + | | p | | p | | + -------------- -------------- + */ + Dimension e = minSize(editor); + Dimension n = minSize(next); + Dimension p = minSize(previous); + Dimension s = spinner.getPreferredSize(); + + int x = l2r ? i.left : i.right; + int y = i.top; + int w = Math.max(p.width, n.width); + int h = Math.max(p.height, n.height); + h = Math.max(h, e.height / 2); + int e_width = s.width - w; + + if (l2r) + { + setBounds(editor, x, y + (s.height - e.height) / 2, e_width, + e.height); + x += e_width; + + setBounds(next, x, y, w, h); + y += h; + + setBounds(previous, x, y, w, h); + } + else + { + setBounds(next, x, y + (s.height - e.height) / 2, w, h); + y += h; + + setBounds(previous, x, y, w, h); + x += w; + y -= h; + + setBounds(editor, x, y, e_width, e.height); + } + } + } + + /** + * DOCUMENT ME! + * + * @param parent DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Dimension minimumLayoutSize(Container parent) + { + Dimension d = new Dimension(); + + if (editor != null) + { + Dimension tmp = editor.getMinimumSize(); + d.width += tmp.width; + d.height = tmp.height; + } + + int nextWidth = 0; + int previousWidth = 0; + int otherHeight = 0; + + if (next != null) + { + Dimension tmp = next.getMinimumSize(); + nextWidth = tmp.width; + otherHeight += tmp.height; + } + if (previous != null) + { + Dimension tmp = previous.getMinimumSize(); + previousWidth = tmp.width; + otherHeight += tmp.height; + } + + d.height = Math.max(d.height, otherHeight); + d.width += Math.max(nextWidth, previousWidth); + + return d; + } + + /** + * DOCUMENT ME! + * + * @param parent DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + public Dimension preferredLayoutSize(Container parent) + { + Dimension d = new Dimension(); + + if (editor != null) + { + Dimension tmp = editor.getPreferredSize(); + d.width += Math.max(tmp.width, 40); + d.height = tmp.height; + } + + int nextWidth = 0; + int previousWidth = 0; + int otherHeight = 0; + + if (next != null) + { + Dimension tmp = next.getPreferredSize(); + nextWidth = tmp.width; + otherHeight += tmp.height; + } + if (previous != null) + { + Dimension tmp = previous.getPreferredSize(); + previousWidth = tmp.width; + otherHeight += tmp.height; + } + + d.height = Math.max(d.height, otherHeight); + d.width += Math.max(nextWidth, previousWidth); + + return d; + } + + /** + * DOCUMENT ME! + * + * @param child DOCUMENT ME! + */ + public void removeLayoutComponent(Component child) + { + if (child == editor) + editor = null; + else if (child == next) + next = null; + else if (previous == child) + previous = null; + } + + /** + * DOCUMENT ME! + * + * @param name DOCUMENT ME! + * @param child DOCUMENT ME! + */ + public void addLayoutComponent(String name, Component child) + { + if ("Editor".equals(name)) + editor = child; + else if ("Next".equals(name)) + next = child; + else if ("Previous".equals(name)) + previous = child; + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + * + * @return DOCUMENT ME! + */ + private Dimension minSize(Component c) + { + if (c == null) + return new Dimension(); + else + return c.getMinimumSize(); + } + + /** + * DOCUMENT ME! + * + * @param c DOCUMENT ME! + * @param x DOCUMENT ME! + * @param y DOCUMENT ME! + * @param w DOCUMENT ME! + * @param h DOCUMENT ME! + */ + private void setBounds(Component c, int x, int y, int w, int h) + { + if (c != null) + c.setBounds(x, y, w, h); + } + + /** DOCUMENT ME! */ + private Component editor; + + /** DOCUMENT ME! */ + private Component next; + + /** DOCUMENT ME! */ + private Component previous; + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneDivider.java b/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneDivider.java new file mode 100644 index 0000000..b8674ed --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneDivider.java @@ -0,0 +1,912 @@ +/* BasicSplitPaneDivider.java -- + Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.LayoutManager; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.JButton; +import javax.swing.JSplitPane; +import javax.swing.SwingConstants; +import javax.swing.border.Border; + +/** + * The divider that separates the two parts of a JSplitPane in the Basic look + * and feel. + * + * <p> + * Implementation status: We do not have a real implementation yet. Currently, + * it is mostly a stub to allow compiling other parts of the + * javax.swing.plaf.basic package, although some parts are already + * functional. + * </p> + * + * @author Sascha Brawer (brawer_AT_dandelis.ch) + */ +public class BasicSplitPaneDivider extends Container + implements PropertyChangeListener +{ + /** + * Determined using the <code>serialver</code> tool of Apple/Sun JDK 1.3.1 + * on MacOS X 10.1.5. + */ + static final long serialVersionUID = 1463404307042803342L; + + /** + * The width and height of the little buttons for showing and hiding parts + * of a JSplitPane in a single mouse click. + */ + protected static final int ONE_TOUCH_SIZE = 6; + + /** The distance the one touch buttons will sit from the divider's edges. */ + protected static final int ONE_TOUCH_OFFSET = 2; + + /** + * An object that performs the tasks associated with an ongoing drag + * operation, or <code>null</code> if the user is currently not dragging + * the divider. + */ + protected DragController dragger; + + /** + * The delegate object that is responsible for the UI of the + * <code>JSplitPane</code> that contains this divider. + */ + protected BasicSplitPaneUI splitPaneUI; + + /** The thickness of the divider in pixels. */ + protected int dividerSize; + + /** A divider that is used for layout purposes. */ + protected Component hiddenDivider; + + /** The JSplitPane containing this divider. */ + protected JSplitPane splitPane; + + /** + * The listener for handling mouse events from both the divider and the + * containing <code>JSplitPane</code>. + * + * <p> + * The reason for also handling MouseEvents from the containing + * <code>JSplitPane</code> is that users should be able to start a drag + * gesture from inside the JSplitPane, but slightly outisde the divider. + * </p> + */ + protected MouseHandler mouseHandler = new MouseHandler(); + + /** + * The current orientation of the containing <code>JSplitPane</code>, which + * is either {@link javax.swing.JSplitPane#HORIZONTAL_SPLIT} or {@link + * javax.swing.JSplitPane#VERTICAL_SPLIT}. + */ + protected int orientation; + + /** + * The button for showing and hiding the left (or top) component of the + * <code>JSplitPane</code>. + */ + protected JButton leftButton; + + /** + * The button for showing and hiding the right (or bottom) component of the + * <code>JSplitPane</code>. + */ + protected JButton rightButton; + + /** + * The border of this divider. Typically, this will be an instance of {@link + * javax.swing.plaf.basic.BasicBorders.SplitPaneDividerBorder}. + * + * @see #getBorder() + * @see #setBorder(javax.swing.border.Border) + */ + private Border border; + + // This is not a pixel count. + // This int should be able to take 3 values. + // left (top), middle, right(bottom) + // 0 1 2 + + /** + * Keeps track of where the divider should be placed when using one touch + * expand buttons. + * This is package-private to avoid an accessor method. + */ + transient int currentDividerLocation = 1; + + /** DOCUMENT ME! */ + private transient Border tmpBorder = new Border() + { + public Insets getBorderInsets(Component c) + { + return new Insets(2, 2, 2, 2); + } + + public boolean isBorderOpaque() + { + return false; + } + + public void paintBorder(Component c, Graphics g, int x, int y, + int width, int height) + { + Color saved = g.getColor(); + g.setColor(Color.BLACK); + + g.drawRect(x + 2, y + 2, width - 4, height - 4); + + g.setColor(saved); + } + }; + + /** + * Constructs a new divider. + * + * @param ui the UI delegate of the enclosing <code>JSplitPane</code>. + */ + public BasicSplitPaneDivider(BasicSplitPaneUI ui) + { + setLayout(new DividerLayout()); + setBasicSplitPaneUI(ui); + setDividerSize(splitPane.getDividerSize()); + setBorder(tmpBorder); + } + + /** + * Sets the delegate object that is responsible for the UI of the {@link + * javax.swing.JSplitPane} containing this divider. + * + * @param newUI the UI delegate, or <code>null</code> to release the + * connection to the current delegate. + */ + public void setBasicSplitPaneUI(BasicSplitPaneUI newUI) + { + /* Remove the connection to the existing JSplitPane. */ + if (splitPane != null) + { + splitPane.removePropertyChangeListener(this); + splitPane.removeMouseListener(mouseHandler); + splitPane.removeMouseMotionListener(mouseHandler); + removeMouseListener(mouseHandler); + removeMouseMotionListener(mouseHandler); + splitPane = null; + hiddenDivider = null; + } + + /* Establish the connection to the new JSplitPane. */ + splitPaneUI = newUI; + if (splitPaneUI != null) + splitPane = newUI.getSplitPane(); + if (splitPane != null) + { + splitPane.addPropertyChangeListener(this); + splitPane.addMouseListener(mouseHandler); + splitPane.addMouseMotionListener(mouseHandler); + addMouseListener(mouseHandler); + addMouseMotionListener(mouseHandler); + hiddenDivider = splitPaneUI.getNonContinuousLayoutDivider(); + orientation = splitPane.getOrientation(); + oneTouchExpandableChanged(); + } + } + + /** + * Returns the delegate object that is responsible for the UI of the {@link + * javax.swing.JSplitPane} containing this divider. + * + * @return The UI for the JSplitPane. + */ + public BasicSplitPaneUI getBasicSplitPaneUI() + { + return splitPaneUI; + } + + /** + * Sets the thickness of the divider. + * + * @param newSize the new width or height in pixels. + */ + public void setDividerSize(int newSize) + { + this.dividerSize = newSize; + } + + /** + * Retrieves the thickness of the divider. + * + * @return The thickness of the divider. + */ + public int getDividerSize() + { + return dividerSize; + } + + /** + * Sets the border of this divider. + * + * @param border the new border. Typically, this will be an instance of + * {@link + * javax.swing.plaf.basic.BasicBorders.SplitPaneBorder}. + * + * @since 1.3 + */ + public void setBorder(Border border) + { + if (border != this.border) + { + Border oldValue = this.border; + this.border = border; + firePropertyChange("border", oldValue, border); + } + } + + /** + * Retrieves the border of this divider. + * + * @return the current border, or <code>null</code> if no border has been + * set. + * + * @since 1.3 + */ + public Border getBorder() + { + return border; + } + + /** + * Retrieves the insets of the divider. If a border has been installed on + * the divider, the result of calling its <code>getBorderInsets</code> + * method is returned. Otherwise, the inherited implementation will be + * invoked. + * + * @see javax.swing.border.Border#getBorderInsets(java.awt.Component) + */ + public Insets getInsets() + { + if (border != null) + return border.getBorderInsets(this); + else + return super.getInsets(); + } + + /** + * Returns the preferred size of this divider, which is + * <code>dividerSize</code> by <code>dividerSize</code> pixels. + * + * @return The preferred size of the divider. + */ + public Dimension getPreferredSize() + { + return getLayout().preferredLayoutSize(this); + } + + /** + * Returns the minimal size of this divider, which is + * <code>dividerSize</code> by <code>dividerSize</code> pixels. + * + * @return The minimal size of the divider. + */ + public Dimension getMinimumSize() + { + return getPreferredSize(); + } + + /** + * Processes events from the <code>JSplitPane</code> that contains this + * divider. + * + * @param e The PropertyChangeEvent. + */ + public void propertyChange(PropertyChangeEvent e) + { + if (e.getPropertyName().equals(JSplitPane.ONE_TOUCH_EXPANDABLE_PROPERTY)) + oneTouchExpandableChanged(); + else if (e.getPropertyName().equals(JSplitPane.ORIENTATION_PROPERTY)) + { + orientation = splitPane.getOrientation(); + if (splitPane.isOneTouchExpandable()) + { + layout(); + repaint(); + } + } + else if (e.getPropertyName().equals(JSplitPane.DIVIDER_SIZE_PROPERTY)) + dividerSize = splitPane.getDividerSize(); + } + + /** + * Paints the divider by painting its border. + * + * @param g The Graphics Object to paint with. + */ + public void paint(Graphics g) + { + Dimension dividerSize; + + super.paint(g); + if (border != null) + { + dividerSize = getSize(); + border.paintBorder(this, g, 0, 0, dividerSize.width, dividerSize.height); + } + } + + /** + * Reacts to changes of the <code>oneToughExpandable</code> property of the + * containing <code>JSplitPane</code>. + */ + protected void oneTouchExpandableChanged() + { + if (splitPane.isOneTouchExpandable()) + { + leftButton = createLeftOneTouchButton(); + rightButton = createRightOneTouchButton(); + add(leftButton); + add(rightButton); + + leftButton.addMouseListener(mouseHandler); + rightButton.addMouseListener(mouseHandler); + + // Set it to 1. + currentDividerLocation = 1; + } + else + { + if (leftButton != null && rightButton != null) + { + leftButton.removeMouseListener(mouseHandler); + rightButton.removeMouseListener(mouseHandler); + + remove(leftButton); + remove(rightButton); + leftButton = null; + rightButton = null; + } + } + layout(); + repaint(); + } + + /** + * Creates a button for showing and hiding the left (or top) part of a + * <code>JSplitPane</code>. + * + * @return The left one touch button. + */ + protected JButton createLeftOneTouchButton() + { + int dir = SwingConstants.WEST; + if (orientation == JSplitPane.VERTICAL_SPLIT) + dir = SwingConstants.NORTH; + JButton button = new BasicArrowButton(dir); + button.setBorder(null); + + return button; + } + + /** + * Creates a button for showing and hiding the right (or bottom) part of a + * <code>JSplitPane</code>. + * + * @return The right one touch button. + */ + protected JButton createRightOneTouchButton() + { + int dir = SwingConstants.EAST; + if (orientation == JSplitPane.VERTICAL_SPLIT) + dir = SwingConstants.SOUTH; + JButton button = new BasicArrowButton(dir); + button.setBorder(null); + return button; + } + + /** + * Prepares the divider for dragging by calling the + * <code>startDragging</code> method of the UI delegate of the enclosing + * <code>JSplitPane</code>. + * + * @see BasicSplitPaneUI#startDragging() + */ + protected void prepareForDragging() + { + if (splitPaneUI != null) + splitPaneUI.startDragging(); + } + + /** + * Drags the divider to a given location by calling the + * <code>dragDividerTo</code> method of the UI delegate of the enclosing + * <code>JSplitPane</code>. + * + * @param location the new location of the divider. + * + * @see BasicSplitPaneUI#dragDividerTo(int location) + */ + protected void dragDividerTo(int location) + { + if (splitPaneUI != null) + splitPaneUI.dragDividerTo(location); + } + + /** + * Finishes a dragging gesture by calling the <code>finishDraggingTo</code> + * method of the UI delegate of the enclosing <code>JSplitPane</code>. + * + * @param location the new, final location of the divider. + * + * @see BasicSplitPaneUI#finishDraggingTo(int location) + */ + protected void finishDraggingTo(int location) + { + if (splitPaneUI != null) + splitPaneUI.finishDraggingTo(location); + } + + /** + * This helper method moves the divider to one of the three locations when + * using one touch expand buttons. Location 0 is the left (or top) most + * location. Location 1 is the middle. Location 2 is the right (or bottom) + * most location. + * This is package-private to avoid an accessor method. + * + * @param locationIndex The location to move to. + */ + void moveDividerTo(int locationIndex) + { + Insets insets = splitPane.getInsets(); + switch (locationIndex) + { + case 1: + splitPane.setDividerLocation(splitPane.getLastDividerLocation()); + break; + case 0: + int top = (orientation == JSplitPane.HORIZONTAL_SPLIT) ? insets.left + : insets.top; + splitPane.setDividerLocation(top); + break; + case 2: + int bottom; + if (orientation == JSplitPane.HORIZONTAL_SPLIT) + bottom = splitPane.getBounds().width - insets.right - dividerSize; + else + bottom = splitPane.getBounds().height - insets.bottom - dividerSize; + splitPane.setDividerLocation(bottom); + break; + } + } + + /** + * The listener for handling mouse events from both the divider and the + * containing <code>JSplitPane</code>. + * + * <p> + * The reason for also handling MouseEvents from the containing + * <code>JSplitPane</code> is that users should be able to start a drag + * gesture from inside the JSplitPane, but slightly outisde the divider. + * </p> + * + * @author Sascha Brawer (brawer_AT_dandelis.ch) + */ + protected class MouseHandler extends MouseAdapter + implements MouseMotionListener + { + /** Keeps track of whether a drag is occurring. */ + private transient boolean isDragging; + + /** + * This method is called when the mouse is pressed. + * + * @param e The MouseEvent. + */ + public void mousePressed(MouseEvent e) + { + if (splitPane.isOneTouchExpandable()) + { + if (e.getSource() == leftButton) + { + currentDividerLocation--; + if (currentDividerLocation < 0) + currentDividerLocation = 0; + moveDividerTo(currentDividerLocation); + return; + } + else if (e.getSource() == rightButton) + { + currentDividerLocation++; + if (currentDividerLocation > 2) + currentDividerLocation = 2; + moveDividerTo(currentDividerLocation); + return; + } + } + isDragging = true; + currentDividerLocation = 1; + if (orientation == JSplitPane.HORIZONTAL_SPLIT) + dragger = new DragController(e); + else + dragger = new VerticalDragController(e); + prepareForDragging(); + } + + /** + * This method is called when the mouse is released. + * + * @param e The MouseEvent. + */ + public void mouseReleased(MouseEvent e) + { + if (isDragging) + dragger.completeDrag(e); + isDragging = false; + } + + /** + * Repeatedly invoked when the user is dragging the mouse cursor while + * having pressed a mouse button. + * + * @param e The MouseEvent. + */ + public void mouseDragged(MouseEvent e) + { + if (dragger != null) + dragger.continueDrag(e); + } + + /** + * Repeatedly invoked when the user is dragging the mouse cursor without + * having pressed a mouse button. + * + * @param e The MouseEvent. + */ + public void mouseMoved(MouseEvent e) + { + // Do nothing. + } + } + + /** + * Performs the tasks associated with an ongoing drag operation. + * + * @author Sascha Brawer (brawer_AT_dandelis.ch) + */ + protected class DragController + { + /** + * The difference between where the mouse is clicked and the initial + * divider location. + */ + transient int offset; + + /** + * Creates a new DragController object. + * + * @param e The MouseEvent to initialize with. + */ + protected DragController(MouseEvent e) + { + offset = e.getX(); + } + + /** + * This method returns true if the divider can move. + * + * @return True if dragging is allowed. + */ + protected boolean isValid() + { + // Views can always be resized? + return true; + } + + /** + * Returns a position for the divider given the MouseEvent. + * + * @param e MouseEvent. + * + * @return The position for the divider to move to. + */ + protected int positionForMouseEvent(MouseEvent e) + { + return e.getX() + getX() - offset; + } + + /** + * This method returns one of the two paramters for the orientation. In + * this case, it returns x. + * + * @param x The x coordinate. + * @param y The y coordinate. + * + * @return The x coordinate. + */ + protected int getNeededLocation(int x, int y) + { + return x; + } + + /** + * This method is called to pass on the drag information to the UI through + * dragDividerTo. + * + * @param newX The x coordinate of the MouseEvent. + * @param newY The y coordinate of the MouseEvent. + */ + protected void continueDrag(int newX, int newY) + { + if (isValid()) + dragDividerTo(adjust(newX, newY)); + } + + /** + * This method is called to pass on the drag information to the UI + * through dragDividerTo. + * + * @param e The MouseEvent. + */ + protected void continueDrag(MouseEvent e) + { + if (isValid()) + dragDividerTo(positionForMouseEvent(e)); + } + + /** + * This method is called to finish the drag session by calling + * finishDraggingTo. + * + * @param x The x coordinate of the MouseEvent. + * @param y The y coordinate of the MouseEvent. + */ + protected void completeDrag(int x, int y) + { + finishDraggingTo(adjust(x, y)); + } + + /** + * This method is called to finish the drag session by calling + * finishDraggingTo. + * + * @param e The MouseEvent. + */ + protected void completeDrag(MouseEvent e) + { + finishDraggingTo(positionForMouseEvent(e)); + } + + /** + * This is a helper method that includes the offset in the needed + * location. + * + * @param x The x coordinate of the MouseEvent. + * @param y The y coordinate of the MouseEvent. + * + * @return The needed location adjusted by the offsets. + */ + int adjust(int x, int y) + { + return getNeededLocation(x, y) + getX() - offset; + } + } + + /** + * This is a helper class that controls dragging when the orientation is + * VERTICAL_SPLIT. + */ + protected class VerticalDragController extends DragController + { + /** + * Creates a new VerticalDragController object. + * + * @param e The MouseEvent to initialize with. + */ + protected VerticalDragController(MouseEvent e) + { + super(e); + offset = e.getY(); + } + + /** + * This method returns one of the two parameters given the orientation. In + * this case, it returns y. + * + * @param x The x coordinate of the MouseEvent. + * @param y The y coordinate of the MouseEvent. + * + * @return The y coordinate. + */ + protected int getNeededLocation(int x, int y) + { + return y; + } + + /** + * This method returns the new location of the divider given a MouseEvent. + * + * @param e The MouseEvent. + * + * @return The new location of the divider. + */ + protected int positionForMouseEvent(MouseEvent e) + { + return e.getY() + getY() - offset; + } + + /** + * This is a helper method that includes the offset in the needed + * location. + * + * @param x The x coordinate of the MouseEvent. + * @param y The y coordinate of the MouseEvent. + * + * @return The needed location adjusted by the offsets. + */ + int adjust(int x, int y) + { + return getNeededLocation(x, y) + getY() - offset; + } + } + + /** + * This helper class acts as the Layout Manager for the divider. + */ + protected class DividerLayout implements LayoutManager + { + /** + * Creates a new DividerLayout object. + */ + protected DividerLayout() + { + } + + /** + * This method is called when a Component is added. + * + * @param string The constraints string. + * @param c The Component to add. + */ + public void addLayoutComponent(String string, Component c) + { + // Do nothing. + } + + /** + * This method is called to lay out the container. + * + * @param c The container to lay out. + */ + public void layoutContainer(Container c) + { + if (splitPane.isOneTouchExpandable()) + { + changeButtonOrientation(); + positionButtons(); + } + } + + /** + * This method returns the minimum layout size. + * + * @param c The container to calculate for. + * + * @return The minimum layout size. + */ + public Dimension minimumLayoutSize(Container c) + { + return preferredLayoutSize(c); + } + + /** + * This method returns the preferred layout size. + * + * @param c The container to calculate for. + * + * @return The preferred layout size. + */ + public Dimension preferredLayoutSize(Container c) + { + return new Dimension(dividerSize, dividerSize); + } + + /** + * This method is called when a component is removed. + * + * @param c The component to remove. + */ + public void removeLayoutComponent(Component c) + { + // Do nothing. + } + + /** + * This method changes the button orientation when the orientation of the + * SplitPane changes. + */ + private void changeButtonOrientation() + { + if (orientation == JSplitPane.HORIZONTAL_SPLIT) + { + ((BasicArrowButton) rightButton).setDirection(SwingConstants.EAST); + ((BasicArrowButton) leftButton).setDirection(SwingConstants.WEST); + } + else + { + ((BasicArrowButton) rightButton).setDirection(SwingConstants.SOUTH); + ((BasicArrowButton) leftButton).setDirection(SwingConstants.NORTH); + } + } + + /** + * This method sizes and positions the buttons. + */ + private void positionButtons() + { + int w = 0; + int h = 0; + if (orientation == JSplitPane.HORIZONTAL_SPLIT) + { + rightButton.setLocation(ONE_TOUCH_OFFSET, ONE_TOUCH_OFFSET); + leftButton.setLocation(ONE_TOUCH_OFFSET, + ONE_TOUCH_OFFSET + 2 * ONE_TOUCH_SIZE); + w = dividerSize - 2 * ONE_TOUCH_OFFSET; + h = 2 * ONE_TOUCH_SIZE; + } + else + { + leftButton.setLocation(ONE_TOUCH_OFFSET, ONE_TOUCH_OFFSET); + rightButton.setLocation(ONE_TOUCH_OFFSET + 2 * ONE_TOUCH_SIZE, + ONE_TOUCH_OFFSET); + h = dividerSize - 2 * ONE_TOUCH_OFFSET; + w = 2 * ONE_TOUCH_SIZE; + } + Dimension dims = new Dimension(w, h); + leftButton.setSize(dims); + rightButton.setSize(dims); + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneUI.java new file mode 100644 index 0000000..ff7e8ac --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneUI.java @@ -0,0 +1,1556 @@ +/* BasicSplitPaneUI.java -- + Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Canvas; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.LayoutManager2; +import java.awt.Point; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.JComponent; +import javax.swing.JSplitPane; +import javax.swing.KeyStroke; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.SplitPaneUI; + +/** + * This is the Basic Look and Feel implementation of the SplitPaneUI class. + */ +public class BasicSplitPaneUI extends SplitPaneUI +{ + /** + * This Layout Manager controls the position and size of the components when + * the JSplitPane's orientation is HORIZONTAL_SPLIT. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class BasicHorizontalLayoutManager implements LayoutManager2 + { + // 3 components at a time. + // LEFT/TOP = 0 + // RIGHT/BOTTOM = 1 + // DIVIDER = 2 + + /** + * This array contains the components in the JSplitPane. The left/top + * component is at index 0, the right/bottom is at 1, and the divider is + * at 2. + */ + protected Component[] components = new Component[3]; + + // These are the _current_ widths of the associated component. + + /** + * This array contains the current width (for HORIZONTAL_SPLIT) or height + * (for VERTICAL_SPLIT) of the components. The indices are the same as + * for components. + */ + protected int[] sizes = new int[3]; + + /** + * This method adds the component given to the JSplitPane. The position of + * the component is given by the constraints object. + * + * @param comp The Component to add. + * @param constraints The constraints that bind the object. + */ + public void addLayoutComponent(Component comp, Object constraints) + { + addLayoutComponent((String) constraints, comp); + } + + /** + * This method is called to add a Component to the JSplitPane. The + * placement string determines where the Component will be placed. The + * string should be one of LEFT, RIGHT, TOP, BOTTOM or null (signals that + * the component is the divider). + * + * @param place The placement of the Component. + * @param component The Component to add. + * + * @throws IllegalArgumentException DOCUMENT ME! + */ + public void addLayoutComponent(String place, Component component) + { + int i = 0; + if (place == null) + i = 2; + else if (place.equals(JSplitPane.TOP) || place.equals(JSplitPane.LEFT)) + i = 0; + else if (place.equals(JSplitPane.BOTTOM) + || place.equals(JSplitPane.RIGHT)) + i = 1; + else + throw new IllegalArgumentException("Illegal placement in JSplitPane"); + components[i] = component; + resetSizeAt(i); + splitPane.revalidate(); + splitPane.repaint(); + } + + /** + * This method returns the width of the JSplitPane minus the insets. + * + * @param containerSize The Dimensions of the JSplitPane. + * @param insets The Insets of the JSplitPane. + * + * @return The width of the JSplitPane minus the insets. + */ + protected int getAvailableSize(Dimension containerSize, Insets insets) + { + return containerSize.width - insets.left - insets.right; + } + + /** + * This method returns the given insets left value. If the given inset is + * null, then 0 is returned. + * + * @param insets The Insets to use with the JSplitPane. + * + * @return The inset's left value. + */ + protected int getInitialLocation(Insets insets) + { + if (insets != null) + return insets.left; + return 0; + } + + /** + * This specifies how a component is aligned with respect to other + * components in the x fdirection. + * + * @param target The container. + * + * @return The component's alignment. + */ + public float getLayoutAlignmentX(Container target) + { + return target.getAlignmentX(); + } + + /** + * This specifies how a component is aligned with respect to other + * components in the y direction. + * + * @param target The container. + * + * @return The component's alignment. + */ + public float getLayoutAlignmentY(Container target) + { + return target.getAlignmentY(); + } + + /** + * This method returns the preferred width of the component. + * + * @param c The component to measure. + * + * @return The preferred width of the component. + */ + protected int getPreferredSizeOfComponent(Component c) + { + Dimension dims = c.getPreferredSize(); + if (dims != null) + return dims.width; + return 0; + } + + /** + * This method returns the current width of the component. + * + * @param c The component to measure. + * + * @return The width of the component. + */ + protected int getSizeOfComponent(Component c) + { + return c.getWidth(); + } + + /** + * This method returns the sizes array. + * + * @return The sizes array. + */ + protected int[] getSizes() + { + return sizes; + } + + /** + * This method invalidates the layout. It does nothing. + * + * @param c The container to invalidate. + */ + public void invalidateLayout(Container c) + { + // DO NOTHING + } + + /** + * This method lays out the components in the container. + * + * @param container The container to lay out. + */ + public void layoutContainer(Container container) + { + if (container instanceof JSplitPane) + { + JSplitPane split = (JSplitPane) container; + distributeExtraSpace(); + Insets insets = split.getInsets(); + int width = getInitialLocation(insets); + Dimension dims = split.getSize(); + for (int i = 0; i < components.length; i += 2) + { + if (components[i] == null) + continue; + setComponentToSize(components[i], sizes[i], width, insets, dims); + width += sizes[i]; + } + if (components[1] != null) + { + setComponentToSize(components[1], sizes[1], width, insets, dims); + width += sizes[1]; + } + } + } + + /** + * This method returns the maximum size for the container given the + * components. It returns a new Dimension object that has width and + * height equal to Integer.MAX_VALUE. + * + * @param target The container to measure. + * + * @return The maximum size. + */ + public Dimension maximumLayoutSize(Container target) + { + return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); + } + + /** + * This method returns the container's minimum size. The minimum width is + * the sum of all the component's minimum widths. The minimum height is + * the maximum of all the components' minimum heights. + * + * @param target The container to measure. + * + * @return The minimum size. + */ + public Dimension minimumLayoutSize(Container target) + { + if (target instanceof JSplitPane) + { + JSplitPane split = (JSplitPane) target; + Insets insets = target.getInsets(); + + int height = 0; + int width = 0; + for (int i = 0; i < components.length; i++) + { + if (components[i] == null) + continue; + Dimension dims = components[i].getMinimumSize(); + if (dims != null) + { + width += dims.width; + height = Math.max(height, dims.height); + } + } + return new Dimension(width, height); + } + return null; + } + + /** + * This method returns the container's preferred size. The preferred width + * is the sum of all the component's preferred widths. The preferred + * height is the maximum of all the components' preferred heights. + * + * @param target The container to measure. + * + * @return The preferred size. + */ + public Dimension preferredLayoutSize(Container target) + { + if (target instanceof JSplitPane) + { + JSplitPane split = (JSplitPane) target; + Insets insets = target.getInsets(); + + int height = 0; + int width = 0; + for (int i = 0; i < components.length; i++) + { + if (components[i] == null) + continue; + Dimension dims = components[i].getPreferredSize(); + if (dims != null) + { + width += dims.width; + if (! (components[i] instanceof BasicSplitPaneDivider)) + height = Math.max(height, dims.height); + } + } + return new Dimension(width, height); + } + return null; + } + + /** + * This method removes the component from the layout. + * + * @param component The component to remove from the layout. + */ + public void removeLayoutComponent(Component component) + { + for (int i = 0; i < components.length; i++) + { + if (component == components[i]) + { + components[i] = null; + sizes[i] = 0; + } + } + } + + /** + * This method resets the size of Component to the preferred size. + * + * @param index The index of the component to reset. + */ + protected void resetSizeAt(int index) + { + if (components[index] != null) + sizes[index] = getPreferredSizeOfComponent(components[index]); + } + + /** + * This method resets the sizes of all the components. + */ + public void resetToPreferredSizes() + { + for (int i = 0; i < components.length; i++) + resetSizeAt(i); + } + + /** + * This methods sets the bounds of the given component. The width is the + * size. The height is the container size minus the top and bottom + * inset. The x coordinate is the location given. The y coordinate is + * the top inset. + * + * @param c The component to set. + * @param size The width of the component. + * @param location The x coordinate. + * @param insets The insets to use. + * @param containerSize The height of the container. + */ + protected void setComponentToSize(Component c, int size, int location, + Insets insets, Dimension containerSize) + { + int w = size; + int h = containerSize.height - insets.top - insets.bottom; + int x = location; + int y = insets.top; + c.setBounds(x, y, w, h); + } + + /** + * This method stores the given int array as the new sizes array. + * + * @param newSizes The array to use as sizes. + */ + protected void setSizes(int[] newSizes) + { + sizes = newSizes; + } + + /** + * This method determines the size of each component. It should be called + * when a new Layout Manager is created for an existing JSplitPane. + */ + protected void updateComponents() + { + Component left = splitPane.getLeftComponent(); + Component right = splitPane.getRightComponent(); + + if (left != null) + { + components[0] = left; + resetSizeAt(0); + } + if (right != null) + { + components[1] = right; + resetSizeAt(1); + } + components[2] = divider; + resetSizeAt(2); + } + + /** + * This method resizes the left and right components to fit inside the + * JSplitPane when there is extra space. + */ + void distributeExtraSpace() + { + int availSize = getAvailableSize(splitPane.getSize(), + splitPane.getInsets()); + int[] newSizes = new int[3]; + double weight = splitPane.getResizeWeight(); + + int oldLen = sizes[0] + sizes[1]; + + // dividers don't change size. + availSize -= sizes[2] + oldLen; + + int rightAlloc = (int) (availSize * (1 - weight)); + int leftAlloc = availSize - rightAlloc; + + sizes[0] += leftAlloc; + sizes[1] += rightAlloc; + } + + /** + * This method returns the minimum width of the component at the given + * index. + * + * @param index The index to check. + * + * @return The minimum width. + */ + int minimumSizeOfComponent(int index) + { + Dimension dims = components[index].getMinimumSize(); + if (dims != null) + return dims.width; + else + return 0; + } + } //end BasicHorizontalLayoutManager + + /** + * This class is the Layout Manager for the JSplitPane when the orientation + * is VERTICAL_SPLIT. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class BasicVerticalLayoutManager + extends BasicHorizontalLayoutManager + { + /** + * This method returns the height of the container minus the top and + * bottom inset. + * + * @param containerSize The size of the container. + * @param insets The insets of the container. + * + * @return The height minus top and bottom inset. + */ + protected int getAvailableSize(Dimension containerSize, Insets insets) + { + return containerSize.height - insets.top - insets.bottom; + } + + /** + * This method returns the top inset. + * + * @param insets The Insets to use. + * + * @return The top inset. + */ + protected int getInitialLocation(Insets insets) + { + return insets.top; + } + + /** + * This method returns the preferred height of the component. + * + * @param c The component to measure. + * + * @return The preferred height of the component. + */ + protected int getPreferredSizeOfComponent(Component c) + { + Dimension dims = c.getPreferredSize(); + if (dims != null) + return dims.height; + return 0; + } + + /** + * This method returns the current height of the component. + * + * @param c The component to measure. + * + * @return The current height of the component. + */ + protected int getSizeOfComponent(Component c) + { + return c.getHeight(); + } + + /** + * This method returns the minimum layout size. The minimum height is the + * sum of all the components' minimum heights. The minimum width is the + * maximum of all the components' minimum widths. + * + * @param container The container to measure. + * + * @return The minimum size. + */ + public Dimension minimumLayoutSize(Container container) + { + if (container instanceof JSplitPane) + { + JSplitPane split = (JSplitPane) container; + Insets insets = container.getInsets(); + + int height = 0; + int width = 0; + for (int i = 0; i < components.length; i++) + { + if (components[i] == null) + continue; + Dimension dims = components[i].getMinimumSize(); + if (dims != null) + { + height += dims.height; + width = Math.max(width, dims.width); + } + } + return new Dimension(width, height); + } + return null; + } + + /** + * This method returns the preferred layout size. The preferred height is + * the sum of all the components' preferred heights. The preferred width + * is the maximum of all the components' preferred widths. + * + * @param container The container to measure. + * + * @return The preferred size. + */ + public Dimension preferredLayoutSize(Container container) + { + if (container instanceof JSplitPane) + { + JSplitPane split = (JSplitPane) container; + Insets insets = container.getInsets(); + + int height = 0; + int width = 0; + for (int i = 0; i < components.length; i++) + { + if (components[i] == null) + continue; + Dimension dims = components[i].getPreferredSize(); + if (dims != null) + { + height += dims.height; + width = Math.max(width, dims.width); + } + } + return new Dimension(width, height); + } + return null; + } + + /** + * This method sets the bounds of the given component. The y coordinate is + * the location given. The x coordinate is the left inset. The height is + * the size given. The width is the container size minus the left and + * right inset. + * + * @param c The component to set bounds for. + * @param size The height. + * @param location The y coordinate. + * @param insets The insets to use. + * @param containerSize The container's size. + */ + protected void setComponentToSize(Component c, int size, int location, + Insets insets, Dimension containerSize) + { + int y = location; + int x = insets.left; + int h = size; + int w = containerSize.width - insets.left - insets.right; + + c.setBounds(x, y, w, h); + } + + /** + * This method returns the minimum height of the component at the given + * index. + * + * @param index The index of the component to check. + * + * @return The minimum height of the given component. + */ + int minimumSizeOfComponent(int index) + { + Dimension dims = components[index].getMinimumSize(); + if (dims != null) + return dims.height; + else + return 0; + } + } + + /** + * This class handles FocusEvents from the JComponent. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class FocusHandler extends FocusAdapter + { + /** + * This method is called when the JSplitPane gains focus. + * + * @param ev The FocusEvent. + */ + public void focusGained(FocusEvent ev) + { + // FIXME: implement. + } + + /** + * This method is called when the JSplitPane loses focus. + * + * @param ev The FocusEvent. + */ + public void focusLost(FocusEvent ev) + { + // FIXME: implement. + } + } + + /** + * This is a deprecated class. It is supposed to be used for handling down + * and right key presses. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class KeyboardDownRightHandler implements ActionListener + { + /** + * This method is called when the down or right keys are pressed. + * + * @param ev The ActionEvent + */ + public void actionPerformed(ActionEvent ev) + { + // FIXME: implement. + } + } + + /** + * This is a deprecated class. It is supposed to be used for handling end + * key presses. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class KeyboardEndHandler implements ActionListener + { + /** + * This method is called when the end key is pressed. + * + * @param ev The ActionEvent. + */ + public void actionPerformed(ActionEvent ev) + { + // FIXME: implement. + } + } + + /** + * This is a deprecated class. It is supposed to be used for handling home + * key presses. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class KeyboardHomeHandler implements ActionListener + { + /** + * This method is called when the home key is pressed. + * + * @param ev The ActionEvent. + */ + public void actionPerformed(ActionEvent ev) + { + // FIXME: implement. + } + } + + /** + * This is a deprecated class. It is supposed to be used for handling resize + * toggles. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class KeyboardResizeToggleHandler implements ActionListener + { + /** + * This method is called when a resize is toggled. + * + * @param ev The ActionEvent. + */ + public void actionPerformed(ActionEvent ev) + { + // FIXME: implement. + } + } + + /** + * This is a deprecated class. It is supposed to be used for handler up and + * left key presses. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class KeyboardUpLeftHandler implements ActionListener + { + /** + * This method is called when the left or up keys are pressed. + * + * @param ev The ActionEvent. + */ + public void actionPerformed(ActionEvent ev) + { + // FIXME: implement. + } + } + + /** + * This helper class handles PropertyChangeEvents from the JSplitPane. When + * a property changes, this will update the UI accordingly. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class PropertyHandler implements PropertyChangeListener + { + /** + * This method is called whenever one of the JSplitPane's properties + * change. + * + * @param e DOCUMENT ME! + */ + public void propertyChange(PropertyChangeEvent e) + { + if (e.getPropertyName().equals(JSplitPane.DIVIDER_SIZE_PROPERTY)) + { + int newSize = splitPane.getDividerSize(); + int[] tmpSizes = layoutManager.getSizes(); + dividerSize = tmpSizes[2]; + Component left = splitPane.getLeftComponent(); + Component right = splitPane.getRightComponent(); + int newSpace = newSize - tmpSizes[2]; + + tmpSizes[2] = newSize; + + tmpSizes[0] += newSpace / 2; + tmpSizes[1] += newSpace / 2; + + layoutManager.setSizes(tmpSizes); + } + else if (e.getPropertyName().equals(JSplitPane.ORIENTATION_PROPERTY)) + { + int max = layoutManager.getAvailableSize(splitPane.getSize(), + splitPane.getInsets()); + int dividerLoc = getDividerLocation(splitPane); + double prop = ((double) dividerLoc) / max; + + resetLayoutManager(); + if (prop <= 1 && prop >= 0) + splitPane.setDividerLocation(prop); + } + layoutManager.layoutContainer(splitPane); + splitPane.repaint(); + // Don't have to deal with continuous_layout - only + // necessary in dragging modes (and it's checked + // every time you drag there) + // Don't have to deal with resize_weight (as there + // will be no extra space associated with this + // event - the changes to the weighting will + // be taken into account the next time the + // sizes change.) + // Don't have to deal with divider_location + // The method in JSplitPane calls our setDividerLocation + // so we'll know about those anyway. + // Don't have to deal with last_divider_location + // Although I'm not sure why, it doesn't seem to + // have any effect on Sun's JSplitPane. + // one_touch_expandable changes are dealt with + // by our divider. + } + } + + /** The location of the divider when dragging began. */ + protected int beginDragDividerLocation; + + /** The size of the divider while dragging. */ + protected int dividerSize; + + /** The location where the last drag location ended. */ + transient int lastDragLocation = -1; + + /** The distance the divider is moved when moved by keyboard actions. */ + protected static int KEYBOARD_DIVIDER_MOVE_OFFSET; + + /** The divider that divides this JSplitPane. */ + protected BasicSplitPaneDivider divider; + + /** The listener that listens for PropertyChangeEvents from the JSplitPane. */ + protected PropertyChangeListener propertyChangeListener; + + /** The JSplitPane's focus handler. */ + protected FocusListener focusListener; + + /** @deprecated The handler for down and right key presses. */ + protected ActionListener keyboardDownRightListener; + + /** @deprecated The handler for end key presses. */ + protected ActionListener keyboardEndListener; + + /** @deprecated The handler for home key presses. */ + protected ActionListener keyboardHomeListener; + + /** @deprecated The handler for toggling resizes. */ + protected ActionListener keyboardResizeToggleListener; + + /** @deprecated The handler for up and left key presses. */ + protected ActionListener keyboardUpLeftListener; + + /** The JSplitPane's current layout manager. */ + protected BasicHorizontalLayoutManager layoutManager; + + /** @deprecated The divider resize toggle key. */ + protected KeyStroke dividerResizeToggleKey; + + /** @deprecated The down key. */ + protected KeyStroke downKey; + + /** @deprecated The end key. */ + protected KeyStroke endKey; + + /** @deprecated The home key. */ + protected KeyStroke homeKey; + + /** @deprecated The left key. */ + protected KeyStroke leftKey; + + /** @deprecated The right key. */ + protected KeyStroke rightKey; + + /** @deprecated The up key. */ + protected KeyStroke upKey; + + /** Set to true when dragging heavy weight components. */ + protected boolean draggingHW; + + /** + * The constraints object used when adding the non-continuous divider to the + * JSplitPane. + */ + protected static final String NON_CONTINUOUS_DIVIDER + = "nonContinuousDivider"; + + /** The dark divider used when dragging in non-continuous layout mode. */ + protected Component nonContinuousLayoutDivider; + + /** The JSplitPane that this UI draws. */ + protected JSplitPane splitPane; + + /** + * Creates a new BasicSplitPaneUI object. + */ + public BasicSplitPaneUI() + { + } + + /** + * This method creates a new BasicSplitPaneUI for the given JComponent. + * + * @param x The JComponent to create a UI for. + * + * @return A new BasicSplitPaneUI. + */ + public static ComponentUI createUI(JComponent x) + { + return new BasicSplitPaneUI(); + } + + /** + * This method installs the BasicSplitPaneUI for the given JComponent. + * + * @param c The JComponent to install the UI for. + */ + public void installUI(JComponent c) + { + if (c instanceof JSplitPane) + { + splitPane = (JSplitPane) c; + installDefaults(); + installListeners(); + installKeyboardActions(); + } + } + + /** + * This method uninstalls the BasicSplitPaneUI for the given JComponent. + * + * @param c The JComponent to uninstall the UI for. + */ + public void uninstallUI(JComponent c) + { + uninstallKeyboardActions(); + uninstallListeners(); + uninstallDefaults(); + + splitPane = null; + } + + /** + * This method installs the defaults given by the Look and Feel. + */ + protected void installDefaults() + { + divider = createDefaultDivider(); + resetLayoutManager(); + nonContinuousLayoutDivider = createDefaultNonContinuousLayoutDivider(); + splitPane.add(divider, JSplitPane.DIVIDER); + + // There is no need to add the nonContinuousLayoutDivider + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + splitPane.setBackground(defaults.getColor("SplitPane.background")); + splitPane.setBorder(defaults.getBorder("SplitPane.border")); + splitPane.setDividerSize(defaults.getInt("SplitPane.dividerSize")); + splitPane.setOpaque(true); + } + + /** + * This method uninstalls the defaults and nulls any objects created during + * install. + */ + protected void uninstallDefaults() + { + layoutManager = null; + splitPane.remove(divider); + divider = null; + nonContinuousLayoutDivider = null; + + splitPane.setBackground(null); + splitPane.setBorder(null); + } + + /** + * This method installs the listeners needed for this UI to function. + */ + protected void installListeners() + { + propertyChangeListener = createPropertyChangeListener(); + focusListener = createFocusListener(); + + splitPane.addPropertyChangeListener(propertyChangeListener); + splitPane.addFocusListener(focusListener); + } + + /** + * This method uninstalls all listeners registered for the UI. + */ + protected void uninstallListeners() + { + splitPane.removePropertyChangeListener(propertyChangeListener); + splitPane.removeFocusListener(focusListener); + + focusListener = null; + propertyChangeListener = null; + } + + /** + * This method installs the keyboard actions for the JSplitPane. + */ + protected void installKeyboardActions() + { + // FIXME: implement. + } + + /** + * This method reverses the work done in installKeyboardActions. + */ + protected void uninstallKeyboardActions() + { + // FIXME: implement. + } + + /** + * This method creates a new PropertyChangeListener. + * + * @return A new PropertyChangeListener. + */ + protected PropertyChangeListener createPropertyChangeListener() + { + return new PropertyHandler(); + } + + /** + * This method creates a new FocusListener. + * + * @return A new FocusListener. + */ + protected FocusListener createFocusListener() + { + return new FocusHandler(); + } + + /** + * This method creates a new ActionListener for up and left key presses. + * + * @return A new ActionListener for up and left keys. + * + * @deprecated 1.3 + */ + protected ActionListener createKeyboardUpLeftListener() + { + return new KeyboardUpLeftHandler(); + } + + /** + * This method creates a new ActionListener for down and right key presses. + * + * @return A new ActionListener for down and right keys. + * + * @deprecated 1.3 + */ + protected ActionListener createKeyboardDownRightListener() + { + return new KeyboardDownRightHandler(); + } + + /** + * This method creates a new ActionListener for home key presses. + * + * @return A new ActionListener for home keys. + * + * @deprecated + */ + protected ActionListener createKeyboardHomeListener() + { + return new KeyboardHomeHandler(); + } + + /** + * This method creates a new ActionListener for end key presses.i + * + * @return A new ActionListener for end keys. + * + * @deprecated 1.3 + */ + protected ActionListener createKeyboardEndListener() + { + return new KeyboardEndHandler(); + } + + /** + * This method creates a new ActionListener for resize toggle key events. + * + * @return A new ActionListener for resize toggle keys. + * + * @deprecated 1.3 + */ + protected ActionListener createKeyboardResizeToggleListener() + { + return new KeyboardResizeToggleHandler(); + } + + /** + * This method returns the orientation of the JSplitPane. + * + * @return The orientation of the JSplitPane. + */ + public int getOrientation() + { + return splitPane.getOrientation(); + } + + /** + * This method sets the orientation of the JSplitPane. + * + * @param orientation The new orientation of the JSplitPane. + */ + public void setOrientation(int orientation) + { + splitPane.setOrientation(orientation); + } + + /** + * This method returns true if the JSplitPane is using continuous layout. + * + * @return True if the JSplitPane is using continuous layout. + */ + public boolean isContinuousLayout() + { + return splitPane.isContinuousLayout(); + } + + /** + * This method sets the continuous layout property of the JSplitPane. + * + * @param b True if the JsplitPane is to use continuous layout. + */ + public void setContinuousLayout(boolean b) + { + splitPane.setContinuousLayout(b); + } + + /** + * This method returns the last location the divider was dragged to. + * + * @return The last location the divider was dragged to. + */ + public int getLastDragLocation() + { + return lastDragLocation; + } + + /** + * This method sets the last location the divider was dragged to. + * + * @param l The last location the divider was dragged to. + */ + public void setLastDragLocation(int l) + { + lastDragLocation = l; + } + + /** + * This method returns the BasicSplitPaneDivider that divides this + * JSplitPane. + * + * @return The divider for the JSplitPane. + */ + public BasicSplitPaneDivider getDivider() + { + return divider; + } + + /** + * This method creates a nonContinuousLayoutDivider for use with the + * JSplitPane in nonContinousLayout mode. The default divider is a gray + * Canvas. + * + * @return The default nonContinousLayoutDivider. + */ + protected Component createDefaultNonContinuousLayoutDivider() + { + if (nonContinuousLayoutDivider == null) + { + nonContinuousLayoutDivider = new Canvas(); + nonContinuousLayoutDivider.setBackground(Color.DARK_GRAY); + } + return nonContinuousLayoutDivider; + } + + /** + * This method sets the component to use as the nonContinuousLayoutDivider. + * + * @param newDivider The component to use as the nonContinuousLayoutDivider. + */ + protected void setNonContinuousLayoutDivider(Component newDivider) + { + setNonContinuousLayoutDivider(newDivider, true); + } + + /** + * This method sets the component to use as the nonContinuousLayoutDivider. + * + * @param newDivider The component to use as the nonContinuousLayoutDivider. + * @param rememberSizes FIXME: document. + */ + protected void setNonContinuousLayoutDivider(Component newDivider, + boolean rememberSizes) + { + // FIXME: use rememberSizes for something + nonContinuousLayoutDivider = newDivider; + } + + /** + * This method returns the nonContinuousLayoutDivider. + * + * @return The nonContinuousLayoutDivider. + */ + public Component getNonContinuousLayoutDivider() + { + return nonContinuousLayoutDivider; + } + + /** + * This method returns the JSplitPane that this BasicSplitPaneUI draws. + * + * @return The JSplitPane. + */ + public JSplitPane getSplitPane() + { + return splitPane; + } + + /** + * This method creates the divider used normally with the JSplitPane. + * + * @return The default divider. + */ + public BasicSplitPaneDivider createDefaultDivider() + { + if (divider == null) + divider = new BasicSplitPaneDivider(this); + return divider; + } + + /** + * This method is called when JSplitPane's resetToPreferredSizes is called. + * It resets the sizes of all components in the JSplitPane. + * + * @param jc The JSplitPane to reset. + */ + public void resetToPreferredSizes(JSplitPane jc) + { + layoutManager.resetToPreferredSizes(); + } + + /** + * This method sets the location of the divider. + * + * @param jc The JSplitPane to set the divider location in. + * @param location The new location of the divider. + */ + public void setDividerLocation(JSplitPane jc, int location) + { + setLastDragLocation(getDividerLocation(splitPane)); + splitPane.setLastDividerLocation(getDividerLocation(splitPane)); + int[] tmpSizes = layoutManager.getSizes(); + tmpSizes[0] = location + - layoutManager.getInitialLocation(splitPane.getInsets()); + tmpSizes[1] = layoutManager.getAvailableSize(splitPane.getSize(), + splitPane.getInsets()) + - tmpSizes[0] - tmpSizes[1]; + + layoutManager.setSizes(tmpSizes); + splitPane.revalidate(); + splitPane.repaint(); + } + + /** + * This method returns the location of the divider. + * + * @param jc The JSplitPane to retrieve the location for. + * + * @return The location of the divider. + */ + public int getDividerLocation(JSplitPane jc) + { + return layoutManager.sizes[0] + + layoutManager.getInitialLocation(splitPane.getInsets()); + } + + /** + * This method returns the smallest value possible for the location of the + * divider. + * + * @param jc The JSplitPane. + * + * @return The minimum divider location. + */ + public int getMinimumDividerLocation(JSplitPane jc) + { + int value = layoutManager.getInitialLocation(jc.getInsets()); + if (layoutManager.components[0] != null) + value += layoutManager.minimumSizeOfComponent(0); + return value; + } + + /** + * This method returns the largest value possible for the location of the + * divider. + * + * @param jc The JSplitPane. + * + * @return The maximum divider location. + */ + public int getMaximumDividerLocation(JSplitPane jc) + { + int value = layoutManager.getInitialLocation(jc.getInsets()) + + layoutManager.getAvailableSize(jc.getSize(), jc.getInsets()) + - splitPane.getDividerSize(); + if (layoutManager.components[1] != null) + value -= layoutManager.minimumSizeOfComponent(1); + return value; + } + + /** + * This method is called after the children of the JSplitPane are painted. + * + * @param jc The JSplitPane. + * @param g The Graphics object to paint with. + */ + public void finishedPaintingChildren(JSplitPane jc, Graphics g) + { + if (! splitPane.isContinuousLayout() && nonContinuousLayoutDivider != null + && nonContinuousLayoutDivider.isVisible()) + javax.swing.SwingUtilities.paintComponent(g, nonContinuousLayoutDivider, + null, + nonContinuousLayoutDivider + .getBounds()); + } + + /** + * This method is called to paint the JSplitPane. + * + * @param g The Graphics object to paint with. + * @param jc The JSplitPane to paint. + */ + public void paint(Graphics g, JComponent jc) + { + } + + /** + * This method returns the preferred size of the JSplitPane. + * + * @param jc The JSplitPane. + * + * @return The preferred size of the JSplitPane. + */ + public Dimension getPreferredSize(JComponent jc) + { + return layoutManager.preferredLayoutSize((Container) jc); + } + + /** + * This method returns the minimum size of the JSplitPane. + * + * @param jc The JSplitPane. + * + * @return The minimum size of the JSplitPane. + */ + public Dimension getMinimumSize(JComponent jc) + { + return layoutManager.minimumLayoutSize((Container) jc); + } + + /** + * This method returns the maximum size of the JSplitPane. + * + * @param jc The JSplitPane. + * + * @return The maximum size of the JSplitPane. + */ + public Dimension getMaximumSize(JComponent jc) + { + return layoutManager.maximumLayoutSize((Container) jc); + } + + /** + * This method returns the border insets of the current border. + * + * @param jc The JSplitPane. + * + * @return The current border insets. + */ + public Insets getInsets(JComponent jc) + { + return splitPane.getBorder().getBorderInsets(splitPane); + } + + /** + * This method resets the current layout manager. The type of layout manager + * is dependent on the current orientation. + */ + protected void resetLayoutManager() + { + if (getOrientation() == JSplitPane.HORIZONTAL_SPLIT) + layoutManager = new BasicHorizontalLayoutManager(); + else + layoutManager = new BasicVerticalLayoutManager(); + getSplitPane().setLayout(layoutManager); + layoutManager.updateComponents(); + + // invalidating by itself does not invalidate the layout. + getSplitPane().revalidate(); + } + + /** + * This method is called when dragging starts. It resets lastDragLocation + * and dividerSize. + */ + protected void startDragging() + { + dividerSize = divider.getDividerSize(); + setLastDragLocation(-1); + + if (! splitPane.getLeftComponent().isLightweight() + || ! splitPane.getRightComponent().isLightweight()) + draggingHW = true; + + if (splitPane.isContinuousLayout()) + nonContinuousLayoutDivider.setVisible(false); + else + { + nonContinuousLayoutDivider.setVisible(true); + nonContinuousLayoutDivider.setBounds(divider.getBounds()); + } + splitPane.revalidate(); + splitPane.repaint(); + } + + /** + * This method is called whenever the divider is dragged. If the JSplitPane + * is in continuousLayout mode, the divider needs to be moved and the + * JSplitPane needs to be laid out. + * + * @param location The new location of the divider. + */ + protected void dragDividerTo(int location) + { + location = validLocation(location); + if (beginDragDividerLocation == -1) + beginDragDividerLocation = location; + + if (splitPane.isContinuousLayout()) + splitPane.setDividerLocation(location); + else + { + Point p = nonContinuousLayoutDivider.getLocation(); + if (getOrientation() == JSplitPane.HORIZONTAL_SPLIT) + p.x = location; + else + p.y = location; + nonContinuousLayoutDivider.setLocation(p); + } + setLastDragLocation(location); + splitPane.repaint(); + } + + /** + * This method is called when the dragging is finished. + * + * @param location The location where the drag finished. + */ + protected void finishDraggingTo(int location) + { + if (nonContinuousLayoutDivider != null) + nonContinuousLayoutDivider.setVisible(false); + draggingHW = false; + location = validLocation(location); + dragDividerTo(location); + splitPane.setDividerLocation(location); + splitPane.setLastDividerLocation(beginDragDividerLocation); + beginDragDividerLocation = -1; + splitPane.repaint(); + } + + /** + * This method returns the width of one of the sides of the divider's border. + * + * @return The width of one side of the divider's border. + * + * @deprecated 1.3 + */ + protected int getDividerBorderSize() + { + if (getOrientation() == JSplitPane.HORIZONTAL_SPLIT) + return divider.getBorder().getBorderInsets(divider).left; + else + return divider.getBorder().getBorderInsets(divider).top; + } + + /** + * This is a helper method that returns a valid location for the divider + * when dragging. + * + * @param location The location to check. + * + * @return A valid location. + */ + private int validLocation(int location) + { + if (location < getMinimumDividerLocation(splitPane)) + return getMinimumDividerLocation(splitPane); + if (location > getMaximumDividerLocation(splitPane)) + return getMaximumDividerLocation(splitPane); + return location; + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTabbedPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTabbedPaneUI.java new file mode 100644 index 0000000..8a27f98 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTabbedPaneUI.java @@ -0,0 +1,3084 @@ +/* BasicTabbedPaneUI.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.LayoutManager; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; +import javax.swing.JViewport; +import javax.swing.KeyStroke; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.PanelUI; +import javax.swing.plaf.TabbedPaneUI; +import javax.swing.plaf.UIResource; +import javax.swing.text.View; + +/** + * This is the Basic Look and Feel's UI delegate for JTabbedPane. + */ +public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants +{ + /** + * A helper class that handles focus. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class FocusHandler extends FocusAdapter + { + /** + * This method is called when the component gains focus. + * + * @param e The FocusEvent. + */ + public void focusGained(FocusEvent e) + { + // FIXME: Implement. + } + + /** + * This method is called when the component loses focus. + * + * @param e The FocusEvent. + */ + public void focusLost(FocusEvent e) + { + // FIXME: Implement. + } + } + + /** + * A helper class for determining if mouse presses occur inside tabs and + * sets the index appropriately. In SCROLL_TAB_MODE, this class also + * handles the mouse clicks on the scrolling buttons. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class MouseHandler extends MouseAdapter + { + /** + * This method is called when the mouse is pressed. The index cannot + * change to a tab that is not enabled. + * + * @param e The MouseEvent. + */ + public void mousePressed(MouseEvent e) + { + int x = e.getX(); + int y = e.getY(); + int tabCount = tabPane.getTabCount(); + + if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) + { + if (e.getSource() == incrButton) + { + if (++currentScrollLocation >= tabCount) + currentScrollLocation = tabCount - 1; + + int width = 0; + for (int i = currentScrollLocation - 1; i < tabCount; i++) + width += rects[i].width; + if (width < viewport.getWidth()) + // FIXME: Still getting mouse events after the button is disabled. + // incrButton.setEnabled(false); + currentScrollLocation--; + else if (! decrButton.isEnabled()) + decrButton.setEnabled(true); + tabPane.revalidate(); + tabPane.repaint(); + return; + } + else if (e.getSource() == decrButton) + { + if (--currentScrollLocation < 0) + currentScrollLocation = 0; + if (currentScrollLocation == 0) + decrButton.setEnabled(false); + else if (! incrButton.isEnabled()) + incrButton.setEnabled(true); + tabPane.revalidate(); + tabPane.repaint(); + return; + } + } + + int index = tabForCoordinate(tabPane, x, y); + + // We need to check since there are areas where tabs cannot be + // e.g. in the inset area. + if (index != -1 && tabPane.isEnabledAt(index)) + tabPane.setSelectedIndex(index); + tabPane.revalidate(); + tabPane.repaint(); + } + } + + /** + * This class handles PropertyChangeEvents fired from the JTabbedPane. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class PropertyChangeHandler implements PropertyChangeListener + { + /** + * This method is called whenever one of the properties of the JTabbedPane + * changes. + * + * @param e The PropertyChangeEvent. + */ + public void propertyChange(PropertyChangeEvent e) + { + if (e.getPropertyName().equals("tabLayoutPolicy")) + { + layoutManager = createLayoutManager(); + + tabPane.setLayout(layoutManager); + } + else if (e.getPropertyName().equals("tabPlacement") + && tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) + { + incrButton = createIncreaseButton(); + decrButton = createDecreaseButton(); + } + tabPane.layout(); + tabPane.repaint(); + } + } + + /** + * A LayoutManager responsible for placing all the tabs and the visible + * component inside the JTabbedPane. This class is only used for + * WRAP_TAB_LAYOUT. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class TabbedPaneLayout implements LayoutManager + { + /** + * This method is called when a component is added to the JTabbedPane. + * + * @param name The name of the component. + * @param comp The component being added. + */ + public void addLayoutComponent(String name, Component comp) + { + // Do nothing. + } + + /** + * This method is called when the rectangles need to be calculated. It + * also fixes the size of the visible component. + */ + public void calculateLayoutInfo() + { + calculateTabRects(tabPane.getTabPlacement(), tabPane.getTabCount()); + + if (tabPane.getSelectedIndex() != -1) + { + Component visible = getVisibleComponent(); + Insets insets = getContentBorderInsets(tabPane.getTabPlacement()); + if (visible != null) + visible.setBounds(contentRect.x + insets.left, + contentRect.y + insets.top, + contentRect.width - insets.left - insets.right, + contentRect.height - insets.top - insets.bottom); + } + } + + /** + * This method calculates the size of the the JTabbedPane. + * + * @param minimum Whether the JTabbedPane will try to be as small as it + * can. + * + * @return The desired size of the JTabbedPane. + */ + protected Dimension calculateSize(boolean minimum) + { + int tabPlacement = tabPane.getTabPlacement(); + int width = 0; + int height = 0; + + int componentHeight = 0; + int componentWidth = 0; + Component c; + Dimension dims; + for (int i = 0; i < tabPane.getTabCount(); i++) + { + c = tabPane.getComponentAt(i); + if (c == null) + continue; + calcRect = c.getBounds(); + dims = c.getPreferredSize(); + if (dims != null) + { + componentHeight = Math.max(componentHeight, dims.height); + componentWidth = Math.max(componentWidth, dims.width); + } + } + Insets insets = tabPane.getInsets(); + + if (tabPlacement == SwingConstants.TOP + || tabPlacement == SwingConstants.BOTTOM) + { + int min = calculateMaxTabWidth(tabPlacement); + width = Math.max(min, componentWidth); + + int tabAreaHeight = preferredTabAreaHeight(tabPlacement, width); + height = tabAreaHeight + componentHeight; + } + else + { + int min = calculateMaxTabHeight(tabPlacement); + height = Math.max(min, componentHeight); + + int tabAreaWidth = preferredTabAreaWidth(tabPlacement, height); + width = tabAreaWidth + componentWidth; + } + + return new Dimension(width, height); + } + + // if tab placement is LEFT OR RIGHT, they share width. + // if tab placement is TOP OR BOTTOM, they share height + // PRE STEP: finds the default sizes for the labels as well as their locations. + // AND where they will be placed within the run system. + // 1. calls normalizeTab Runs. + // 2. calls rotate tab runs. + // 3. pads the tab runs. + // 4. pads the selected tab. + + /** + * This method is called to calculate the tab rectangles. This method + * will calculate the size and position of all rectangles (taking into + * account which ones should be in which tab run). It will pad them and + * normalize them as necessary. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param tabCount The run the current selection is in. + */ + protected void calculateTabRects(int tabPlacement, int tabCount) + { + if (tabCount == 0) + return; + assureRectsCreated(tabCount); + + FontMetrics fm = getFontMetrics(); + SwingUtilities.calculateInnerArea(tabPane, calcRect); + Insets tabAreaInsets = getTabAreaInsets(tabPlacement); + Insets insets = tabPane.getInsets(); + int max = 0; + int runs = 0; + int start = getTabRunIndent(tabPlacement, 1); + if (tabPlacement == SwingConstants.TOP + || tabPlacement == SwingConstants.BOTTOM) + { + int maxHeight = calculateMaxTabHeight(tabPlacement); + + calcRect.width -= tabAreaInsets.left + tabAreaInsets.right; + max = calcRect.width + tabAreaInsets.left + insets.left; + start += tabAreaInsets.left + insets.left; + int width = 0; + int runWidth = start; + + for (int i = 0; i < tabCount; i++) + { + width = calculateTabWidth(tabPlacement, i, fm); + + if (runWidth + width > max) + { + runWidth = tabAreaInsets.left + insets.left + + getTabRunIndent(tabPlacement, ++runs); + rects[i] = new Rectangle(runWidth, + insets.top + tabAreaInsets.top, + width, maxHeight); + runWidth += width; + if (runs > tabRuns.length - 1) + expandTabRunsArray(); + tabRuns[runs] = i; + } + else + { + rects[i] = new Rectangle(runWidth, + insets.top + tabAreaInsets.top, + width, maxHeight); + runWidth += width; + } + } + runs++; + tabAreaRect.width = tabPane.getWidth() - insets.left - insets.right; + tabAreaRect.height = runs * maxTabHeight + - (runs - 1) * tabRunOverlay + + tabAreaInsets.top + tabAreaInsets.bottom; + contentRect.width = tabAreaRect.width; + contentRect.height = tabPane.getHeight() - insets.top + - insets.bottom - tabAreaRect.height; + contentRect.x = insets.left; + tabAreaRect.x = insets.left; + if (tabPlacement == SwingConstants.BOTTOM) + { + contentRect.y = insets.top; + tabAreaRect.y = contentRect.y + contentRect.height; + } + else + { + tabAreaRect.y = insets.top; + contentRect.y = tabAreaRect.y + tabAreaRect.height; + } + } + else + { + int maxWidth = calculateMaxTabWidth(tabPlacement); + calcRect.height -= tabAreaInsets.top + tabAreaInsets.bottom; + max = calcRect.height + tabAreaInsets.top + insets.top; + + int height = 0; + start += tabAreaInsets.top + insets.top; + int runHeight = start; + + int fontHeight = fm.getHeight(); + + for (int i = 0; i < tabCount; i++) + { + height = calculateTabHeight(tabPlacement, i, fontHeight); + if (runHeight + height > max) + { + runHeight = tabAreaInsets.top + insets.top + + getTabRunIndent(tabPlacement, ++runs); + rects[i] = new Rectangle(insets.left + tabAreaInsets.left, + runHeight, maxWidth, height); + runHeight += height; + if (runs > tabRuns.length - 1) + expandTabRunsArray(); + tabRuns[runs] = i; + } + else + { + rects[i] = new Rectangle(insets.left + tabAreaInsets.left, + runHeight, maxWidth, height); + runHeight += height; + } + } + runs++; + + tabAreaRect.width = runs * maxTabWidth - (runs - 1) * tabRunOverlay + + tabAreaInsets.left + tabAreaInsets.right; + tabAreaRect.height = tabPane.getHeight() - insets.top + - insets.bottom; + tabAreaRect.y = insets.top; + contentRect.width = tabPane.getWidth() - insets.left - insets.right + - tabAreaRect.width; + contentRect.height = tabAreaRect.height; + contentRect.y = insets.top; + if (tabPlacement == SwingConstants.LEFT) + { + tabAreaRect.x = insets.left; + contentRect.x = tabAreaRect.x + tabAreaRect.width; + } + else + { + contentRect.x = insets.left; + tabAreaRect.x = contentRect.x + contentRect.width; + } + } + runCount = runs; + + tabRuns[0] = 0; + normalizeTabRuns(tabPlacement, tabCount, start, max); + selectedRun = getRunForTab(tabCount, tabPane.getSelectedIndex()); + if (shouldRotateTabRuns(tabPlacement)) + rotateTabRuns(tabPlacement, selectedRun); + + // Need to pad the runs and move them to the correct location. + for (int i = 0; i < runCount; i++) + { + int first = lastTabInRun(tabCount, getPreviousTabRun(i)) + 1; + if (first == tabCount) + first = 0; + int last = lastTabInRun(tabCount, i); + if (shouldPadTabRun(tabPlacement, i)) + padTabRun(tabPlacement, first, last, max); + + // Done padding, now need to move it. + if (tabPlacement == SwingConstants.TOP && i > 0) + { + for (int j = first; j <= last; j++) + rects[j].y += (runCount - i) * maxTabHeight + - (runCount - i) * tabRunOverlay; + } + + if (tabPlacement == SwingConstants.BOTTOM) + { + int height = tabPane.getBounds().height - insets.bottom + - tabAreaInsets.bottom; + int adjustment; + if (i == 0) + adjustment = height - maxTabHeight; + else + adjustment = height - (runCount - i + 1) * maxTabHeight + - (runCount - i) * tabRunOverlay; + + for (int j = first; j <= last; j++) + rects[j].y = adjustment; + } + + if (tabPlacement == SwingConstants.LEFT && i > 0) + { + for (int j = first; j <= last; j++) + rects[j].x += (runCount - i) * maxTabWidth + - (runCount - i) * tabRunOverlay; + } + + if (tabPlacement == SwingConstants.RIGHT) + { + int width = tabPane.getBounds().width - insets.right + - tabAreaInsets.right; + int adjustment; + if (i == 0) + adjustment = width - maxTabWidth; + else + adjustment = width - (runCount - i + 1) * maxTabWidth + + (runCount - i) * tabRunOverlay; + + for (int j = first; j <= last; j++) + rects[j].x = adjustment; + } + } + padSelectedTab(tabPlacement, tabPane.getSelectedIndex()); + } + + /** + * This method is called when the JTabbedPane is laid out in + * WRAP_TAB_LAYOUT. It calls calculateLayoutInfo to find the positions + * of all its components. + * + * @param parent The Container to lay out. + */ + public void layoutContainer(Container parent) + { + calculateLayoutInfo(); + } + + /** + * This method returns the minimum layout size for the given container. + * + * @param parent The container that is being sized. + * + * @return The minimum size. + */ + public Dimension minimumLayoutSize(Container parent) + { + return calculateSize(false); + } + + // If there is more free space in an adjacent run AND the tab in the run can fit in the + // adjacent run, move it. This method is not perfect, it is merely an approximation. + // If you play around with Sun's JTabbedPane, you'll see that + // it does do some pretty strange things with regards to not moving tabs + // that should be moved. + // start = the x position where the tabs will begin + // max = the maximum position of where the tabs can go to (tabAreaInsets.left + the width of the tab area) + + /** + * This method tries to "even out" the number of tabs in each run based on + * their widths. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param tabCount The number of tabs. + * @param start The x position where the tabs will begin. + * @param max The maximum x position where the tab can run to. + */ + protected void normalizeTabRuns(int tabPlacement, int tabCount, int start, + int max) + { + Insets tabAreaInsets = getTabAreaInsets(tabPlacement); + if (tabPlacement == SwingUtilities.TOP + || tabPlacement == SwingUtilities.BOTTOM) + { + // We should only do this for runCount - 1, cause we can only shift that many times between + // runs. + for (int i = 1; i < runCount; i++) + { + Rectangle currRun = rects[lastTabInRun(tabCount, i)]; + Rectangle nextRun = rects[lastTabInRun(tabCount, getNextTabRun(i))]; + int spaceInCurr = currRun.x + currRun.width; + int spaceInNext = nextRun.x + nextRun.width; + + int diffNow = spaceInCurr - spaceInNext; + int diffLater = (spaceInCurr - currRun.width) + - (spaceInNext + currRun.width); + while (Math.abs(diffLater) < Math.abs(diffNow) + && spaceInNext + currRun.width < max) + { + tabRuns[i]--; + spaceInNext += currRun.width; + spaceInCurr -= currRun.width; + currRun = rects[lastTabInRun(tabCount, i)]; + diffNow = spaceInCurr - spaceInNext; + diffLater = (spaceInCurr - currRun.width) + - (spaceInNext + currRun.width); + } + + // Fix the bounds. + int first = lastTabInRun(tabCount, i) + 1; + int last = lastTabInRun(tabCount, getNextTabRun(i)); + int currX = tabAreaInsets.left; + for (int j = first; j <= last; j++) + { + rects[j].x = currX; + currX += rects[j].width; + } + } + } + else + { + for (int i = 1; i < runCount; i++) + { + Rectangle currRun = rects[lastTabInRun(tabCount, i)]; + Rectangle nextRun = rects[lastTabInRun(tabCount, getNextTabRun(i))]; + int spaceInCurr = currRun.y + currRun.height; + int spaceInNext = nextRun.y + nextRun.height; + + int diffNow = spaceInCurr - spaceInNext; + int diffLater = (spaceInCurr - currRun.height) + - (spaceInNext + currRun.height); + while (Math.abs(diffLater) < Math.abs(diffNow) + && spaceInNext + currRun.height < max) + { + tabRuns[i]--; + spaceInNext += currRun.height; + spaceInCurr -= currRun.height; + currRun = rects[lastTabInRun(tabCount, i)]; + diffNow = spaceInCurr - spaceInNext; + diffLater = (spaceInCurr - currRun.height) + - (spaceInNext + currRun.height); + } + + int first = lastTabInRun(tabCount, i) + 1; + int last = lastTabInRun(tabCount, getNextTabRun(i)); + int currY = tabAreaInsets.top; + for (int j = first; j <= last; j++) + { + rects[j].y = currY; + currY += rects[j].height; + } + } + } + } + + /** + * This method pads the tab at the selected index by the selected tab pad + * insets (so that it looks larger). + * + * @param tabPlacement The placement of the tabs. + * @param selectedIndex The selected index. + */ + protected void padSelectedTab(int tabPlacement, int selectedIndex) + { + Insets insets = getSelectedTabPadInsets(tabPlacement); + rects[selectedIndex].x -= insets.left; + rects[selectedIndex].y -= insets.top; + rects[selectedIndex].width += insets.left + insets.right; + rects[selectedIndex].height += insets.top + insets.bottom; + } + + // If the tabs on the run don't fill the width of the window, make it fit now. + // start = starting index of the run + // end = last index of the run + // max = tabAreaInsets.left + width (or equivalent) + // assert start <= end. + + /** + * This method makes each tab in the run larger so that the tabs expand + * to fill the runs width/height (depending on tabPlacement). + * + * @param tabPlacement The placement of the tabs. + * @param start The index of the first tab. + * @param end The last index of the tab + * @param max The amount of space in the run (width for TOP and BOTTOM + * tabPlacement). + */ + protected void padTabRun(int tabPlacement, int start, int end, int max) + { + if (tabPlacement == SwingConstants.TOP + || tabPlacement == SwingConstants.BOTTOM) + { + int runWidth = rects[end].x + rects[end].width; + int spaceRemaining = max - runWidth; + int numTabs = end - start + 1; + + // now divvy up the space. + int spaceAllocated = spaceRemaining / numTabs; + int currX = rects[start].x; + for (int i = start; i <= end; i++) + { + rects[i].x = currX; + rects[i].width += spaceAllocated; + currX += rects[i].width; + // This is used because since the spaceAllocated + // variable is an int, it rounds down. Sometimes, + // we don't fill an entire row, so we make it do + // so now. + if (i == end && rects[i].x + rects[i].width != max) + rects[i].width = max - rects[i].x; + } + } + else + { + int runHeight = rects[end].y + rects[end].height; + int spaceRemaining = max - runHeight; + int numTabs = end - start + 1; + + int spaceAllocated = spaceRemaining / numTabs; + int currY = rects[start].y; + for (int i = start; i <= end; i++) + { + rects[i].y = currY; + rects[i].height += spaceAllocated; + currY += rects[i].height; + if (i == end && rects[i].y + rects[i].height != max) + rects[i].height = max - rects[i].y; + } + } + } + + /** + * This method returns the preferred layout size for the given container. + * + * @param parent The container to size. + * + * @return The preferred layout size. + */ + public Dimension preferredLayoutSize(Container parent) + { + return calculateSize(false); + } + + /** + * This method returns the preferred tab height given a tabPlacement and + * width. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param width The expected width. + * + * @return The preferred tab area height. + */ + protected int preferredTabAreaHeight(int tabPlacement, int width) + { + if (tabPane.getTabCount() == 0) + return calculateTabAreaHeight(tabPlacement, 0, 0); + + int runs = 0; + int runWidth = 0; + int tabWidth = 0; + + FontMetrics fm = getFontMetrics(); + + Insets tabAreaInsets = getTabAreaInsets(tabPlacement); + Insets insets = tabPane.getInsets(); + + // Only interested in width, this is a messed up rectangle now. + width -= tabAreaInsets.left + tabAreaInsets.right + insets.left + + insets.right; + + // The reason why we can't use runCount: + // This method is only called to calculate the size request + // for the tabbedPane. However, this size request is dependent on + // our desired width. We need to find out what the height would + // be IF we got our desired width. + for (int i = 0; i < tabPane.getTabCount(); i++) + { + tabWidth = calculateTabWidth(tabPlacement, i, fm); + if (runWidth + tabWidth > width) + { + runWidth = tabWidth; + runs++; + } + else + runWidth += tabWidth; + } + runs++; + + int maxTabHeight = calculateMaxTabHeight(tabPlacement); + int tabAreaHeight = calculateTabAreaHeight(tabPlacement, runs, + maxTabHeight); + return tabAreaHeight; + } + + /** + * This method calculates the preferred tab area width given a tab + * placement and height. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param height The expected height. + * + * @return The preferred tab area width. + */ + protected int preferredTabAreaWidth(int tabPlacement, int height) + { + if (tabPane.getTabCount() == 0) + return calculateTabAreaHeight(tabPlacement, 0, 0); + + int runs = 0; + int runHeight = 0; + int tabHeight = 0; + + FontMetrics fm = getFontMetrics(); + + Insets tabAreaInsets = getTabAreaInsets(tabPlacement); + Insets insets = tabPane.getInsets(); + + height -= tabAreaInsets.top + tabAreaInsets.bottom + insets.top + + insets.bottom; + int fontHeight = fm.getHeight(); + + for (int i = 0; i < tabPane.getTabCount(); i++) + { + tabHeight = calculateTabHeight(tabPlacement, i, fontHeight); + if (runHeight + tabHeight > height) + { + runHeight = tabHeight; + runs++; + } + else + runHeight += tabHeight; + } + runs++; + + int maxTabWidth = calculateMaxTabWidth(tabPlacement); + int tabAreaWidth = calculateTabAreaWidth(tabPlacement, runs, maxTabWidth); + return tabAreaWidth; + } + + /** + * This method rotates the places each run in the correct place the + * tabRuns array. See the comment for tabRuns for how the runs are placed + * in the array. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param selectedRun The run the current selection is in. + */ + protected void rotateTabRuns(int tabPlacement, int selectedRun) + { + if (runCount == 1 || selectedRun == 1 || selectedRun == -1) + return; + int[] newTabRuns = new int[tabRuns.length]; + int currentRun = selectedRun; + int i = 1; + do + { + newTabRuns[i] = tabRuns[currentRun]; + currentRun = getNextTabRun(currentRun); + i++; + } + while (i < runCount); + if (runCount > 1) + newTabRuns[0] = tabRuns[currentRun]; + + tabRuns = newTabRuns; + BasicTabbedPaneUI.this.selectedRun = 1; + } + + /** + * This method is called when a component is removed from the + * JTabbedPane. + * + * @param comp The component removed. + */ + public void removeLayoutComponent(Component comp) + { + // Do nothing. + } + } + + /** + * This class acts as the LayoutManager for the JTabbedPane in + * SCROLL_TAB_MODE. + */ + private class TabbedPaneScrollLayout extends TabbedPaneLayout + { + /** + * This method returns the preferred layout size for the given container. + * + * @param parent The container to calculate a size for. + * + * @return The preferred layout size. + */ + public Dimension preferredLayoutSize(Container parent) + { + return super.calculateSize(true); + } + + /** + * This method returns the minimum layout size for the given container. + * + * @param parent The container to calculate a size for. + * + * @return The minimum layout size. + */ + public Dimension minimumLayoutSize(Container parent) + { + return super.calculateSize(true); + } + + /** + * This method calculates the tab area height given a desired width. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param width The expected width. + * + * @return The tab area height given the width. + */ + protected int preferredTabAreaHeight(int tabPlacement, int width) + { + if (tabPane.getTabCount() == 0) + return calculateTabAreaHeight(tabPlacement, 0, 0); + + int runs = 1; + + int maxTabHeight = calculateMaxTabHeight(tabPlacement); + int tabAreaHeight = calculateTabAreaHeight(tabPlacement, runs, + maxTabHeight); + return tabAreaHeight; + } + + /** + * This method calculates the tab area width given a desired height. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param height The expected height. + * + * @return The tab area width given the height. + */ + protected int preferredTabAreaWidth(int tabPlacement, int height) + { + if (tabPane.getTabCount() == 0) + return calculateTabAreaHeight(tabPlacement, 0, 0); + + int runs = 1; + + int maxTabWidth = calculateMaxTabWidth(tabPlacement); + int tabAreaWidth = calculateTabAreaWidth(tabPlacement, runs, maxTabWidth); + return tabAreaWidth; + } + + /** + * This method is called to calculate the tab rectangles. This method + * will calculate the size and position of all rectangles (taking into + * account which ones should be in which tab run). It will pad them and + * normalize them as necessary. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param tabCount The number of tabs. + */ + protected void calculateTabRects(int tabPlacement, int tabCount) + { + if (tabCount == 0) + return; + assureRectsCreated(tabCount); + + FontMetrics fm = getFontMetrics(); + SwingUtilities.calculateInnerArea(tabPane, calcRect); + Insets tabAreaInsets = getTabAreaInsets(tabPlacement); + Insets insets = tabPane.getInsets(); + int max = 0; + int runs = 1; + int start = 0; + int top = 0; + if (tabPlacement == SwingConstants.TOP + || tabPlacement == SwingConstants.BOTTOM) + { + int maxHeight = calculateMaxTabHeight(tabPlacement); + calcRect.width -= tabAreaInsets.left + tabAreaInsets.right; + max = calcRect.width + tabAreaInsets.left + insets.left; + start = tabAreaInsets.left + insets.left; + int width = 0; + int runWidth = start; + top = insets.top + tabAreaInsets.top; + for (int i = 0; i < tabCount; i++) + { + width = calculateTabWidth(tabPlacement, i, fm); + + rects[i] = new Rectangle(runWidth, top, width, maxHeight); + runWidth += width; + } + tabAreaRect.width = tabPane.getWidth() - insets.left - insets.right; + tabAreaRect.height = runs * maxTabHeight + - (runs - 1) * tabRunOverlay + + tabAreaInsets.top + tabAreaInsets.bottom; + contentRect.width = tabAreaRect.width; + contentRect.height = tabPane.getHeight() - insets.top + - insets.bottom - tabAreaRect.height; + contentRect.x = insets.left; + tabAreaRect.x = insets.left; + if (tabPlacement == SwingConstants.BOTTOM) + { + contentRect.y = insets.top; + tabAreaRect.y = contentRect.y + contentRect.height; + } + else + { + tabAreaRect.y = insets.top; + contentRect.y = tabAreaRect.y + tabAreaRect.height; + } + } + else + { + int maxWidth = calculateMaxTabWidth(tabPlacement); + + calcRect.height -= tabAreaInsets.top + tabAreaInsets.bottom; + max = calcRect.height + tabAreaInsets.top; + int height = 0; + start = tabAreaInsets.top + insets.top; + int runHeight = start; + int fontHeight = fm.getHeight(); + top = insets.left + tabAreaInsets.left; + for (int i = 0; i < tabCount; i++) + { + height = calculateTabHeight(tabPlacement, i, fontHeight); + rects[i] = new Rectangle(top, runHeight, maxWidth, height); + runHeight += height; + } + tabAreaRect.width = runs * maxTabWidth - (runs - 1) * tabRunOverlay + + tabAreaInsets.left + tabAreaInsets.right; + tabAreaRect.height = tabPane.getHeight() - insets.top + - insets.bottom; + tabAreaRect.y = insets.top; + contentRect.width = tabPane.getWidth() - insets.left - insets.right + - tabAreaRect.width; + contentRect.height = tabAreaRect.height; + contentRect.y = insets.top; + if (tabPlacement == SwingConstants.LEFT) + { + tabAreaRect.x = insets.left; + contentRect.x = tabAreaRect.x + tabAreaRect.width; + } + else + { + contentRect.x = insets.left; + tabAreaRect.x = contentRect.x + contentRect.width; + } + } + runCount = runs; + + padSelectedTab(tabPlacement, tabPane.getSelectedIndex()); + } + + /** + * This method is called when the JTabbedPane is laid out in + * SCROLL_TAB_LAYOUT. It finds the position for all components in the + * JTabbedPane. + * + * @param pane The JTabbedPane to be laid out. + */ + public void layoutContainer(Container pane) + { + super.layoutContainer(pane); + int tabCount = tabPane.getTabCount(); + Point p = null; + if (tabCount == 0) + return; + int tabPlacement = tabPane.getTabPlacement(); + incrButton.hide(); + decrButton.hide(); + if (tabPlacement == SwingConstants.TOP + || tabPlacement == SwingConstants.BOTTOM) + { + if (tabAreaRect.x + tabAreaRect.width < rects[tabCount - 1].x + + rects[tabCount - 1].width) + { + Dimension incrDims = incrButton.getPreferredSize(); + Dimension decrDims = decrButton.getPreferredSize(); + + decrButton.setBounds(tabAreaRect.x + tabAreaRect.width + - incrDims.width - decrDims.width, + tabAreaRect.y, decrDims.width, + tabAreaRect.height); + incrButton.setBounds(tabAreaRect.x + tabAreaRect.width + - incrDims.width, tabAreaRect.y, + decrDims.width, tabAreaRect.height); + + tabAreaRect.width -= decrDims.width + incrDims.width; + incrButton.show(); + decrButton.show(); + } + } + + if (tabPlacement == SwingConstants.LEFT + || tabPlacement == SwingConstants.RIGHT) + { + if (tabAreaRect.y + tabAreaRect.height < rects[tabCount - 1].y + + rects[tabCount - 1].height) + { + Dimension incrDims = incrButton.getPreferredSize(); + Dimension decrDims = decrButton.getPreferredSize(); + + decrButton.setBounds(tabAreaRect.x, + tabAreaRect.y + tabAreaRect.height + - incrDims.height - decrDims.height, + tabAreaRect.width, decrDims.height); + incrButton.setBounds(tabAreaRect.x, + tabAreaRect.y + tabAreaRect.height + - incrDims.height, tabAreaRect.width, + incrDims.height); + + tabAreaRect.height -= decrDims.height + incrDims.height; + incrButton.show(); + decrButton.show(); + } + } + viewport.setBounds(tabAreaRect.x, tabAreaRect.y, tabAreaRect.width, + tabAreaRect.height); + int tabC = tabPane.getTabCount() - 1; + if (tabCount > 0) + { + int w = Math.max(rects[tabC].width + rects[tabC].x, tabAreaRect.width); + int h = Math.max(rects[tabC].height, tabAreaRect.height); + p = findPointForIndex(currentScrollLocation); + + // we want to cover that entire space so that borders that run under + // the tab area don't show up when we move the viewport around. + panel.setSize(w + p.x, h + p.y); + } + viewport.setViewPosition(p); + viewport.repaint(); + } + } + + /** + * This class handles ChangeEvents from the JTabbedPane. + * + * @specnote Apparently this class was intended to be protected, + * but was made public by a compiler bug and is now + * public for compatibility. + */ + public class TabSelectionHandler implements ChangeListener + { + /** + * This method is called whenever a ChangeEvent is fired from the + * JTabbedPane. + * + * @param e The ChangeEvent fired. + */ + public void stateChanged(ChangeEvent e) + { + selectedRun = getRunForTab(tabPane.getTabCount(), + tabPane.getSelectedIndex()); + tabPane.revalidate(); + tabPane.repaint(); + } + } + + /** + * This helper class is a JPanel that fits inside the ScrollViewport. This + * panel's sole job is to paint the tab rectangles inside the viewport so + * that it's clipped correctly. + */ + private class ScrollingPanel extends JPanel + { + /** + * This is a private UI class for our panel. + */ + private class ScrollingPanelUI extends BasicPanelUI + { + /** + * This method overrides the default paint method. It paints the tab + * rectangles for the JTabbedPane in the panel. + * + * @param g The Graphics object to paint with. + * @param c The JComponent to paint. + */ + public void paint(Graphics g, JComponent c) + { + paintTabArea(g, tabPane.getTabPlacement(), tabPane.getSelectedIndex()); + } + } + + /** + * This method overrides the updateUI method. It makes the default UI for + * this ScrollingPanel to be a ScrollingPanelUI. + */ + public void updateUI() + { + setUI((PanelUI) new ScrollingPanelUI()); + } + } + + /** + * This is a helper class that paints the panel that paints tabs. This + * custom JViewport is used so that the tabs painted in the panel will be + * clipped. This class implements UIResource so tabs are not added when + * this objects of this class are added to the JTabbedPane. + */ + private class ScrollingViewport extends JViewport implements UIResource + { + } + + /** + * This is a helper class that implements UIResource so it is not added as a + * tab when an object of this class is added to the JTabbedPane. + */ + private class ScrollingButton extends BasicArrowButton implements UIResource + { + /** + * Creates a ScrollingButton given the direction. + * + * @param dir The direction to point in. + */ + public ScrollingButton(int dir) + { + super(dir); + } + } + + /** The button that increments the current scroll location. + * This is package-private to avoid an accessor method. */ + transient ScrollingButton incrButton; + + /** The button that decrements the current scroll location. + * This is package-private to avoid an accessor method. */ + transient ScrollingButton decrButton; + + /** The viewport used to display the tabs. + * This is package-private to avoid an accessor method. */ + transient ScrollingViewport viewport; + + /** The panel inside the viewport that paints the tabs. + * This is package-private to avoid an accessor method. */ + transient ScrollingPanel panel; + + /** The starting visible tab in the run in SCROLL_TAB_MODE. + * This is package-private to avoid an accessor method. */ + transient int currentScrollLocation; + + /** A reusable rectangle. */ + protected Rectangle calcRect; + + /** An array of Rectangles keeping track of the tabs' area and position. */ + protected Rectangle[] rects; + + /** The insets around the content area. */ + protected Insets contentBorderInsets; + + /** The extra insets around the selected tab. */ + protected Insets selectedTabPadInsets; + + /** The insets around the tab area. */ + protected Insets tabAreaInsets; + + /** The insets around each and every tab. */ + protected Insets tabInsets; + + /** + * The outer bottom and right edge color for both the tab and content + * border. + */ + protected Color darkShadow; + + /** The color of the focus outline on the selected tab. */ + protected Color focus; + + /** FIXME: find a use for this. */ + protected Color highlight; + + /** The top and left edge color for both the tab and content border. */ + protected Color lightHighlight; + + /** The inner bottom and right edge color for the tab and content border. */ + protected Color shadow; + + /** The maximum tab height. */ + protected int maxTabHeight; + + /** The maximum tab width. */ + protected int maxTabWidth; + + /** The number of runs in the JTabbedPane. */ + protected int runCount; + + /** The index of the run that the selected index is in. */ + protected int selectedRun; + + /** The amount of space each run overlaps the previous by. */ + protected int tabRunOverlay; + + /** The gap between text and label */ + protected int textIconGap; + + // Keeps track of tab runs. + // The organization of this array is as follows (lots of experimentation to + // figure this out) + // index 0 = furthest away from the component area (aka outer run) + // index 1 = closest to component area (aka selected run) + // index > 1 = listed in order leading from selected run to outer run. + // each int in the array is the tab index + 1 (counting starts at 1) + // for the last tab in the run. (same as the rects array) + + /** This array keeps track of which tabs are in which run. See above. */ + protected int[] tabRuns; + + /** + * This is the keystroke for moving down. + * + * @deprecated 1.3 + */ + protected KeyStroke downKey; + + /** + * This is the keystroke for moving left. + * + * @deprecated 1.3 + */ + protected KeyStroke leftKey; + + /** + * This is the keystroke for moving right. + * + * @deprecated 1.3 + */ + protected KeyStroke rightKey; + + /** + * This is the keystroke for moving up. + * + * @deprecated 1.3 + */ + protected KeyStroke upKey; + + /** The listener that listens for focus events. */ + protected FocusListener focusListener; + + /** The listener that listens for mouse events. */ + protected MouseListener mouseListener; + + /** The listener that listens for property change events. */ + protected PropertyChangeListener propertyChangeListener; + + /** The listener that listens for change events. */ + protected ChangeListener tabChangeListener; + + /** The tab pane that this UI paints. */ + protected JTabbedPane tabPane; + + /** The current layout manager for the tabPane. + * This is package-private to avoid an accessor method. */ + transient LayoutManager layoutManager; + + /** The rectangle that describes the tab area's position and size. + * This is package-private to avoid an accessor method. */ + transient Rectangle tabAreaRect; + + /** The rectangle that describes the content area's position and + * size. This is package-private to avoid an accessor method. */ + transient Rectangle contentRect; + + /** + * Creates a new BasicTabbedPaneUI object. + */ + public BasicTabbedPaneUI() + { + super(); + } + + /** + * This method creates a ScrollingButton that points in the appropriate + * direction for an increasing button. + * This is package-private to avoid an accessor method. + * + * @return The increase ScrollingButton. + */ + ScrollingButton createIncreaseButton() + { + if (incrButton == null) + incrButton = new ScrollingButton(SwingConstants.NORTH); + if (tabPane.getTabPlacement() == SwingConstants.TOP + || tabPane.getTabPlacement() == SwingConstants.BOTTOM) + incrButton.setDirection(SwingConstants.EAST); + else + incrButton.setDirection(SwingConstants.SOUTH); + return incrButton; + } + + /** + * This method creates a ScrollingButton that points in the appropriate + * direction for a decreasing button. + * This is package-private to avoid an accessor method. + * + * @return The decrease ScrollingButton. + */ + ScrollingButton createDecreaseButton() + { + if (decrButton == null) + decrButton = new ScrollingButton(SwingConstants.SOUTH); + if (tabPane.getTabPlacement() == SwingConstants.TOP + || tabPane.getTabPlacement() == SwingConstants.BOTTOM) + decrButton.setDirection(SwingConstants.WEST); + else + decrButton.setDirection(SwingConstants.NORTH); + return decrButton; + } + + /** + * This method finds the point to set the view position at given the index + * of a tab. The tab will be the first visible tab in the run. + * This is package-private to avoid an accessor method. + * + * @param index The index of the first visible tab. + * + * @return The position of the first visible tab. + */ + Point findPointForIndex(int index) + { + int tabPlacement = tabPane.getTabPlacement(); + int selectedIndex = tabPane.getSelectedIndex(); + Insets insets = getSelectedTabPadInsets(tabPlacement); + int w = 0; + int h = 0; + + if (tabPlacement == TOP || tabPlacement == BOTTOM) + { + if (index > 0) + { + w += rects[index - 1].x + rects[index - 1].width; + if (index > selectedIndex) + w -= insets.left + insets.right; + } + } + + else + { + if (index > 0) + { + h += rects[index - 1].y + rects[index - 1].height; + if (index > selectedIndex) + h -= insets.top + insets.bottom; + } + } + + Point p = new Point(w, h); + return p; + } + + /** + * This method creates a new BasicTabbedPaneUI. + * + * @param c The JComponent to create a UI for. + * + * @return A new BasicTabbedPaneUI. + */ + public static ComponentUI createUI(JComponent c) + { + return new BasicTabbedPaneUI(); + } + + /** + * This method installs the UI for the given JComponent. + * + * @param c The JComponent to install the UI for. + */ + public void installUI(JComponent c) + { + super.installUI(c); + if (c instanceof JTabbedPane) + { + tabPane = (JTabbedPane) c; + + installComponents(); + installDefaults(); + installListeners(); + installKeyboardActions(); + + layoutManager = createLayoutManager(); + tabPane.setLayout(layoutManager); + tabPane.layout(); + } + } + + /** + * This method uninstalls the UI for the given JComponent. + * + * @param c The JComponent to uninstall the UI for. + */ + public void uninstallUI(JComponent c) + { + layoutManager = null; + + uninstallKeyboardActions(); + uninstallListeners(); + uninstallDefaults(); + uninstallComponents(); + + tabPane = null; + } + + /** + * This method creates the appropriate layout manager for the JTabbedPane's + * current tab layout policy. If the tab layout policy is + * SCROLL_TAB_LAYOUT, then all the associated components that need to be + * created will be done so now. + * + * @return A layout manager given the tab layout policy. + */ + protected LayoutManager createLayoutManager() + { + if (tabPane.getTabLayoutPolicy() == JTabbedPane.WRAP_TAB_LAYOUT) + return new TabbedPaneLayout(); + else + { + incrButton = createIncreaseButton(); + decrButton = createDecreaseButton(); + viewport = new ScrollingViewport(); + viewport.setLayout(null); + panel = new ScrollingPanel(); + viewport.setView(panel); + tabPane.add(incrButton); + tabPane.add(decrButton); + tabPane.add(viewport); + currentScrollLocation = 0; + decrButton.setEnabled(false); + panel.addMouseListener(mouseListener); + incrButton.addMouseListener(mouseListener); + decrButton.addMouseListener(mouseListener); + viewport.setBackground(Color.LIGHT_GRAY); + + return new TabbedPaneScrollLayout(); + } + } + + /** + * This method installs components for this JTabbedPane. + */ + protected void installComponents() + { + // Nothing to be done. + } + + /** + * This method uninstalls components for this JTabbedPane. + */ + protected void uninstallComponents() + { + // Nothing to be done. + } + + /** + * This method installs defaults for the Look and Feel. + */ + protected void installDefaults() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + tabPane.setFont(defaults.getFont("TabbedPane.font")); + tabPane.setForeground(defaults.getColor("TabbedPane.foreground")); + tabPane.setBackground(defaults.getColor("TabbedPane.background")); + tabPane.setOpaque(false); + + highlight = defaults.getColor("TabbedPane.highlight"); + lightHighlight = defaults.getColor("TabbedPane.lightHighlight"); + + shadow = defaults.getColor("TabbedPane.shadow"); + darkShadow = defaults.getColor("TabbedPane.darkShadow"); + + focus = defaults.getColor("TabbedPane.focus"); + + textIconGap = defaults.getInt("TabbedPane.textIconGap"); + tabRunOverlay = defaults.getInt("TabbedPane.tabRunOverlay"); + + tabInsets = defaults.getInsets("TabbedPane.tabbedPaneTabInsets"); + selectedTabPadInsets = defaults.getInsets("TabbedPane.tabbedPaneTabPadInsets"); + tabAreaInsets = defaults.getInsets("TabbedPane.tabbedPaneTabAreaInsets"); + contentBorderInsets = defaults.getInsets("TabbedPane.tabbedPaneContentBorderInsets"); + + calcRect = new Rectangle(); + tabRuns = new int[10]; + tabAreaRect = new Rectangle(); + contentRect = new Rectangle(); + } + + /** + * This method uninstalls defaults for the Look and Feel. + */ + protected void uninstallDefaults() + { + calcRect = null; + tabAreaRect = null; + contentRect = null; + tabRuns = null; + + contentBorderInsets = null; + tabAreaInsets = null; + selectedTabPadInsets = null; + tabInsets = null; + + focus = null; + darkShadow = null; + shadow = null; + lightHighlight = null; + highlight = null; + + tabPane.setBackground(null); + tabPane.setForeground(null); + tabPane.setFont(null); + } + + /** + * This method creates and installs the listeners for this UI. + */ + protected void installListeners() + { + mouseListener = createMouseListener(); + tabChangeListener = createChangeListener(); + propertyChangeListener = createPropertyChangeListener(); + focusListener = createFocusListener(); + + tabPane.addMouseListener(mouseListener); + tabPane.addChangeListener(tabChangeListener); + tabPane.addPropertyChangeListener(propertyChangeListener); + tabPane.addFocusListener(focusListener); + } + + /** + * This method removes and nulls the listeners for this UI. + */ + protected void uninstallListeners() + { + tabPane.removeFocusListener(focusListener); + tabPane.removePropertyChangeListener(propertyChangeListener); + tabPane.removeChangeListener(tabChangeListener); + tabPane.removeMouseListener(mouseListener); + + focusListener = null; + propertyChangeListener = null; + tabChangeListener = null; + mouseListener = null; + } + + /** + * This method creates a new MouseListener. + * + * @return A new MouseListener. + */ + protected MouseListener createMouseListener() + { + return new MouseHandler(); + } + + /** + * This method creates a new FocusListener. + * + * @return A new FocusListener. + */ + protected FocusListener createFocusListener() + { + return new FocusHandler(); + } + + /** + * This method creates a new ChangeListener. + * + * @return A new ChangeListener. + */ + protected ChangeListener createChangeListener() + { + return new TabSelectionHandler(); + } + + /** + * This method creates a new PropertyChangeListener. + * + * @return A new PropertyChangeListener. + */ + protected PropertyChangeListener createPropertyChangeListener() + { + return new PropertyChangeHandler(); + } + + /** + * This method installs keyboard actions for the JTabbedPane. + */ + protected void installKeyboardActions() + { + // FIXME: Implement. + } + + /** + * This method uninstalls keyboard actions for the JTabbedPane. + */ + protected void uninstallKeyboardActions() + { + // FIXME: Implement. + } + + /** + * This method returns the preferred size of the JTabbedPane. + * + * @param c The JComponent to find a size for. + * + * @return The preferred size. + */ + public Dimension getPreferredSize(JComponent c) + { + return layoutManager.preferredLayoutSize(tabPane); + } + + /** + * This method returns the minimum size of the JTabbedPane. + * + * @param c The JComponent to find a size for. + * + * @return The minimum size. + */ + public Dimension getMinimumSize(JComponent c) + { + return layoutManager.minimumLayoutSize(tabPane); + } + + /** + * This method returns the maximum size of the JTabbedPane. + * + * @param c The JComponent to find a size for. + * + * @return The maximum size. + */ + public Dimension getMaximumSize(JComponent c) + { + return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE); + } + + /** + * This method paints the JTabbedPane. + * + * @param g The Graphics object to paint with. + * @param c The JComponent to paint. + */ + public void paint(Graphics g, JComponent c) + { + if (tabPane.getTabCount() == 0) + return; + if (tabPane.getTabLayoutPolicy() == JTabbedPane.WRAP_TAB_LAYOUT) + paintTabArea(g, tabPane.getTabPlacement(), tabPane.getSelectedIndex()); + paintContentBorder(g, tabPane.getTabPlacement(), tabPane.getSelectedIndex()); + } + + /** + * This method paints the tab area. This includes painting the rectangles + * that make up the tabs. + * + * @param g The Graphics object to paint with. + * @param tabPlacement The JTabbedPane's tab placement. + * @param selectedIndex The selected index. + */ + protected void paintTabArea(Graphics g, int tabPlacement, int selectedIndex) + { + Rectangle ir = new Rectangle(); + Rectangle tr = new Rectangle(); + + boolean isScroll = tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT; + + // Please note: the ordering of the painting is important. + // we WANT to paint the outermost run first and then work our way in. + int tabCount = tabPane.getTabCount(); + int currRun = 1; + if (tabCount < 1) + return; + + if (runCount > 1) + currRun = 0; + for (int i = 0; i < runCount; i++) + { + int first = lastTabInRun(tabCount, getPreviousTabRun(currRun)) + 1; + if (isScroll) + first = currentScrollLocation; + else if (first == tabCount) + first = 0; + int last = lastTabInRun(tabCount, currRun); + if (isScroll) + { + for (int k = first; k < tabCount; k++) + { + if (rects[k].x + rects[k].width - rects[first].x > viewport + .getWidth()) + { + last = k; + break; + } + } + } + + for (int j = first; j <= last; j++) + { + if (j != selectedIndex || isScroll) + paintTab(g, tabPlacement, rects, j, ir, tr); + } + currRun = getPreviousTabRun(currRun); + } + if (! isScroll) + paintTab(g, tabPlacement, rects, selectedIndex, ir, tr); + } + + /** + * This method paints an individual tab. + * + * @param g The Graphics object to paint with. + * @param tabPlacement The JTabbedPane's tab placement. + * @param rects The array of rectangles that keep the size and position of + * the tabs. + * @param tabIndex The tab index to paint. + * @param iconRect The rectangle to use for the icon. + * @param textRect The rectangle to use for the text. + */ + protected void paintTab(Graphics g, int tabPlacement, Rectangle[] rects, + int tabIndex, Rectangle iconRect, Rectangle textRect) + { + FontMetrics fm = getFontMetrics(); + Icon icon = getIconForTab(tabIndex); + String title = tabPane.getTitleAt(tabIndex); + boolean isSelected = tabIndex == tabPane.getSelectedIndex(); + calcRect = getTabBounds(tabPane, tabIndex); + + int x = calcRect.x; + int y = calcRect.y; + int w = calcRect.width; + int h = calcRect.height; + if (getRunForTab(tabPane.getTabCount(), tabIndex) == 1) + { + Insets insets = getTabAreaInsets(tabPlacement); + switch (tabPlacement) + { + case TOP: + h += insets.bottom; + break; + case LEFT: + w += insets.right; + break; + case BOTTOM: + y -= insets.top; + h += insets.top; + break; + case RIGHT: + x -= insets.left; + w += insets.left; + break; + } + } + + layoutLabel(tabPlacement, fm, tabIndex, title, icon, calcRect, iconRect, + textRect, isSelected); + paintTabBackground(g, tabPlacement, tabIndex, x, y, w, h, isSelected); + paintTabBorder(g, tabPlacement, tabIndex, x, y, w, h, isSelected); + + // FIXME: Paint little folding corner and jagged edge clipped tab. + if (icon != null) + paintIcon(g, tabPlacement, tabIndex, icon, iconRect, isSelected); + if (title != null && ! title.equals("")) + paintText(g, tabPlacement, tabPane.getFont(), fm, tabIndex, title, + textRect, isSelected); + } + + /** + * This method lays out the tab and finds the location to paint the icon + * and text. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param metrics The font metrics for the font to paint with. + * @param tabIndex The tab index to paint. + * @param title The string painted. + * @param icon The icon painted. + * @param tabRect The tab bounds. + * @param iconRect The calculated icon bounds. + * @param textRect The calculated text bounds. + * @param isSelected Whether this tab is selected. + */ + protected void layoutLabel(int tabPlacement, FontMetrics metrics, + int tabIndex, String title, Icon icon, + Rectangle tabRect, Rectangle iconRect, + Rectangle textRect, boolean isSelected) + { + SwingUtilities.layoutCompoundLabel(metrics, title, icon, + SwingConstants.CENTER, + SwingConstants.CENTER, + SwingConstants.CENTER, + SwingConstants.CENTER, tabRect, + iconRect, textRect, textIconGap); + + int shiftX = getTabLabelShiftX(tabPlacement, tabIndex, isSelected); + int shiftY = getTabLabelShiftY(tabPlacement, tabIndex, isSelected); + + iconRect.x += shiftX; + iconRect.y += shiftY; + + textRect.x += shiftX; + textRect.y += shiftY; + } + + /** + * This method paints the icon. + * + * @param g The Graphics object to paint. + * @param tabPlacement The JTabbedPane's tab placement. + * @param tabIndex The tab index to paint. + * @param icon The icon to paint. + * @param iconRect The bounds of the icon. + * @param isSelected Whether this tab is selected. + */ + protected void paintIcon(Graphics g, int tabPlacement, int tabIndex, + Icon icon, Rectangle iconRect, boolean isSelected) + { + icon.paintIcon(tabPane, g, iconRect.x, iconRect.y); + } + + /** + * This method paints the text for the given tab. + * + * @param g The Graphics object to paint with. + * @param tabPlacement The JTabbedPane's tab placement. + * @param font The font to paint with. + * @param metrics The fontmetrics of the given font. + * @param tabIndex The tab index. + * @param title The string to paint. + * @param textRect The bounds of the string. + * @param isSelected Whether this tab is selected. + */ + protected void paintText(Graphics g, int tabPlacement, Font font, + FontMetrics metrics, int tabIndex, String title, + Rectangle textRect, boolean isSelected) + { + View textView = getTextViewForTab(tabIndex); + if (textView != null) + { + textView.paint(g, textRect); + return; + } + + Color fg = tabPane.getForegroundAt(tabIndex); + if (fg == null) + fg = tabPane.getForeground(); + Color bg = tabPane.getBackgroundAt(tabIndex); + if (bg == null) + bg = tabPane.getBackground(); + + Color saved_color = g.getColor(); + Font f = g.getFont(); + g.setFont(font); + + if (tabPane.isEnabledAt(tabIndex)) + { + g.setColor(fg); + + int mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex); + + if (mnemIndex != -1) + BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex, + textRect.x, + textRect.y + + metrics.getAscent()); + else + g.drawString(title, textRect.x, textRect.y + metrics.getAscent()); + } + else + { + g.setColor(bg.brighter()); + + int mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex); + + if (mnemIndex != -1) + BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex, + textRect.x, textRect.y); + else + g.drawString(title, textRect.x, textRect.y); + + g.setColor(bg.darker()); + if (mnemIndex != -1) + BasicGraphicsUtils.drawStringUnderlineCharAt(g, title, mnemIndex, + textRect.x + 1, + textRect.y + 1); + else + g.drawString(title, textRect.x + 1, textRect.y + 1); + } + + g.setColor(saved_color); + g.setFont(f); + } + + /** + * This method returns how much the label for the tab should shift in the X + * direction. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param tabIndex The tab index being painted. + * @param isSelected Whether this tab is selected. + * + * @return The amount the label should shift by in the X direction. + */ + protected int getTabLabelShiftX(int tabPlacement, int tabIndex, + boolean isSelected) + { + // No reason to shift. + return 0; + } + + /** + * This method returns how much the label for the tab should shift in the Y + * direction. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param tabIndex The tab index being painted. + * @param isSelected Whether this tab is selected. + * + * @return The amount the label should shift by in the Y direction. + */ + protected int getTabLabelShiftY(int tabPlacement, int tabIndex, + boolean isSelected) + { + // No reason to shift. + return 0; + } + + /** + * This method paints the focus rectangle around the selected tab. + * + * @param g The Graphics object to paint with. + * @param tabPlacement The JTabbedPane's tab placement. + * @param rects The array of rectangles keeping track of size and position. + * @param tabIndex The tab index. + * @param iconRect The icon bounds. + * @param textRect The text bounds. + * @param isSelected Whether this tab is selected. + */ + protected void paintFocusIndicator(Graphics g, int tabPlacement, + Rectangle[] rects, int tabIndex, + Rectangle iconRect, Rectangle textRect, + boolean isSelected) + { + Color saved = g.getColor(); + calcRect = iconRect.union(textRect); + + g.setColor(focus); + + g.drawRect(calcRect.x, calcRect.y, calcRect.width, calcRect.height); + + g.setColor(saved); + } + + /** + * This method paints the border for an individual tab. + * + * @param g The Graphics object to paint with. + * @param tabPlacement The JTabbedPane's tab placement. + * @param tabIndex The tab index. + * @param x The x position of the tab. + * @param y The y position of the tab. + * @param w The width of the tab. + * @param h The height of the tab. + * @param isSelected Whether the tab is selected. + */ + protected void paintTabBorder(Graphics g, int tabPlacement, int tabIndex, + int x, int y, int w, int h, boolean isSelected) + { + Color saved = g.getColor(); + + if (! isSelected || tabPlacement != SwingConstants.TOP) + { + g.setColor(shadow); + g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1); + g.setColor(darkShadow); + g.drawLine(x, y + h, x + w, y + h); + } + + if (! isSelected || tabPlacement != SwingConstants.LEFT) + { + g.setColor(darkShadow); + g.drawLine(x + w, y, x + w, y + h); + g.setColor(shadow); + g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1); + } + + if (! isSelected || tabPlacement != SwingConstants.RIGHT) + { + g.setColor(lightHighlight); + g.drawLine(x, y, x, y + h); + } + + if (! isSelected || tabPlacement != SwingConstants.BOTTOM) + { + g.setColor(lightHighlight); + g.drawLine(x, y, x + w, y); + } + + g.setColor(saved); + } + + /** + * This method paints the background for an individual tab. + * + * @param g The Graphics object to paint with. + * @param tabPlacement The JTabbedPane's tab placement. + * @param tabIndex The tab index. + * @param x The x position of the tab. + * @param y The y position of the tab. + * @param w The width of the tab. + * @param h The height of the tab. + * @param isSelected Whether the tab is selected. + */ + protected void paintTabBackground(Graphics g, int tabPlacement, + int tabIndex, int x, int y, int w, int h, + boolean isSelected) + { + Color saved = g.getColor(); + if (isSelected) + g.setColor(Color.LIGHT_GRAY); + else + { + Color bg = tabPane.getBackgroundAt(tabIndex); + if (bg == null) + bg = Color.GRAY; + g.setColor(bg); + } + + g.fillRect(x, y, w, h); + + g.setColor(saved); + } + + /** + * This method paints the border around the content area. + * + * @param g The Graphics object to paint with. + * @param tabPlacement The JTabbedPane's tab placement. + * @param selectedIndex The index of the selected tab. + */ + protected void paintContentBorder(Graphics g, int tabPlacement, + int selectedIndex) + { + Insets insets = getContentBorderInsets(tabPlacement); + int x = contentRect.x; + int y = contentRect.y; + int w = contentRect.width; + int h = contentRect.height; + paintContentBorderTopEdge(g, tabPlacement, selectedIndex, x, y, w, h); + paintContentBorderLeftEdge(g, tabPlacement, selectedIndex, x, y, w, h); + paintContentBorderBottomEdge(g, tabPlacement, selectedIndex, x, y, w, h); + paintContentBorderRightEdge(g, tabPlacement, selectedIndex, x, y, w, h); + } + + /** + * This method paints the top edge of the content border. + * + * @param g The Graphics object to paint with. + * @param tabPlacement The JTabbedPane's tab placement. + * @param selectedIndex The selected tab index. + * @param x The x coordinate for the content area. + * @param y The y coordinate for the content area. + * @param w The width of the content area. + * @param h The height of the content area. + */ + protected void paintContentBorderTopEdge(Graphics g, int tabPlacement, + int selectedIndex, int x, int y, + int w, int h) + { + Color saved = g.getColor(); + g.setColor(lightHighlight); + + int startgap = rects[selectedIndex].x; + int endgap = rects[selectedIndex].x + rects[selectedIndex].width; + + int diff = 0; + + if (tabPlacement == SwingConstants.TOP) + { + if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) + { + Point p = findPointForIndex(currentScrollLocation); + diff = p.x; + } + + g.drawLine(x, y, startgap - diff, y); + g.drawLine(endgap - diff, y, x + w, y); + } + else + g.drawLine(x, y, x + w, y); + + g.setColor(saved); + } + + /** + * This method paints the left edge of the content border. + * + * @param g The Graphics object to paint with. + * @param tabPlacement The JTabbedPane's tab placement. + * @param selectedIndex The selected tab index. + * @param x The x coordinate for the content area. + * @param y The y coordinate for the content area. + * @param w The width of the content area. + * @param h The height of the content area. + */ + protected void paintContentBorderLeftEdge(Graphics g, int tabPlacement, + int selectedIndex, int x, int y, + int w, int h) + { + Color saved = g.getColor(); + g.setColor(lightHighlight); + + int startgap = rects[selectedIndex].y; + int endgap = rects[selectedIndex].y + rects[selectedIndex].height; + + int diff = 0; + + if (tabPlacement == SwingConstants.LEFT) + { + if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) + { + Point p = findPointForIndex(currentScrollLocation); + diff = p.y; + } + + g.drawLine(x, y, x, startgap - diff); + g.drawLine(x, endgap - diff, x, y + h); + } + else + g.drawLine(x, y, x, y + h); + + g.setColor(saved); + } + + /** + * This method paints the bottom edge of the content border. + * + * @param g The Graphics object to paint with. + * @param tabPlacement The JTabbedPane's tab placement. + * @param selectedIndex The selected tab index. + * @param x The x coordinate for the content area. + * @param y The y coordinate for the content area. + * @param w The width of the content area. + * @param h The height of the content area. + */ + protected void paintContentBorderBottomEdge(Graphics g, int tabPlacement, + int selectedIndex, int x, int y, + int w, int h) + { + Color saved = g.getColor(); + + int startgap = rects[selectedIndex].x; + int endgap = rects[selectedIndex].x + rects[selectedIndex].width; + + int diff = 0; + + if (tabPlacement == SwingConstants.BOTTOM) + { + if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) + { + Point p = findPointForIndex(currentScrollLocation); + diff = p.x; + } + + g.setColor(shadow); + g.drawLine(x + 1, y + h - 1, startgap - diff, y + h - 1); + g.drawLine(endgap - diff, y + h - 1, x + w - 1, y + h - 1); + + g.setColor(darkShadow); + g.drawLine(x, y + h, startgap - diff, y + h); + g.drawLine(endgap - diff, y + h, x + w, y + h); + } + else + { + g.setColor(shadow); + g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1); + g.setColor(darkShadow); + g.drawLine(x, y + h, x + w, y + h); + } + + g.setColor(saved); + } + + /** + * This method paints the right edge of the content border. + * + * @param g The Graphics object to paint with. + * @param tabPlacement The JTabbedPane's tab placement. + * @param selectedIndex The selected tab index. + * @param x The x coordinate for the content area. + * @param y The y coordinate for the content area. + * @param w The width of the content area. + * @param h The height of the content area. + */ + protected void paintContentBorderRightEdge(Graphics g, int tabPlacement, + int selectedIndex, int x, int y, + int w, int h) + { + Color saved = g.getColor(); + int startgap = rects[selectedIndex].y; + int endgap = rects[selectedIndex].y + rects[selectedIndex].height; + + int diff = 0; + + if (tabPlacement == SwingConstants.RIGHT) + { + if (tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) + { + Point p = findPointForIndex(currentScrollLocation); + diff = p.y; + } + + g.setColor(shadow); + g.drawLine(x + w - 1, y + 1, x + w - 1, startgap - diff); + g.drawLine(x + w - 1, endgap - diff, x + w - 1, y + h - 1); + + g.setColor(darkShadow); + g.drawLine(x + w, y, x + w, startgap - diff); + g.drawLine(x + w, endgap - diff, x + w, y + h); + } + else + { + g.setColor(shadow); + g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1); + g.setColor(darkShadow); + g.drawLine(x + w, y, x + w, y + h); + } + + g.setColor(saved); + } + + /** + * This method returns the tab bounds for the given index. + * + * @param pane The JTabbedPane. + * @param i The index to look for. + * + * @return The bounds of the tab with the given index. + */ + public Rectangle getTabBounds(JTabbedPane pane, int i) + { + return rects[i]; + } + + /** + * This method returns the number of runs. + * + * @param pane The JTabbedPane. + * + * @return The number of runs. + */ + public int getTabRunCount(JTabbedPane pane) + { + return runCount; + } + + /** + * This method returns the tab index given a coordinate. + * + * @param pane The JTabbedPane. + * @param x The x coordinate. + * @param y The y coordinate. + * + * @return The tab index that the coordinate lands in. + */ + public int tabForCoordinate(JTabbedPane pane, int x, int y) + { + Point p = new Point(x, y); + int tabCount = tabPane.getTabCount(); + int currRun = 1; + for (int i = 0; i < runCount; i++) + { + int first = lastTabInRun(tabCount, getPreviousTabRun(currRun)) + 1; + if (first == tabCount) + first = 0; + int last = lastTabInRun(tabCount, currRun); + for (int j = first; j <= last; j++) + { + if (getTabBounds(pane, j).contains(p)) + return j; + } + currRun = getNextTabRun(currRun); + } + return -1; + } + + /** + * This method returns the tab bounds in the given rectangle. + * + * @param tabIndex The index to get bounds for. + * @param dest The rectangle to store bounds in. + * + * @return The rectangle passed in. + */ + protected Rectangle getTabBounds(int tabIndex, Rectangle dest) + { + dest.setBounds(getTabBounds(tabPane, tabIndex)); + return dest; + } + + /** + * This method returns the component that is shown in the content area. + * + * @return The component that is shown in the content area. + */ + protected Component getVisibleComponent() + { + return tabPane.getComponentAt(tabPane.getSelectedIndex()); + } + + /** + * This method sets the visible component. + * + * @param component The component to be set visible. + */ + protected void setVisibleComponent(Component component) + { + component.setVisible(true); + tabPane.setSelectedComponent(component); + } + + /** + * This method assures that enough rectangles are created given the + * tabCount. The old array is copied to the new one. + * + * @param tabCount The number of tabs. + */ + protected void assureRectsCreated(int tabCount) + { + if (rects == null) + rects = new Rectangle[tabCount]; + if (tabCount == rects.length) + return; + else + { + int numToCopy = Math.min(tabCount, rects.length); + Rectangle[] tmp = new Rectangle[tabCount]; + System.arraycopy(rects, 0, tmp, 0, numToCopy); + rects = tmp; + } + } + + /** + * This method expands the tabRuns array to give it more room. The old array + * is copied to the new one. + */ + protected void expandTabRunsArray() + { + // This method adds another 10 index positions to the tabRuns array. + if (tabRuns == null) + tabRuns = new int[10]; + else + { + int[] newRuns = new int[tabRuns.length + 10]; + System.arraycopy(tabRuns, 0, newRuns, 0, tabRuns.length); + tabRuns = newRuns; + } + } + + /** + * This method returns which run a particular tab belongs to. + * + * @param tabCount The number of tabs. + * @param tabIndex The tab to find. + * + * @return The tabRuns index that it belongs to. + */ + protected int getRunForTab(int tabCount, int tabIndex) + { + if (runCount == 1 && tabIndex < tabCount && tabIndex >= 0) + return 1; + for (int i = 0; i < runCount; i++) + { + int first = lastTabInRun(tabCount, getPreviousTabRun(i)) + 1; + if (first == tabCount) + first = 0; + int last = lastTabInRun(tabCount, i); + if (last >= tabIndex && first <= tabIndex) + return i; + } + return -1; + } + + /** + * This method returns the index of the last tab in a run. + * + * @param tabCount The number of tabs. + * @param run The run to check. + * + * @return The last tab in the given run. + */ + protected int lastTabInRun(int tabCount, int run) + { + if (tabRuns[run] == 0) + return tabCount - 1; + else + return tabRuns[run] - 1; + } + + /** + * This method returns the tab run overlay. + * + * @param tabPlacement The JTabbedPane's tab placement. + * + * @return The tab run overlay. + */ + protected int getTabRunOverlay(int tabPlacement) + { + return tabRunOverlay; + } + + /** + * This method returns the tab run indent. It is used in WRAP_TAB_LAYOUT and + * makes each tab run start indented by a certain amount. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param run The run to get indent for. + * + * @return The amount a run should be indented. + */ + protected int getTabRunIndent(int tabPlacement, int run) + { + return 0; + } + + /** + * This method returns whether a tab run should be padded. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param run The run to check. + * + * @return Whether the given run should be padded. + */ + protected boolean shouldPadTabRun(int tabPlacement, int run) + { + return true; + } + + /** + * This method returns whether the tab runs should be rotated. + * + * @param tabPlacement The JTabbedPane's tab placement. + * + * @return Whether runs should be rotated. + */ + protected boolean shouldRotateTabRuns(int tabPlacement) + { + return true; + } + + /** + * This method returns an icon for the tab. If the tab is disabled, it + * should return the disabledIcon. If it is enabled, then it should return + * the default icon. + * + * @param tabIndex The tab index to get an icon for. + * + * @return The icon for the tab index. + */ + protected Icon getIconForTab(int tabIndex) + { + if (tabPane.isEnabledAt(tabIndex)) + return tabPane.getIconAt(tabIndex); + else + return tabPane.getDisabledIconAt(tabIndex); + } + + /** + * This method returns a view that can paint the text for the label. + * + * @param tabIndex The tab index to get a view for. + * + * @return The view for the tab index. + */ + protected View getTextViewForTab(int tabIndex) + { + return null; + } + + /** + * This method returns the tab height, including insets, for the given index + * and fontheight. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param tabIndex The index of the tab to calculate. + * @param fontHeight The font height. + * + * @return This tab's height. + */ + protected int calculateTabHeight(int tabPlacement, int tabIndex, + int fontHeight) + { + Icon icon = getIconForTab(tabIndex); + Insets insets = getTabInsets(tabPlacement, tabIndex); + + if (icon != null) + { + Rectangle vr = new Rectangle(); + Rectangle ir = new Rectangle(); + Rectangle tr = new Rectangle(); + layoutLabel(tabPlacement, getFontMetrics(), tabIndex, + tabPane.getTitleAt(tabIndex), icon, vr, ir, tr, + tabIndex == tabPane.getSelectedIndex()); + calcRect = tr.union(ir); + } + else + calcRect.height = fontHeight; + + calcRect.height += insets.top + insets.bottom; + return calcRect.height; + } + + /** + * This method returns the max tab height. + * + * @param tabPlacement The JTabbedPane's tab placement. + * + * @return The maximum tab height. + */ + protected int calculateMaxTabHeight(int tabPlacement) + { + maxTabHeight = 0; + + FontMetrics fm = getFontMetrics(); + int fontHeight = fm.getHeight(); + + for (int i = 0; i < tabPane.getTabCount(); i++) + maxTabHeight = Math.max(calculateTabHeight(tabPlacement, i, fontHeight), + maxTabHeight); + + return maxTabHeight; + } + + /** + * This method calculates the tab width, including insets, for the given tab + * index and font metrics. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param tabIndex The tab index to calculate for. + * @param metrics The font's metrics. + * + * @return The tab width for the given index. + */ + protected int calculateTabWidth(int tabPlacement, int tabIndex, + FontMetrics metrics) + { + Icon icon = getIconForTab(tabIndex); + Insets insets = getTabInsets(tabPlacement, tabIndex); + + if (icon != null) + { + Rectangle vr = new Rectangle(); + Rectangle ir = new Rectangle(); + Rectangle tr = new Rectangle(); + layoutLabel(tabPlacement, getFontMetrics(), tabIndex, + tabPane.getTitleAt(tabIndex), icon, vr, ir, tr, + tabIndex == tabPane.getSelectedIndex()); + calcRect = tr.union(ir); + } + else + calcRect.width = metrics.stringWidth(tabPane.getTitleAt(tabIndex)); + + calcRect.width += insets.left + insets.right; + return calcRect.width; + } + + /** + * This method calculates the max tab width. + * + * @param tabPlacement The JTabbedPane's tab placement. + * + * @return The maximum tab width. + */ + protected int calculateMaxTabWidth(int tabPlacement) + { + maxTabWidth = 0; + + FontMetrics fm = getFontMetrics(); + + for (int i = 0; i < tabPane.getTabCount(); i++) + maxTabWidth = Math.max(calculateTabWidth(tabPlacement, i, fm), + maxTabWidth); + + return maxTabWidth; + } + + /** + * This method calculates the tab area height, including insets, for the + * given amount of runs and tab height. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param horizRunCount The number of runs. + * @param maxTabHeight The max tab height. + * + * @return The tab area height. + */ + protected int calculateTabAreaHeight(int tabPlacement, int horizRunCount, + int maxTabHeight) + { + Insets insets = getTabAreaInsets(tabPlacement); + int tabAreaHeight = horizRunCount * maxTabHeight + - (horizRunCount - 1) * tabRunOverlay; + + tabAreaHeight += insets.top + insets.bottom; + + return tabAreaHeight; + } + + /** + * This method calculates the tab area width, including insets, for the + * given amount of runs and tab width. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param vertRunCount The number of runs. + * @param maxTabWidth The max tab width. + * + * @return The tab area width. + */ + protected int calculateTabAreaWidth(int tabPlacement, int vertRunCount, + int maxTabWidth) + { + Insets insets = getTabAreaInsets(tabPlacement); + int tabAreaWidth = vertRunCount * maxTabWidth + - (vertRunCount - 1) * tabRunOverlay; + + tabAreaWidth += insets.left + insets.right; + + return tabAreaWidth; + } + + /** + * This method returns the tab insets appropriately rotated. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param tabIndex The tab index. + * + * @return The tab insets for the given index. + */ + protected Insets getTabInsets(int tabPlacement, int tabIndex) + { + Insets target = new Insets(0, 0, 0, 0); + rotateInsets(tabInsets, target, tabPlacement); + return target; + } + + /** + * This method returns the selected tab pad insets appropriately rotated. + * + * @param tabPlacement The JTabbedPane's tab placement. + * + * @return The selected tab pad insets. + */ + protected Insets getSelectedTabPadInsets(int tabPlacement) + { + Insets target = new Insets(0, 0, 0, 0); + rotateInsets(selectedTabPadInsets, target, tabPlacement); + return target; + } + + /** + * This method returns the tab area insets appropriately rotated. + * + * @param tabPlacement The JTabbedPane's tab placement. + * + * @return The tab area insets. + */ + protected Insets getTabAreaInsets(int tabPlacement) + { + Insets target = new Insets(0, 0, 0, 0); + rotateInsets(tabAreaInsets, target, tabPlacement); + return target; + } + + /** + * This method returns the content border insets appropriately rotated. + * + * @param tabPlacement The JTabbedPane's tab placement. + * + * @return The content border insets. + */ + protected Insets getContentBorderInsets(int tabPlacement) + { + Insets target = new Insets(0, 0, 0, 0); + rotateInsets(contentBorderInsets, target, tabPlacement); + return target; + } + + /** + * This method returns the fontmetrics for the font of the JTabbedPane. + * + * @return The font metrics for the JTabbedPane. + */ + protected FontMetrics getFontMetrics() + { + FontMetrics fm = tabPane.getToolkit().getFontMetrics(tabPane.getFont()); + return fm; + } + + /** + * This method navigates from the selected tab into the given direction. As + * a result, a new tab will be selected (if possible). + * + * @param direction The direction to navigate in. + */ + protected void navigateSelectedTab(int direction) + { + int tabPlacement = tabPane.getTabPlacement(); + if (tabPlacement == SwingConstants.TOP + || tabPlacement == SwingConstants.BOTTOM) + { + if (direction == SwingConstants.WEST) + selectPreviousTabInRun(tabPane.getSelectedIndex()); + else if (direction == SwingConstants.EAST) + selectNextTabInRun(tabPane.getSelectedIndex()); + + else + { + int offset = getTabRunOffset(tabPlacement, tabPane.getTabCount(), + tabPane.getSelectedIndex(), + (tabPlacement == SwingConstants.RIGHT) + ? true : false); + selectAdjacentRunTab(tabPlacement, tabPane.getSelectedIndex(), + offset); + } + } + if (tabPlacement == SwingConstants.LEFT + || tabPlacement == SwingConstants.RIGHT) + { + if (direction == SwingConstants.NORTH) + selectPreviousTabInRun(tabPane.getSelectedIndex()); + else if (direction == SwingConstants.SOUTH) + selectNextTabInRun(tabPane.getSelectedIndex()); + else + { + int offset = getTabRunOffset(tabPlacement, tabPane.getTabCount(), + tabPane.getSelectedIndex(), + (tabPlacement == SwingConstants.RIGHT) + ? true : false); + selectAdjacentRunTab(tabPlacement, tabPane.getSelectedIndex(), + offset); + } + } + } + + /** + * This method selects the next tab in the run. + * + * @param current The current selected index. + */ + protected void selectNextTabInRun(int current) + { + tabPane.setSelectedIndex(getNextTabIndexInRun(tabPane.getTabCount(), + current)); + } + + /** + * This method selects the previous tab in the run. + * + * @param current The current selected index. + */ + protected void selectPreviousTabInRun(int current) + { + tabPane.setSelectedIndex(getPreviousTabIndexInRun(tabPane.getTabCount(), + current)); + } + + /** + * This method selects the next tab (regardless of runs). + * + * @param current The current selected index. + */ + protected void selectNextTab(int current) + { + tabPane.setSelectedIndex(getNextTabIndex(current)); + } + + /** + * This method selects the previous tab (regardless of runs). + * + * @param current The current selected index. + */ + protected void selectPreviousTab(int current) + { + tabPane.setSelectedIndex(getPreviousTabIndex(current)); + } + + /** + * This method selects the correct tab given an offset from the current tab + * index. If the tab placement is TOP or BOTTOM, the offset will be in the + * y direction, otherwise, it will be in the x direction. A new coordinate + * will be found by adding the offset to the current location of the tab. + * The tab that the new location will be selected. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param tabIndex The tab to start from. + * @param offset The coordinate offset. + */ + protected void selectAdjacentRunTab(int tabPlacement, int tabIndex, + int offset) + { + int x = rects[tabIndex].x + rects[tabIndex].width / 2; + int y = rects[tabIndex].y + rects[tabIndex].height / 2; + + switch (tabPlacement) + { + case SwingConstants.TOP: + case SwingConstants.BOTTOM: + y += offset; + break; + case SwingConstants.RIGHT: + case SwingConstants.LEFT: + x += offset; + break; + } + + int index = tabForCoordinate(tabPane, x, y); + if (index != -1) + tabPane.setSelectedIndex(index); + } + + // This method is called when you press up/down to cycle through tab runs. + // it returns the distance (between the two runs' x/y position. + // where one run is the current selected run and the other run is the run in the + // direction of the scroll (dictated by the forward flag) + // the offset is an absolute value of the difference + + /** + * This method calculates the offset distance for use in + * selectAdjacentRunTab. The offset returned will be a difference in the y + * coordinate between the run in the desired direction and the current run + * (for tabPlacement in TOP or BOTTOM). Use x coordinate for LEFT and + * RIGHT. + * + * @param tabPlacement The JTabbedPane's tab placement. + * @param tabCount The number of tabs. + * @param tabIndex The starting index. + * @param forward If forward, the run in the desired direction will be the + * next run. + * + * @return The offset between the two runs. + */ + protected int getTabRunOffset(int tabPlacement, int tabCount, int tabIndex, + boolean forward) + { + int currRun = getRunForTab(tabCount, tabIndex); + int offset; + int nextRun = (forward) ? getNextTabRun(currRun) : getPreviousTabRun(currRun); + if (tabPlacement == SwingConstants.TOP + || tabPlacement == SwingConstants.BOTTOM) + offset = rects[lastTabInRun(tabCount, nextRun)].y + - rects[lastTabInRun(tabCount, currRun)].y; + else + offset = rects[lastTabInRun(tabCount, nextRun)].x + - rects[lastTabInRun(tabCount, currRun)].x; + return offset; + } + + /** + * This method returns the previous tab index. + * + * @param base The index to start from. + * + * @return The previous tab index. + */ + protected int getPreviousTabIndex(int base) + { + base--; + if (base < 0) + return tabPane.getTabCount() - 1; + return base; + } + + /** + * This method returns the next tab index. + * + * @param base The index to start from. + * + * @return The next tab index. + */ + protected int getNextTabIndex(int base) + { + base++; + if (base == tabPane.getTabCount()) + return 0; + return base; + } + + /** + * This method returns the next tab index in the run. If the next index is + * out of this run, it will return the starting tab index for the run. + * + * @param tabCount The number of tabs. + * @param base The index to start from. + * + * @return The next tab index in the run. + */ + protected int getNextTabIndexInRun(int tabCount, int base) + { + int index = getNextTabIndex(base); + int run = getRunForTab(tabCount, base); + if (index == lastTabInRun(tabCount, run) + 1) + index = lastTabInRun(tabCount, getPreviousTabRun(run)) + 1; + return getNextTabIndex(base); + } + + /** + * This method returns the previous tab index in the run. If the previous + * index is out of this run, it will return the last index for the run. + * + * @param tabCount The number of tabs. + * @param base The index to start from. + * + * @return The previous tab index in the run. + */ + protected int getPreviousTabIndexInRun(int tabCount, int base) + { + int index = getPreviousTabIndex(base); + int run = getRunForTab(tabCount, base); + if (index == lastTabInRun(tabCount, getPreviousTabRun(run))) + index = lastTabInRun(tabCount, run); + return getPreviousTabIndex(base); + } + + /** + * This method returns the index of the previous run. + * + * @param baseRun The run to start from. + * + * @return The index of the previous run. + */ + protected int getPreviousTabRun(int baseRun) + { + if (getTabRunCount(tabPane) == 1) + return 1; + + int prevRun = --baseRun; + if (prevRun < 0) + prevRun = getTabRunCount(tabPane) - 1; + return prevRun; + } + + /** + * This method returns the index of the next run. + * + * @param baseRun The run to start from. + * + * @return The index of the next run. + */ + protected int getNextTabRun(int baseRun) + { + if (getTabRunCount(tabPane) == 1) + return 1; + + int nextRun = ++baseRun; + if (nextRun == getTabRunCount(tabPane)) + nextRun = 0; + return nextRun; + } + + /** + * This method rotates the insets given a direction to rotate them in. + * Target placement should be one of TOP, LEFT, BOTTOM, RIGHT. The rotated + * insets will be stored in targetInsets. Passing in TOP as the direction + * does nothing. Passing in LEFT switches top and left, right and bottom. + * Passing in BOTTOM switches top and bottom. Passing in RIGHT switches top + * for left, left for bottom, bottom for right, and right for top. + * + * @param topInsets The reference insets. + * @param targetInsets An Insets object to store the new insets. + * @param targetPlacement The rotation direction. + */ + protected static void rotateInsets(Insets topInsets, Insets targetInsets, + int targetPlacement) + { + // Sun's version will happily throw an NPE if params are null, + // so I won't check it either. + switch (targetPlacement) + { + case SwingConstants.TOP: + targetInsets.top = topInsets.top; + targetInsets.left = topInsets.left; + targetInsets.right = topInsets.right; + targetInsets.bottom = topInsets.bottom; + break; + case SwingConstants.LEFT: + targetInsets.left = topInsets.top; + targetInsets.top = topInsets.left; + targetInsets.right = topInsets.bottom; + targetInsets.bottom = topInsets.right; + break; + case SwingConstants.BOTTOM: + targetInsets.top = topInsets.bottom; + targetInsets.bottom = topInsets.top; + targetInsets.left = topInsets.left; + targetInsets.right = topInsets.right; + break; + case SwingConstants.RIGHT: + targetInsets.top = topInsets.left; + targetInsets.left = topInsets.bottom; + targetInsets.bottom = topInsets.right; + targetInsets.right = topInsets.top; + break; + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTableHeaderUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTableHeaderUI.java new file mode 100644 index 0000000..700b406 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTableHeaderUI.java @@ -0,0 +1,224 @@ +/* BasicTableHeaderUI.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.awt.event.MouseEvent; + +import javax.swing.CellRendererPane; +import javax.swing.JComponent; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.border.Border; +import javax.swing.event.MouseInputListener; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.TableHeaderUI; +import javax.swing.table.JTableHeader; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import javax.swing.table.TableColumnModel; + +public class BasicTableHeaderUI + extends TableHeaderUI +{ + + public static ComponentUI createUI(JComponent h) + { + return new BasicTableHeaderUI(); + } + + protected JTableHeader header; + protected MouseInputListener mouseInputListener; + protected CellRendererPane rendererPane; + protected Border cellBorder; + + class MouseInputHandler + implements MouseInputListener + { + public void mouseClicked(MouseEvent e) {} + public void mouseDragged(MouseEvent e) {} + public void mouseEntered(MouseEvent e) {} + public void mouseExited(MouseEvent e) {} + public void mouseMoved(MouseEvent e) {} + public void mousePressed(MouseEvent e) {} + public void mouseReleased(MouseEvent e) {} + } + + protected MouseInputListener createMouseInputListener() + { + return new MouseInputHandler(); + } + + public BasicTableHeaderUI() + { + mouseInputListener = createMouseInputListener(); + } + + protected void installDefaults() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + header.setBackground(defaults.getColor("TableHeader.background")); + header.setForeground(defaults.getColor("TableHeader.foreground")); + header.setFont(defaults.getFont("TableHeader.font")); + cellBorder = defaults.getBorder("TableHeader.cellBorder"); + } + + protected void installKeyboardActions() + { + } + + protected void installListeners() + { + header.addMouseListener(mouseInputListener); + } + + public void installUI(JComponent c) + { + header = (JTableHeader) c; + installDefaults(); + installKeyboardActions(); + installListeners(); + } + + protected void uninstallDefaults() + { + header.setBackground(null); + header.setForeground(null); + header.setFont(null); + } + + protected void uninstallKeyboardActions() + { + } + + protected void uninstallListeners() + { + header.removeMouseListener(mouseInputListener); + } + + public void uninstallUI(JComponent c) + { + uninstallListeners(); + uninstallKeyboardActions(); + uninstallDefaults(); + } + + public void paint(Graphics gfx, JComponent c) + { + TableColumnModel cmod = header.getColumnModel(); + int ncols = cmod.getColumnCount(); + if (ncols == 0) + return; + + Rectangle clip = gfx.getClipBounds(); + TableCellRenderer defaultRend = header.getDefaultRenderer(); + + for (int i = 0; i < ncols; ++i) + { + Rectangle bounds = header.getHeaderRect(i); + if (bounds.intersects(clip)) + { + TableColumn col = cmod.getColumn(i); + TableCellRenderer rend = col.getHeaderRenderer(); + if (rend == null) + rend = defaultRend; + Object val = col.getHeaderValue(); + Component comp = rend.getTableCellRendererComponent(header.getTable(), + val, + false, // isSelected + false, // isFocused + -1, i); + comp.setFont(header.getFont()); + comp.setBackground(header.getBackground()); + comp.setForeground(header.getForeground()); + if (comp instanceof JComponent) + ((JComponent)comp).setBorder(cellBorder); + gfx.translate(bounds.x, bounds.y); + comp.setSize(bounds.width, bounds.height); + comp.setLocation(0,0); + comp.paint(gfx); + gfx.translate(-bounds.x, -bounds.y); + } + } + + } + + public Dimension getPreferredSize(JComponent c) + { + TableColumnModel cmod = header.getColumnModel(); + TableCellRenderer defaultRend = header.getDefaultRenderer(); + int ncols = cmod.getColumnCount(); + Dimension ret = new Dimension(0,0); + int spacing = 0; + + if (header.getTable() != null + && header.getTable().getIntercellSpacing() != null) + spacing = header.getTable().getIntercellSpacing().width; + + for (int i = 0; i < ncols; ++i) + { + TableColumn col = cmod.getColumn(i); + TableCellRenderer rend = col.getHeaderRenderer(); + if (rend == null) + rend = defaultRend; + Object val = col.getHeaderValue(); + Component comp = rend.getTableCellRendererComponent(header.getTable(), + val, + false, // isSelected + false, // isFocused + -1, i); + comp.setFont(header.getFont()); + comp.setBackground(header.getBackground()); + comp.setForeground(header.getForeground()); + if (comp instanceof JComponent) + ((JComponent)comp).setBorder(cellBorder); + + Dimension d = comp.getPreferredSize(); + ret.width += spacing; + ret.height = Math.max(d.height, ret.height); + } + ret.width = cmod.getTotalColumnWidth(); + return ret; + } + + +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTableUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTableUI.java new file mode 100644 index 0000000..7787436 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTableUI.java @@ -0,0 +1,398 @@ +/* BasicTableUI.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseEvent; + +import javax.swing.BorderFactory; +import javax.swing.CellRendererPane; +import javax.swing.JComponent; +import javax.swing.JTable; +import javax.swing.ListSelectionModel; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.border.Border; +import javax.swing.event.MouseInputListener; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.TableUI; +import javax.swing.table.TableCellRenderer; +import javax.swing.table.TableColumn; +import javax.swing.table.TableColumnModel; + +public class BasicTableUI + extends TableUI +{ + public static ComponentUI createUI(JComponent comp) + { + return new BasicTableUI(); + } + + protected FocusListener focusListener; + protected KeyListener keyListener; + protected MouseInputListener mouseInputListener; + protected CellRendererPane rendererPane; + protected JTable table; + + /** The normal cell border. */ + Border cellBorder; + + /** The cell border for selected/highlighted cells. */ + Border highlightCellBorder; + + class FocusHandler implements FocusListener + { + public void focusGained(FocusEvent e) + { + } + public void focusLost(FocusEvent e) + { + } + } + + class KeyHandler implements KeyListener + { + public void keyPressed(KeyEvent e) + { + } + public void keyReleased(KeyEvent e) + { + } + public void keyTyped(KeyEvent e) + { + } + } + + class MouseInputHandler implements MouseInputListener + { + Point begin, curr; + + private void updateSelection(boolean controlPressed) + { + if (table.getRowSelectionAllowed()) + { + int lo_row = table.rowAtPoint(begin); + int hi_row = table.rowAtPoint(curr); + ListSelectionModel rowModel = table.getSelectionModel(); + if (lo_row != -1 && hi_row != -1) + { + if (controlPressed && rowModel.getSelectionMode() + != ListSelectionModel.SINGLE_SELECTION) + rowModel.addSelectionInterval(lo_row, hi_row); + else + rowModel.setSelectionInterval(lo_row, hi_row); + } + } + + if (table.getColumnSelectionAllowed()) + { + int lo_col = table.columnAtPoint(begin); + int hi_col = table.columnAtPoint(curr); + ListSelectionModel colModel = table.getColumnModel(). + getSelectionModel(); + if (lo_col != -1 && hi_col != -1) + { + if (controlPressed && colModel.getSelectionMode() != + ListSelectionModel.SINGLE_SELECTION) + colModel.addSelectionInterval(lo_col, hi_col); + else + colModel.setSelectionInterval(lo_col, hi_col); + } + } + } + + public void mouseClicked(MouseEvent e) + { + } + public void mouseDragged(MouseEvent e) + { + curr = new Point(e.getX(), e.getY()); + updateSelection(e.isControlDown()); + } + public void mouseEntered(MouseEvent e) + { + } + public void mouseExited(MouseEvent e) + { + } + public void mouseMoved(MouseEvent e) + { + } + public void mousePressed(MouseEvent e) + { + begin = new Point(e.getX(), e.getY()); + curr = new Point(e.getX(), e.getY()); + //if control is pressed and the cell is already selected, deselect it + if (e.isControlDown() && table. + isCellSelected(table.rowAtPoint(begin),table.columnAtPoint(begin))) + { + table.getSelectionModel(). + removeSelectionInterval(table.rowAtPoint(begin), + table.rowAtPoint(begin)); + table.getColumnModel().getSelectionModel(). + removeSelectionInterval(table.columnAtPoint(begin), + table.columnAtPoint(begin)); + } + else + updateSelection(e.isControlDown()); + + } + public void mouseReleased(MouseEvent e) + { + begin = null; + curr = null; + } + } + + protected FocusListener createFocusListener() + { + return new FocusHandler(); + } + protected KeyListener createKeyListener() + { + return new KeyHandler(); + } + protected MouseInputListener createMouseInputListener() + { + return new MouseInputHandler(); + } + + public Dimension getMaximumSize(JComponent comp) + { + return getPreferredSize(comp); + } + + public Dimension getMinimumSize(JComponent comp) + { + return getPreferredSize(comp); + } + + public Dimension getPreferredSize(JComponent comp) + { + int width = table.getColumnModel().getTotalColumnWidth(); + int height = table.getRowCount() * table.getRowHeight(); + return new Dimension(width, height); + } + + protected void installDefaults() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + table.setFont(defaults.getFont("Table.font")); + table.setGridColor(defaults.getColor("Table.gridColor")); + table.setForeground(defaults.getColor("Table.foreground")); + table.setBackground(defaults.getColor("Table.background")); + table.setSelectionForeground(defaults.getColor("Table.selectionForeground")); + table.setSelectionBackground(defaults.getColor("Table.selectionBackground")); + table.setOpaque(true); + + highlightCellBorder = defaults.getBorder("Table.focusCellHighlightBorder"); + cellBorder = BorderFactory.createEmptyBorder(1, 1, 1, 1); + } + protected void installKeyboardActions() + { + } + + protected void installListeners() + { + table.addFocusListener(focusListener); + table.addKeyListener(keyListener); + table.addMouseListener(mouseInputListener); + table.addMouseMotionListener(mouseInputListener); + } + + protected void uninstallDefaults() + { + // TODO: this method used to do the following which is not + // quite right (at least it breaks apps that run fine with the + // JDK): + // + // table.setFont(null); + // table.setGridColor(null); + // table.setForeground(null); + // table.setBackground(null); + // table.setSelectionForeground(null); + // table.setSelectionBackground(null); + // + // This would leave the component in a corrupt state, which is + // not acceptable. A possible solution would be to have component + // level defaults installed, that get overridden by the UI defaults + // and get restored in this method. I am not quite sure about this + // though. / Roman Kennke + } + + protected void uninstallKeyboardActions() + { + } + + protected void uninstallListeners() + { + table.removeFocusListener(focusListener); + table.removeKeyListener(keyListener); + table.removeMouseListener(mouseInputListener); + table.removeMouseMotionListener(mouseInputListener); + } + + public void installUI(JComponent comp) + { + table = (JTable)comp; + focusListener = createFocusListener(); + keyListener = createKeyListener(); + mouseInputListener = createMouseInputListener(); + installDefaults(); + installKeyboardActions(); + installListeners(); + } + + public void uninstallUI(JComponent c) + { + uninstallListeners(); + uninstallKeyboardActions(); + uninstallDefaults(); + } + + public void paint(Graphics gfx, JComponent ignored) + { + int ncols = table.getColumnCount(); + int nrows = table.getRowCount(); + if (nrows == 0 || ncols == 0) + return; + + Rectangle clip = gfx.getClipBounds(); + TableColumnModel cols = table.getColumnModel(); + + int height = table.getRowHeight(); + int x0 = 0, y0 = 0; + int x = x0; + int y = y0; + + Dimension gap = table.getIntercellSpacing(); + int ymax = clip.y + clip.height; + int xmax = clip.x + clip.width; + + // paint the cell contents + for (int c = 0; c < ncols && x < xmax; ++c) + { + y = y0; + TableColumn col = cols.getColumn(c); + int width = col.getWidth(); + int modelCol = col.getModelIndex(); + + for (int r = 0; r < nrows && y < ymax; ++r) + { + Rectangle bounds = new Rectangle(x, y, width, height); + if (bounds.intersects(clip)) + { + TableCellRenderer rend = table.getCellRenderer(r, c); + Component comp = table.prepareRenderer(rend, r, c); + gfx.translate(x, y); + comp.setBounds(new Rectangle(0, 0, width, height)); + // Set correct border on cell renderer. + if (comp instanceof JComponent) + { + if (table.isCellSelected(r, c)) + ((JComponent) comp).setBorder(highlightCellBorder); + else + ((JComponent) comp).setBorder(cellBorder); + } + comp.paint(gfx); + gfx.translate(-x, -y); + } + y += height; + if (gap != null) + y += gap.height; + } + x += width; + if (gap != null) + x += gap.width; + } + + // tighten up the x and y max bounds + ymax = y; + xmax = x; + + Color grid = table.getGridColor(); + + // paint vertical grid lines + if (grid != null && table.getShowVerticalLines()) + { + x = x0; + Color save = gfx.getColor(); + gfx.setColor(grid); + boolean paintedLine = false; + for (int c = 0; c < ncols && x < xmax; ++c) + { + x += cols.getColumn(c).getWidth();; + if (gap != null) + x += gap.width; + gfx.drawLine(x, y0, x, ymax); + paintedLine = true; + } + gfx.setColor(save); + } + + // paint horizontal grid lines + if (grid != null && table.getShowHorizontalLines()) + { + y = y0; + Color save = gfx.getColor(); + gfx.setColor(grid); + boolean paintedLine = false; + for (int r = 0; r < nrows && y < ymax; ++r) + { + y += height; + if (gap != null) + y += gap.height; + gfx.drawLine(x0, y, xmax, y); + paintedLine = true; + } + gfx.setColor(save); + } + + } + +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTextAreaUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTextAreaUI.java new file mode 100644 index 0000000..97b0ccb --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTextAreaUI.java @@ -0,0 +1,68 @@ +/* BasicTextAreaUI.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.text.Element; +import javax.swing.text.PlainView; +import javax.swing.text.View; + +public class BasicTextAreaUI extends BasicTextUI +{ + public static ComponentUI createUI(JComponent comp) + { + return new BasicTextAreaUI(); + } + + public BasicTextAreaUI() + { + } + + public View create(Element elem) + { + return new PlainView(elem); + } + + protected String getPropertyPrefix() + { + return "TextArea"; + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTextFieldUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTextFieldUI.java new file mode 100644 index 0000000..a300446 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTextFieldUI.java @@ -0,0 +1,80 @@ +/* BasicTextFieldUI.java + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.beans.PropertyChangeEvent; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.text.Element; +import javax.swing.text.FieldView; +import javax.swing.text.View; + +public class BasicTextFieldUI extends BasicTextUI +{ + public BasicTextFieldUI() + { + super(); + } + + public View create(Element elem) + { + return new FieldView(elem); + } + + public static ComponentUI createUI(JComponent c) + { + return new BasicTextFieldUI(); + } + + protected String getPropertyPrefix() + { + return "TextField"; + } + + public void installUI(JComponent c) + { + super.installUI(c); + } + + protected void propertyChange(PropertyChangeEvent event) + { + // Does nothing by default. + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTextPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTextPaneUI.java new file mode 100644 index 0000000..55d908e --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTextPaneUI.java @@ -0,0 +1,68 @@ +/* BasicTextPaneUI.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.text.Element; +import javax.swing.text.PlainView; +import javax.swing.text.View; + +public class BasicTextPaneUI extends BasicEditorPaneUI +{ + public BasicTextPaneUI() + { + // Do nothing here. + } + + public static ComponentUI createUI(JComponent comp) + { + return new BasicTextPaneUI(); + } + + public View create(Element elem) + { + return new PlainView(elem); + } + + protected String getPropertyPrefix() + { + return "TextPane"; + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTextUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTextUI.java new file mode 100644 index 0000000..dd0828e --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTextUI.java @@ -0,0 +1,635 @@ +/* BasicTextUI.java -- + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.Action; +import javax.swing.ActionMap; +import javax.swing.InputMap; +import javax.swing.JComponent; +import javax.swing.SwingUtilities; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.plaf.ActionMapUIResource; +import javax.swing.plaf.TextUI; +import javax.swing.plaf.UIResource; +import javax.swing.text.BadLocationException; +import javax.swing.text.Caret; +import javax.swing.text.DefaultCaret; +import javax.swing.text.DefaultEditorKit; +import javax.swing.text.DefaultHighlighter; +import javax.swing.text.Document; +import javax.swing.text.EditorKit; +import javax.swing.text.Element; +import javax.swing.text.Highlighter; +import javax.swing.text.JTextComponent; +import javax.swing.text.Keymap; +import javax.swing.text.PlainView; +import javax.swing.text.Position; +import javax.swing.text.View; +import javax.swing.text.ViewFactory; + + +public abstract class BasicTextUI extends TextUI + implements ViewFactory +{ + public static class BasicCaret extends DefaultCaret + implements UIResource + { + public BasicCaret() + { + } + } + + public static class BasicHighlighter extends DefaultHighlighter + implements UIResource + { + public BasicHighlighter() + { + } + } + + private class RootView extends View + { + private View view; + + public RootView() + { + super(null); + } + + // View methods. + + public ViewFactory getViewFactory() + { + // FIXME: Handle EditorKit somehow. + return BasicTextUI.this; + } + + public void setView(View v) + { + if (view != null) + view.setParent(null); + + if (v != null) + v.setParent(null); + + view = v; + } + + public Container getContainer() + { + return textComponent; + } + + public float getPreferredSpan(int axis) + { + if (view != null) + return view.getPreferredSpan(axis); + + return Integer.MAX_VALUE; + } + + public void paint(Graphics g, Shape s) + { + if (view != null) + view.paint(g, s); + } + + public Shape modelToView(int position, Shape a, Position.Bias bias) + throws BadLocationException + { + if (view == null) + return null; + + return ((PlainView) view).modelToView(position, a, bias).getBounds(); + } + + /** + * Notification about text insertions. These are forwarded to the + * real root view. + * + * @param ev the DocumentEvent describing the change + * @param shape the current allocation of the view's display + * @param vf the ViewFactory to use for creating new Views + */ + public void insertUpdate(DocumentEvent ev, Shape shape, ViewFactory vf) + { + view.insertUpdate(ev, shape, vf); + } + + /** + * Notification about text removals. These are forwarded to the + * real root view. + * + * @param ev the DocumentEvent describing the change + * @param shape the current allocation of the view's display + * @param vf the ViewFactory to use for creating new Views + */ + public void removeUpdate(DocumentEvent ev, Shape shape, ViewFactory vf) + { + view.removeUpdate(ev, shape, vf); + } + + /** + * Notification about text changes. These are forwarded to the + * real root view. + * + * @param ev the DocumentEvent describing the change + * @param shape the current allocation of the view's display + * @param vf the ViewFactory to use for creating new Views + */ + public void changedUpdate(DocumentEvent ev, Shape shape, ViewFactory vf) + { + view.changedUpdate(ev, shape, vf); + } + } + + class UpdateHandler implements PropertyChangeListener + { + public void propertyChange(PropertyChangeEvent event) + { + if (event.getPropertyName().equals("document")) + { + // Document changed. + modelChanged(); + } + } + } + + /** + * Listens for changes on the underlying model and forwards notifications + * to the View. This also updates the caret position of the text component. + * + * TODO: Maybe this should somehow be handled through EditorKits + */ + class DocumentHandler implements DocumentListener + { + /** + * Notification about a document change event. + * + * @param ev the DocumentEvent describing the change + */ + public void changedUpdate(DocumentEvent ev) + { + Dimension size = textComponent.getSize(); + rootView.changedUpdate(ev, new Rectangle(0, 0, size.width, size.height), + BasicTextUI.this); + } + + /** + * Notification about a document insert event. + * + * @param ev the DocumentEvent describing the insertion + */ + public void insertUpdate(DocumentEvent ev) + { + Dimension size = textComponent.getSize(); + rootView.insertUpdate(ev, new Rectangle(0, 0, size.width, size.height), + BasicTextUI.this); + int caretPos = textComponent.getCaretPosition(); + if (caretPos >= ev.getOffset()) + textComponent.setCaretPosition(caretPos + ev.getLength()); + } + + /** + * Notification about a document removal event. + * + * @param ev the DocumentEvent describing the removal + */ + public void removeUpdate(DocumentEvent ev) + { + Dimension size = textComponent.getSize(); + rootView.removeUpdate(ev, new Rectangle(0, 0, size.width, size.height), + BasicTextUI.this); + int caretPos = textComponent.getCaretPosition(); + if (caretPos >= ev.getOffset()) + textComponent.setCaretPosition(ev.getOffset()); + } + } + + static EditorKit kit = new DefaultEditorKit(); + + RootView rootView = new RootView(); + JTextComponent textComponent; + UpdateHandler updateHandler = new UpdateHandler(); + + /** The DocumentEvent handler. */ + DocumentHandler documentHandler = new DocumentHandler(); + + public BasicTextUI() + { + } + + protected Caret createCaret() + { + return new BasicCaret(); + } + + protected Highlighter createHighlighter() + { + return new BasicHighlighter(); + } + + protected final JTextComponent getComponent() + { + return textComponent; + } + + public void installUI(final JComponent c) + { + super.installUI(c); + c.setOpaque(true); + + textComponent = (JTextComponent) c; + + Document doc = textComponent.getDocument(); + if (doc == null) + { + doc = getEditorKit(textComponent).createDefaultDocument(); + textComponent.setDocument(doc); + } + + textComponent.addPropertyChangeListener(updateHandler); + modelChanged(); + + installDefaults(); + installListeners(); + installKeyboardActions(); + } + + protected void installDefaults() + { + Caret caret = textComponent.getCaret(); + if (caret == null) + { + caret = createCaret(); + textComponent.setCaret(caret); + } + + Highlighter highlighter = textComponent.getHighlighter(); + if (highlighter == null) + textComponent.setHighlighter(createHighlighter()); + + String prefix = getPropertyPrefix(); + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + textComponent.setBackground(defaults.getColor(prefix + ".background")); + textComponent.setForeground(defaults.getColor(prefix + ".foreground")); + textComponent.setMargin(defaults.getInsets(prefix + ".margin")); + textComponent.setBorder(defaults.getBorder(prefix + ".border")); + textComponent.setFont(defaults.getFont(prefix + ".font")); + + caret.setBlinkRate(defaults.getInt(prefix + ".caretBlinkRate")); + } + + private FocusListener focuslistener = new FocusListener() { + public void focusGained(FocusEvent e) + { + textComponent.repaint(); + } + public void focusLost(FocusEvent e) + { + textComponent.repaint(); + } + }; + + protected void installListeners() + { + textComponent.addFocusListener(focuslistener); + installDocumentListeners(); + } + + /** + * Installs the document listeners on the textComponent's model. + */ + private void installDocumentListeners() + { + Document doc = textComponent.getDocument(); + if (doc != null) + doc.addDocumentListener(documentHandler); + } + + /** + * Returns the name of the keymap for this type of TextUI. + * + * This is implemented so that the classname of this TextUI + * without the package prefix is returned. This way subclasses + * don't have to override this method. + * + * @return the name of the keymap for this TextUI + */ + protected String getKeymapName() + { + String fullClassName = getClass().getName(); + int index = fullClassName.lastIndexOf('.'); + String className = fullClassName.substring(index + 1); + return className; + } + + protected Keymap createKeymap() + { + String prefix = getPropertyPrefix(); + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + JTextComponent.KeyBinding[] bindings = + (JTextComponent.KeyBinding[]) defaults.get(prefix + ".keyBindings"); + if (bindings == null) + { + bindings = new JTextComponent.KeyBinding[0]; + defaults.put(prefix + ".keyBindings", bindings); + } + + Keymap km = JTextComponent.addKeymap(getKeymapName(), + JTextComponent.getKeymap(JTextComponent.DEFAULT_KEYMAP)); + JTextComponent.loadKeymap(km, bindings, textComponent.getActions()); + return km; + } + + protected void installKeyboardActions() + { + // load any bindings for the older Keymap interface + Keymap km = JTextComponent.getKeymap(getKeymapName()); + if (km == null) + km = createKeymap(); + textComponent.setKeymap(km); + + // load any bindings for the newer InputMap / ActionMap interface + SwingUtilities.replaceUIInputMap(textComponent, + JComponent.WHEN_FOCUSED, + getInputMap(JComponent.WHEN_FOCUSED)); + SwingUtilities.replaceUIActionMap(textComponent, getActionMap()); + } + + InputMap getInputMap(int condition) + { + String prefix = getPropertyPrefix(); + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + switch (condition) + { + case JComponent.WHEN_IN_FOCUSED_WINDOW: + // FIXME: is this the right string? nobody seems to use it. + return (InputMap) defaults.get(prefix + ".windowInputMap"); + case JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT: + return (InputMap) defaults.get(prefix + ".ancestorInputMap"); + default: + case JComponent.WHEN_FOCUSED: + return (InputMap) defaults.get(prefix + ".focusInputMap"); + } + } + + ActionMap getActionMap() + { + String prefix = getPropertyPrefix(); + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + ActionMap am = (ActionMap) defaults.get(prefix + ".actionMap"); + if (am == null) + { + am = createActionMap(); + defaults.put(prefix + ".actionMap", am); + } + return am; + } + + ActionMap createActionMap() + { + Action[] actions = textComponent.getActions(); + ActionMap am = new ActionMapUIResource(); + for (int i = 0; i < actions.length; ++i) + { + String name = (String) actions[i].getValue(Action.NAME); + if (name != null) + am.put(name, actions[i]); + } + return am; + } + + public void uninstallUI(final JComponent component) + { + super.uninstallUI(component); + rootView.setView(null); + + textComponent.removePropertyChangeListener(updateHandler); + + uninstallDefaults(); + uninstallListeners(); + uninstallKeyboardActions(); + + textComponent = null; + } + + protected void uninstallDefaults() + { + // Do nothing here. + } + + protected void uninstallListeners() + { + textComponent.removeFocusListener(focuslistener); + } + + protected void uninstallKeyboardActions() + { + // Do nothing here. + } + + protected abstract String getPropertyPrefix(); + + public Dimension getPreferredSize(JComponent c) + { + View v = getRootView(textComponent); + + float w = v.getPreferredSpan(View.X_AXIS); + float h = v.getPreferredSpan(View.Y_AXIS); + + return new Dimension((int) w, (int) h); + } + + /** + * Returns the maximum size for text components that use this UI. + * + * This returns (Integer.MAX_VALUE, Integer.MAX_VALUE). + * + * @return the maximum size for text components that use this UI + */ + public Dimension getMaximumSize(JComponent c) + { + // Sun's implementation returns Integer.MAX_VALUE here, so do we. + return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); + } + + public final void paint(Graphics g, JComponent c) + { + paintSafely(g); + } + + protected void paintSafely(Graphics g) + { + Caret caret = textComponent.getCaret(); + Highlighter highlighter = textComponent.getHighlighter(); + + if (textComponent.isOpaque()) + paintBackground(g); + + if (highlighter != null + && textComponent.getSelectionStart() != textComponent.getSelectionEnd()) + highlighter.paint(g); + + rootView.paint(g, getVisibleEditorRect()); + + if (caret != null && textComponent.hasFocus()) + caret.paint(g); + } + + protected void paintBackground(Graphics g) + { + g.setColor(textComponent.getBackground()); + g.fillRect(0, 0, textComponent.getWidth(), textComponent.getHeight()); + } + + public void damageRange(JTextComponent t, int p0, int p1) + { + damageRange(t, p0, p1, null, null); + } + + public void damageRange(JTextComponent t, int p0, int p1, + Position.Bias firstBias, Position.Bias secondBias) + { + } + + public EditorKit getEditorKit(JTextComponent t) + { + return kit; + } + + public int getNextVisualPositionFrom(JTextComponent t, int pos, + Position.Bias b, int direction, + Position.Bias[] biasRet) + throws BadLocationException + { + return 0; + } + + public View getRootView(JTextComponent t) + { + return rootView; + } + + public Rectangle modelToView(JTextComponent t, int pos) + throws BadLocationException + { + return modelToView(t, pos, Position.Bias.Forward); + } + + public Rectangle modelToView(JTextComponent t, int pos, Position.Bias bias) + throws BadLocationException + { + return rootView.modelToView(pos, getVisibleEditorRect(), bias).getBounds(); + } + + public int viewToModel(JTextComponent t, Point pt) + { + return viewToModel(t, pt, null); + } + + public int viewToModel(JTextComponent t, Point pt, Position.Bias[] biasReturn) + { + return 0; + } + + public View create(Element elem) + { + // Subclasses have to implement this to get this functionality. + return null; + } + + public View create(Element elem, int p0, int p1) + { + // Subclasses have to implement this to get this functionality. + return null; + } + + protected Rectangle getVisibleEditorRect() + { + int width = textComponent.getWidth(); + int height = textComponent.getHeight(); + + if (width <= 0 || height <= 0) + return null; + + Insets insets = textComponent.getInsets(); + return new Rectangle(insets.left, insets.top, + width - insets.left + insets.right, + height - insets.top + insets.bottom); + } + + protected final void setView(View view) + { + rootView.setView(view); + view.setParent(rootView); + } + + protected void modelChanged() + { + if (textComponent == null || rootView == null) + return; + ViewFactory factory = rootView.getViewFactory(); + if (factory == null) + return; + Document doc = textComponent.getDocument(); + if (doc == null) + return; + installDocumentListeners(); + Element elem = doc.getDefaultRootElement(); + if (elem == null) + return; + setView(factory.create(elem)); + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicToggleButtonUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicToggleButtonUI.java new file mode 100644 index 0000000..84509ad --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicToggleButtonUI.java @@ -0,0 +1,62 @@ +/* BasicToggleButtonUI.java + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; + +public class BasicToggleButtonUI extends BasicButtonUI +{ + public static ComponentUI createUI(final JComponent component) + { + return new BasicToggleButtonUI(); + } + + /** + * Returns the prefix for the UI defaults property for this UI class. + * This is 'ToggleButton' for this class. + * + * @return the prefix for the UI defaults property + */ + protected String getPropertyPrefix() + { + return "ToggleButton"; + } +} + diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicToolBarSeparatorUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicToolBarSeparatorUI.java new file mode 100644 index 0000000..db29fdc --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicToolBarSeparatorUI.java @@ -0,0 +1,127 @@ +/* BasicToolBarSeparatorUI.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Dimension; +import java.awt.Graphics; + +import javax.swing.JComponent; +import javax.swing.JSeparator; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.ComponentUI; + +/** + * The Basic Look and Feel UI delegate for Separator. + */ +public class BasicToolBarSeparatorUI extends BasicSeparatorUI +{ + private transient Dimension size; + + /** + * Creates a new UI delegate for the given JComponent. + * + * @param c The JComponent to create a delegate for. + * + * @return A new BasicToolBarSeparatorUI. + */ + public static ComponentUI createUI(JComponent c) + { + return new BasicToolBarSeparatorUI(); + } + + /** + * This method installs the defaults that are given by the Basic L&F. + * + * @param s The Separator that is being installed. + */ + protected void installDefaults(JSeparator s) + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + size = defaults.getDimension("ToolBar.separatorSize"); + } + + /** + * This method does nothing as a Separator is just blank space. + * + * @param g The Graphics object to paint with + * @param c The JComponent to paint. + */ + public void paint(Graphics g, JComponent c) + { + // Do nothing. + } + + /** + * This method returns the preferred size of the JComponent. + * + * @param c The JComponent to measure. + * + * @return The preferred size. + */ + public Dimension getPreferredSize(JComponent c) + { + return size; + } + + /** + * This method returns the minimum size of the JComponent. + * + * @param c The JComponent to measure. + * + * @return The minimum size. + */ + public Dimension getMinimumSize(JComponent c) + { + return size; + } + + /** + * This method returns the maximum size of the JComponent. + * + * @param c The JComponent to measure. + * + * @return The maximum size. + */ + public Dimension getMaximumSize(JComponent c) + { + return size; + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicToolBarUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicToolBarUI.java new file mode 100644 index 0000000..bc655a2 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicToolBarUI.java @@ -0,0 +1,1435 @@ +/* BasicToolBarUI.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Window; +import java.awt.event.ContainerEvent; +import java.awt.event.ContainerListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.MouseEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.Hashtable; + +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JToolBar; +import javax.swing.RootPaneContainer; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.border.Border; +import javax.swing.event.MouseInputListener; +import javax.swing.plaf.BorderUIResource.EtchedBorderUIResource; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.ToolBarUI; +import javax.swing.plaf.UIResource; + +/** + * This is the Basic Look and Feel UI class for JToolBar. + */ +public class BasicToolBarUI extends ToolBarUI implements SwingConstants +{ + /** Static owner of all DragWindows. + * This is package-private to avoid an accessor method. */ + static JFrame owner = new JFrame(); + + /** The border used when the JToolBar is in nonrollover mode. */ + private static Border nonRolloverBorder; + + /** The border used when the JToolBar is in rollover mode. */ + private static Border rolloverBorder; + + /** The last known BorderLayout constraint before floating. */ + protected String constraintBeforeFloating; + + /** The last known orientation of the JToolBar before floating. + * This is package-private to avoid an accessor method. */ + int lastGoodOrientation; + + /** The color of the border when it is dockable. */ + protected Color dockingBorderColor; + + /** The background color of the JToolBar when it is dockable. */ + protected Color dockingColor; + + /** The docking listener responsible for mouse events on the JToolBar. */ + protected MouseInputListener dockingListener; + + /** The window used for dragging the JToolBar. */ + protected BasicToolBarUI.DragWindow dragWindow; + + /** The color of the border when it is not dockable. */ + protected Color floatingBorderColor; + + /** The background color of the JToolBar when it is not dockable. */ + protected Color floatingColor; + + /** The index of the focused component. */ + protected int focusedCompIndex; + + /** The PropertyChangeListener for the JToolBar. */ + protected PropertyChangeListener propertyListener; + + /** The JToolBar this UI delegate is responsible for. */ + protected JToolBar toolBar; + + /** The Container listener for the JToolBar. */ + protected ContainerListener toolBarContListener; + + /** The Focus listener for the JToolBar. */ + protected FocusListener toolBarFocusListener; + + /** + * The floating window that is responsible for holding the JToolBar when it + * is dragged outside of its original parent. + */ + private transient Window floatFrame; + + /** The original parent of the JToolBar. + * This is package-private to avoid an accessor method. */ + transient Container origParent; + + /** A hashtable of components and their original borders. + * This is package-private to avoid an accessor method. */ + transient Hashtable borders; + + /** A window listener for the floatable frame. */ + private transient WindowListener windowListener; + + /** A set of cached bounds of the JToolBar. + * This is package-private to avoid an accessor method. */ + transient Dimension cachedBounds; + + /** The cached orientation of the JToolBar. + * This is package-private to avoid an accessor method. */ + transient int cachedOrientation; + + /** + * This method creates a new <code>BasicToolBarUI</code> object for the given JToolBar. + */ + public BasicToolBarUI() + { + // Do nothing here. + } + + /** + * This method returns whether the JToolBar can dock at the given position. + * + * @param c The component to try to dock in. + * @param p The position of the mouse cursor relative to the given + * component. + * + * @return Whether the JToolBar can dock. + */ + public boolean canDock(Component c, Point p) + { + return areaOfClick(c, p) != -1; + } + + /** + * This helper method returns the position of the JToolBar if it can dock. + * + * @param c The component to try to dock in. + * @param p The position of the mouse cursor relative to the given + * component. + * + * @return One of the SwingConstants directions or -1 if the JToolBar can't + * dock. + */ + private int areaOfClick(Component c, Point p) + { + // Has to dock in immediate parent, not eventual root container. + Rectangle pBounds = c.getBounds(); + + // XXX: In Sun's implementation, the space the toolbar has to dock is dependent on the size it had last. + Dimension d = toolBar.getSize(); + int limit = Math.min(d.width, d.height); + + // The order of checking is 1. top 2. bottom 3. left 4. right + if (! pBounds.contains(p)) + return -1; + + if (p.y < limit) + return SwingConstants.NORTH; + + if (p.y > (pBounds.height - limit)) + return SwingConstants.SOUTH; + + if (p.x < limit) + return SwingConstants.WEST; + + if (p.x > (pBounds.width - limit)) + return SwingConstants.EAST; + + return -1; + } + + /** + * This method creates a new DockingListener for the JToolBar. + * + * @return A new DockingListener for the JToolBar. + */ + protected MouseInputListener createDockingListener() + { + return new DockingListener(toolBar); + } + + /** + * This method creates a new DragWindow for the given JToolBar. + * + * @param toolbar The JToolBar to create a DragWindow for. + * + * @return A new DragWindow. + */ + protected BasicToolBarUI.DragWindow createDragWindow(JToolBar toolbar) + { + return new DragWindow(); + } + + /** + * This method creates a new floating frame for the JToolBar. By default, + * this UI uses createFloatingWindow instead. This method of creating a + * floating frame is deprecated. + * + * @param toolbar The JToolBar to create a floating frame for. + * + * @return A new floating frame. + */ + protected JFrame createFloatingFrame(JToolBar toolbar) + { + // FIXME: Though deprecated, this should still work. + return null; + } + + /** + * This method creates a new floating window for the JToolBar. This is the + * method used by default to create a floating container for the JToolBar. + * + * @param toolbar The JToolBar to create a floating window for. + * + * @return A new floating window. + */ + protected RootPaneContainer createFloatingWindow(JToolBar toolbar) + { + // This one is used by default though. + return new ToolBarDialog(); + } + + /** + * This method creates a new WindowListener for the JToolBar. + * + * @return A new WindowListener. + */ + protected WindowListener createFrameListener() + { + return new FrameListener(); + } + + /** + * This method creates a new nonRolloverBorder for JButtons when the + * JToolBar's rollover property is set to false. + * + * @return A new NonRolloverBorder. + */ + protected Border createNonRolloverBorder() + { + return new EtchedBorderUIResource(); + } + + /** + * This method creates a new PropertyChangeListener for the JToolBar. + * + * @return A new PropertyChangeListener. + */ + protected PropertyChangeListener createPropertyListener() + { + return new PropertyListener(); + } + + /** + * This method creates a new rollover border for JButtons when the + * JToolBar's rollover property is set to true. + * + * @return A new rollover border. + */ + protected Border createRolloverBorder() + { + return new EtchedBorderUIResource() + { + public void paintBorder(Component c, Graphics g, int x, int y, + int width, int height) + { + if (c instanceof JButton) + { + if (((JButton) c).getModel().isRollover()) + super.paintBorder(c, g, x, y, width, height); + } + } + }; + } + + /** + * This method creates a new Container listener for the JToolBar. + * + * @return A new Container listener. + */ + protected ContainerListener createToolBarContListener() + { + return new ToolBarContListener(); + } + + /** + * This method creates a new FocusListener for the JToolBar. + * + * @return A new FocusListener for the JToolBar. + */ + protected FocusListener createToolBarFocusListener() + { + return new ToolBarFocusListener(); + } + + /** + * This method creates a new UI delegate for the given JComponent. + * + * @param c The JComponent to create a UI delegate for. + * + * @return A new UI delegate. + */ + public static ComponentUI createUI(JComponent c) + { + return new BasicToolBarUI(); + } + + /** + * This method is called to drag the DragWindow around when the JToolBar is + * being dragged around. + * + * @param position The mouse cursor coordinates relative to the JToolBar. + * @param origin The screen position of the JToolBar. + */ + protected void dragTo(Point position, Point origin) + { + int loc = areaOfClick(origParent, + SwingUtilities.convertPoint(toolBar, position, + origParent)); + + if (loc != -1) + { + dragWindow.setBorderColor(dockingBorderColor); + dragWindow.setBackground(dockingColor); + } + else + { + dragWindow.setBorderColor(floatingBorderColor); + dragWindow.setBackground(floatingColor); + } + + int w = 0; + int h = 0; + + boolean tmp = ((loc == SwingConstants.NORTH) + || (loc == SwingConstants.SOUTH) || (loc == -1)); + + if (((cachedOrientation == SwingConstants.HORIZONTAL) && tmp) + || ((cachedOrientation == VERTICAL) && ! tmp)) + { + w = cachedBounds.width; + h = cachedBounds.height; + } + else + { + w = cachedBounds.height; + h = cachedBounds.width; + } + + Point p = dragWindow.getOffset(); + Insets insets = toolBar.getInsets(); + + dragWindow.setBounds((origin.x + position.x) - p.x + - ((insets.left + insets.right) / 2), + (origin.y + position.y) - p.y + - ((insets.top + insets.bottom) / 2), w, h); + + if (! dragWindow.isVisible()) + dragWindow.show(); + } + + /** + * This method is used at the end of a drag session to place the frame in + * either its original parent as a docked JToolBar or in its floating + * frame. + * + * @param position The position of the mouse cursor relative to the + * JToolBar. + * @param origin The screen position of the JToolBar before the drag session + * started. + */ + protected void floatAt(Point position, Point origin) + { + Point p = new Point(position); + int aoc = areaOfClick(origParent, + SwingUtilities.convertPoint(toolBar, p, origParent)); + + Container oldParent = toolBar.getParent(); + + oldParent.remove(toolBar); + oldParent.doLayout(); + oldParent.repaint(); + + Container newParent; + + if (aoc == -1) + newParent = ((RootPaneContainer) floatFrame).getContentPane(); + else + { + floatFrame.hide(); + newParent = origParent; + } + + String constraint; + switch (aoc) + { + case SwingConstants.EAST: + constraint = BorderLayout.EAST; + break; + case SwingConstants.NORTH: + constraint = BorderLayout.NORTH; + break; + case SwingConstants.SOUTH: + constraint = BorderLayout.SOUTH; + break; + case SwingConstants.WEST: + constraint = BorderLayout.WEST; + break; + default: + constraint = BorderLayout.CENTER; + break; + } + + int newOrientation = SwingConstants.HORIZONTAL; + if ((aoc != -1) + && ((aoc == SwingConstants.EAST) || (aoc == SwingConstants.WEST))) + newOrientation = SwingConstants.VERTICAL; + + if (aoc != -1) + { + constraintBeforeFloating = constraint; + lastGoodOrientation = newOrientation; + } + + newParent.add(toolBar, constraint); + + setFloating(aoc == -1, null); + toolBar.setOrientation(newOrientation); + + Insets insets = floatFrame.getInsets(); + Dimension dims = toolBar.getPreferredSize(); + p = dragWindow.getOffset(); + setFloatingLocation((position.x + origin.x) - p.x + - ((insets.left + insets.right) / 2), + (position.y + origin.y) - p.y + - ((insets.top + insets.bottom) / 2)); + + if (aoc == -1) + { + floatFrame.pack(); + floatFrame.setSize(dims.width + insets.left + insets.right, + dims.height + insets.top + insets.bottom); + floatFrame.show(); + } + + newParent.invalidate(); + newParent.validate(); + newParent.repaint(); + } + + /** + * This method returns the docking color. + * + * @return The docking color. + */ + public Color getDockingColor() + { + return dockingColor; + } + + /** + * This method returns the Color which is displayed when over a floating + * area. + * + * @return The color which is displayed when over a floating area. + */ + public Color getFloatingColor() + { + return floatingColor; + } + + /** + * This method returns the maximum size of the given JComponent for this UI. + * + * @param c The JComponent to find the maximum size for. + * + * @return The maximum size for this UI. + */ + public Dimension getMaximumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the minimum size of the given JComponent for this UI. + * + * @param c The JComponent to find a minimum size for. + * + * @return The minimum size for this UI. + */ + public Dimension getMinimumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the preferred size of the given JComponent for this + * UI. + * + * @param c The JComponent to find a preferred size for. + * + * @return The preferred size for this UI. + */ + public Dimension getPreferredSize(JComponent c) + { + return toolBar.getLayout().preferredLayoutSize(c); + } + + /** + * This method installs the needed components for the JToolBar. + */ + protected void installComponents() + { + floatFrame = (Window) createFloatingWindow(toolBar); + + dragWindow = createDragWindow(toolBar); + + cachedBounds = toolBar.getPreferredSize(); + cachedOrientation = toolBar.getOrientation(); + + nonRolloverBorder = createNonRolloverBorder(); + rolloverBorder = createRolloverBorder(); + + borders = new Hashtable(); + + fillHashtable(); + } + + /** + * This method installs the defaults as specified by the look and feel. + */ + protected void installDefaults() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + toolBar.setBorder(new ToolBarBorder()); + toolBar.setBackground(defaults.getColor("ToolBar.background")); + toolBar.setForeground(defaults.getColor("ToolBar.foreground")); + toolBar.setFont(defaults.getFont("ToolBar.font")); + + dockingBorderColor = defaults.getColor("ToolBar.dockingForeground"); + dockingColor = defaults.getColor("ToolBar.dockingBackground"); + + floatingBorderColor = defaults.getColor("ToolBar.floatingForeground"); + floatingColor = defaults.getColor("ToolBar.floatingBackground"); + } + + /** + * This method installs the keyboard actions for the JToolBar as specified + * by the look and feel. + */ + protected void installKeyboardActions() + { + // FIXME: implement. + } + + /** + * This method installs listeners for the JToolBar. + * + * @param toolbar The JToolBar to register listeners for. + */ + protected void installListeners(JToolBar toolbar) + { + dockingListener = createDockingListener(); + toolBar.addMouseListener(dockingListener); + toolBar.addMouseMotionListener(dockingListener); + + propertyListener = createPropertyListener(); + toolBar.addPropertyChangeListener(propertyListener); + + toolBarContListener = createToolBarContListener(); + toolBar.addContainerListener(toolBarContListener); + + windowListener = createFrameListener(); + floatFrame.addWindowListener(windowListener); + + toolBarFocusListener = createToolBarFocusListener(); + toolBar.addFocusListener(toolBarFocusListener); + } + + /** + * This method installs non rollover borders for each component inside the + * given JComponent. + * + * @param c The JComponent whose children need to have non rollover borders + * installed. + */ + protected void installNonRolloverBorders(JComponent c) + { + Component[] components = toolBar.getComponents(); + + for (int i = 0; i < components.length; i++) + setBorderToNonRollover(components[i]); + } + + /** + * This method installs normal (or their original) borders for each + * component inside the given JComponent. + * + * @param c The JComponent whose children need to have their original + * borders installed. + */ + protected void installNormalBorders(JComponent c) + { + Component[] components = toolBar.getComponents(); + + for (int i = 0; i < components.length; i++) + setBorderToNormal(components[i]); + } + + /** + * This method install rollover borders for each component inside the given + * JComponent. + * + * @param c The JComponent whose children need to have rollover borders + * installed. + */ + protected void installRolloverBorders(JComponent c) + { + Component[] components = toolBar.getComponents(); + + for (int i = 0; i < components.length; i++) + setBorderToRollover(components[i]); + } + + /** + * This method fills the borders hashtable with a list of components that + * are JButtons and their borders. + */ + private void fillHashtable() + { + Component[] c = toolBar.getComponents(); + + for (int i = 0; i < c.length; i++) + { + if (c[i] instanceof JButton) + { + // Don't really care about anything other than JButtons + JButton b = (JButton) c[i]; + + if (b.getBorder() != null) + borders.put(b, b.getBorder()); + } + } + } + + /** + * This method installs the UI for the given JComponent. + * + * @param c The JComponent to install a UI for. + */ + public void installUI(JComponent c) + { + super.installUI(c); + + if (c instanceof JToolBar) + { + toolBar = (JToolBar) c; + toolBar.setOpaque(true); + installDefaults(); + installComponents(); + installListeners(toolBar); + installKeyboardActions(); + } + } + + /** + * This method returns whether the JToolBar is floating. + * + * @return Whether the JToolBar is floating. + */ + public boolean isFloating() + { + return floatFrame.isVisible(); + } + + /** + * This method returns whether rollover borders have been set. + * + * @return Whether rollover borders have been set. + */ + public boolean isRolloverBorders() + { + return toolBar.isRollover(); + } + + /** + * This method navigates in the given direction giving focus to the next + * component in the given direction. + * + * @param direction The direction to give focus to. + */ + protected void navigateFocusedComp(int direction) + { + // FIXME: Implement. + } + + /** + * This method sets the border of the given component to a non rollover + * border. + * + * @param c The Component whose border needs to be set. + */ + protected void setBorderToNonRollover(Component c) + { + if (c instanceof JButton) + { + JButton b = (JButton) c; + b.setRolloverEnabled(false); + b.setBorder(nonRolloverBorder); + } + } + + /** + * This method sets the border of the given component to its original value. + * + * @param c The Component whose border needs to be set. + */ + protected void setBorderToNormal(Component c) + { + if (c instanceof JButton) + { + JButton b = (JButton) c; + Border border = (Border) borders.get(b); + b.setBorder(border); + } + } + + /** + * This method sets the border of the given component to a rollover border. + * + * @param c The Component whose border needs to be set. + */ + protected void setBorderToRollover(Component c) + { + if (c instanceof JButton) + { + JButton b = (JButton) c; + b.setRolloverEnabled(true); + b.setBorder(rolloverBorder); + } + } + + /** + * This method sets the docking color. + * + * @param c The docking color. + */ + public void setDockingColor(Color c) + { + dockingColor = c; + } + + /** + * This method sets the floating property for the JToolBar. + * + * @param b Whether the JToolBar is floating. + * @param p FIXME + */ + public void setFloating(boolean b, Point p) + { + // FIXME: use p for something. It's not location + // since we already have setFloatingLocation. + floatFrame.setVisible(b); + } + + /** + * This method sets the color displayed when the JToolBar is not in a + * dockable area. + * + * @param c The floating color. + */ + public void setFloatingColor(Color c) + { + floatingColor = c; + } + + /** + * This method sets the floating location of the JToolBar. + * + * @param x The x coordinate for the floating frame. + * @param y The y coordinate for the floating frame. + */ + public void setFloatingLocation(int x, int y) + { + // x,y are the coordinates of the new JFrame created to store the toolbar + // XXX: The floating location is bogus is not floating. + floatFrame.setLocation(x, y); + floatFrame.invalidate(); + floatFrame.validate(); + floatFrame.repaint(); + } + + /** + * This is a convenience method for changing the orientation of the + * JToolBar. + * + * @param orientation The new orientation. + */ + public void setOrientation(int orientation) + { + toolBar.setOrientation(orientation); + } + + /** + * This method changes the child components to have rollover borders if the + * given parameter is true. Otherwise, the components are set to have non + * rollover borders. + * + * @param rollover Whether the children will have rollover borders. + */ + public void setRolloverBorders(boolean rollover) + { + if (rollover) + installRolloverBorders(toolBar); + else + installNonRolloverBorders(toolBar); + } + + /** + * This method uninstall UI installed components from the JToolBar. + */ + protected void uninstallComponents() + { + installNormalBorders(toolBar); + borders = null; + rolloverBorder = null; + nonRolloverBorder = null; + cachedBounds = null; + + floatFrame = null; + dragWindow = null; + } + + /** + * This method removes the defaults installed by the Look and Feel. + */ + protected void uninstallDefaults() + { + toolBar.setBackground(null); + toolBar.setForeground(null); + toolBar.setFont(null); + + dockingBorderColor = null; + dockingColor = null; + floatingBorderColor = null; + floatingColor = null; + } + + /** + * This method uninstalls keyboard actions installed by the UI. + */ + protected void uninstallKeyboardActions() + { + // FIXME: implement. + } + + /** + * This method uninstalls listeners installed by the UI. + */ + protected void uninstallListeners() + { + toolBar.removeFocusListener(toolBarFocusListener); + toolBarFocusListener = null; + + floatFrame.removeWindowListener(windowListener); + windowListener = null; + + toolBar.removeContainerListener(toolBarContListener); + toolBarContListener = null; + + toolBar.removeMouseMotionListener(dockingListener); + toolBar.removeMouseListener(dockingListener); + dockingListener = null; + } + + /** + * This method uninstalls the UI. + * + * @param c The JComponent that is having this UI removed. + */ + public void uninstallUI(JComponent c) + { + uninstallKeyboardActions(); + uninstallListeners(); + uninstallComponents(); + uninstallDefaults(); + toolBar = null; + } + + /** + * This is the MouseHandler class that allows the user to drag the JToolBar + * in and out of the parent and dock it if it can. + */ + public class DockingListener implements MouseInputListener + { + /** Whether the JToolBar is being dragged. */ + protected boolean isDragging; + + /** + * The origin point. This point is saved from the beginning press and is + * used until the end of the drag session. + */ + protected Point origin; + + /** The JToolBar being dragged. */ + protected JToolBar toolBar; + + /** + * Creates a new DockingListener object. + * + * @param t The JToolBar this DockingListener is being used for. + */ + public DockingListener(JToolBar t) + { + toolBar = t; + } + + /** + * This method is called when the mouse is clicked. + * + * @param e The MouseEvent. + */ + public void mouseClicked(MouseEvent e) + { + // Don't care. + } + + /** + * This method is called when the mouse is dragged. It delegates the drag + * painting to the dragTo method. + * + * @param e The MouseEvent. + */ + public void mouseDragged(MouseEvent e) + { + if (isDragging) + dragTo(e.getPoint(), origin); + } + + /** + * This method is called when the mouse enters the JToolBar. + * + * @param e The MouseEvent. + */ + public void mouseEntered(MouseEvent e) + { + // Don't care (yet). + } + + /** + * This method is called when the mouse exits the JToolBar. + * + * @param e The MouseEvent. + */ + public void mouseExited(MouseEvent e) + { + // Don't care (yet). + } + + /** + * This method is called when the mouse is moved in the JToolBar. + * + * @param e The MouseEvent. + */ + public void mouseMoved(MouseEvent e) + { + } + + /** + * This method is called when the mouse is pressed in the JToolBar. If the + * press doesn't occur in a place where it causes the JToolBar to be + * dragged, it returns. Otherwise, it starts a drag session. + * + * @param e The MouseEvent. + */ + public void mousePressed(MouseEvent e) + { + if (! toolBar.isFloatable()) + return; + + Point ssd = e.getPoint(); + Insets insets = toolBar.getInsets(); + + // Verify that this click occurs in the top inset. + if (toolBar.getOrientation() == SwingConstants.HORIZONTAL) + { + if (e.getX() > insets.left) + return; + } + else + { + if (e.getY() > insets.top) + return; + } + + origin = new Point(0, 0); + SwingUtilities.convertPointToScreen(ssd, toolBar); + + if (! (SwingUtilities.getAncestorOfClass(Window.class, toolBar) instanceof UIResource)) + // Need to know who keeps the toolBar if it gets dragged back into it. + origParent = toolBar.getParent(); + + SwingUtilities.convertPointToScreen(origin, toolBar); + + isDragging = true; + + if (dragWindow != null) + dragWindow.setOffset(new Point(e.getX(), e.getY())); + + dragTo(e.getPoint(), origin); + } + + /** + * This method is called when the mouse is released from the JToolBar. + * + * @param e The MouseEvent. + */ + public void mouseReleased(MouseEvent e) + { + if (! isDragging || ! toolBar.isFloatable()) + return; + + isDragging = false; + floatAt(e.getPoint(), origin); + dragWindow.hide(); + } + } + + /** + * This is the window that appears when the JToolBar is being dragged + * around. + */ + protected class DragWindow extends Window + { + /** + * The current border color. It changes depending on whether the JToolBar + * is over a place that allows it to dock. + */ + private Color borderColor; + + /** The between the mouse and the top left corner of the window. */ + private Point offset; + + /** + * Creates a new DragWindow object. + * This is package-private to avoid an accessor method. + */ + DragWindow() + { + super(owner); + } + + /** + * The color that the border should be. + * + * @return The border color. + */ + public Color getBorderColor() + { + if (borderColor == null) + return Color.BLACK; + + return borderColor; + } + + /** + * This method returns the insets for the DragWindow. + * + * @return The insets for the DragWindow. + */ + public Insets getInsets() + { + // This window has no decorations, so insets are empty. + return new Insets(0, 0, 0, 0); + } + + /** + * This method returns the mouse offset from the top left corner of the + * DragWindow. + * + * @return The mouse offset. + */ + public Point getOffset() + { + return offset; + } + + /** + * This method paints the DragWindow. + * + * @param g The Graphics object to paint with. + */ + public void paint(Graphics g) + { + // No visiting children necessary. + Color saved = g.getColor(); + Rectangle b = getBounds(); + + g.setColor(getBorderColor()); + g.drawRect(0, 0, b.width - 1, b.height - 1); + + g.setColor(saved); + } + + /** + * This method changes the border color. + * + * @param c The new border color. + */ + public void setBorderColor(Color c) + { + borderColor = c; + } + + /** + * This method changes the mouse offset. + * + * @param p The new mouse offset. + */ + public void setOffset(Point p) + { + offset = p; + } + + /** + * FIXME: Do something. + * + * @param o DOCUMENT ME! + */ + public void setOrientation(int o) + { + // FIXME: implement. + } + } + + /** + * This helper class listens for Window events from the floatable window and + * if it is closed, returns the JToolBar to the last known good location. + */ + protected class FrameListener extends WindowAdapter + { + /** + * This method is called when the floating window is closed. + * + * @param e The WindowEvent. + */ + public void windowClosing(WindowEvent e) + { + Container parent = toolBar.getParent(); + parent.remove(toolBar); + + if (origParent != null) + { + origParent.add(toolBar, + (constraintBeforeFloating != null) + ? constraintBeforeFloating : BorderLayout.NORTH); + toolBar.setOrientation(lastGoodOrientation); + } + + origParent.invalidate(); + origParent.validate(); + origParent.repaint(); + } + } + + /** + * This helper class listens for PropertyChangeEvents from the JToolBar. + */ + protected class PropertyListener implements PropertyChangeListener + { + /** + * This method is called when a property from the JToolBar is changed. + * + * @param e The PropertyChangeEvent. + */ + public void propertyChange(PropertyChangeEvent e) + { + // FIXME: need name properties so can change floatFrame title. + if (e.getPropertyName().equals("rollover")) + setRolloverBorders(toolBar.isRollover()); + } + } + + /** + * This helper class listens for components added to and removed from the + * JToolBar. + */ + protected class ToolBarContListener implements ContainerListener + { + /** + * This method is responsible for setting rollover or non rollover for new + * buttons added to the JToolBar. + * + * @param e The ContainerEvent. + */ + public void componentAdded(ContainerEvent e) + { + if (e.getChild() instanceof JButton) + { + JButton b = (JButton) e.getChild(); + + if (b.getBorder() != null) + borders.put(b, b.getBorder()); + } + + if (isRolloverBorders()) + setBorderToRollover(e.getChild()); + else + setBorderToNonRollover(e.getChild()); + + cachedBounds = toolBar.getPreferredSize(); + cachedOrientation = toolBar.getOrientation(); + } + + /** + * This method is responsible for giving the child components their + * original borders when they are removed. + * + * @param e The ContainerEvent. + */ + public void componentRemoved(ContainerEvent e) + { + setBorderToNormal(e.getChild()); + cachedBounds = toolBar.getPreferredSize(); + cachedOrientation = toolBar.getOrientation(); + } + } + + /** + * This is the floating window that is returned when getFloatingWindow is + * called. + */ + private class ToolBarDialog extends JDialog implements UIResource + { + /** + * Creates a new ToolBarDialog object with the name given by the JToolBar. + */ + public ToolBarDialog() + { + super(); + setName((toolBar.getName() != null) ? toolBar.getName() : ""); + } + } + + /** + * DOCUMENT ME! + */ + protected class ToolBarFocusListener implements FocusListener + { + /** + * Creates a new ToolBarFocusListener object. + */ + protected ToolBarFocusListener() + { + // FIXME: implement. + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void focusGained(FocusEvent e) + { + // FIXME: implement. + } + + /** + * DOCUMENT ME! + * + * @param e DOCUMENT ME! + */ + public void focusLost(FocusEvent e) + { + // FIXME: implement. + } + } + + /** + * This helper class acts as the border for the JToolBar. + */ + private static class ToolBarBorder implements Border + { + /** The size of the larger, draggable side of the border. */ + private static final int offset = 10; + + /** The other sides. */ + private static final int regular = 2; + + /** + * This method returns the border insets for the JToolBar. + * + * @param c The Component to find insets for. + * + * @return The border insets. + */ + public Insets getBorderInsets(Component c) + { + if (c instanceof JToolBar) + { + JToolBar tb = (JToolBar) c; + int orientation = tb.getOrientation(); + + if (! tb.isFloatable()) + return new Insets(regular, regular, regular, regular); + else if (orientation == SwingConstants.HORIZONTAL) + return new Insets(regular, offset, regular, regular); + else + return new Insets(offset, regular, regular, regular); + } + + return new Insets(0, 0, 0, 0); + } + + /** + * This method returns whether the border is opaque. + * + * @return Whether the border is opaque. + */ + public boolean isBorderOpaque() + { + return false; + } + + /** + * This method paints the ribbed area of the border. + * + * @param g The Graphics object to paint with. + * @param x The x coordinate of the area. + * @param y The y coordinate of the area. + * @param w The width of the area. + * @param h The height of the area. + * @param size The size of the bump. + * @param c The color of the bumps. + */ + private void paintBumps(Graphics g, int x, int y, int w, int h, int size, + Color c) + { + Color saved = g.getColor(); + g.setColor(c); + + int hgap = 2 * size; + int vgap = 4 * size; + int count = 0; + + for (int i = x; i < (w + x); i += hgap) + for (int j = ((count++ % 2) == 0) ? y : (y + (2 * size)); j < (h + y); + j += vgap) + g.fillRect(i, j, size, size); + + g.setColor(saved); + } + + /** + * This method paints the border around the given Component. + * + * @param c The Component whose border is being painted. + * @param g The Graphics object to paint with. + * @param x The x coordinate of the component. + * @param y The y coordinate of the component. + * @param width The width of the component. + * @param height The height of the component. + */ + public void paintBorder(Component c, Graphics g, int x, int y, int width, + int height) + { + if (c instanceof JToolBar) + { + JToolBar tb = (JToolBar) c; + + int orientation = tb.getOrientation(); + + if (orientation == SwingConstants.HORIZONTAL) + { + paintBumps(g, x, y, offset, height, 1, Color.WHITE); + paintBumps(g, x + 1, y + 1, offset - 1, height - 1, 1, Color.GRAY); + } + else + { + paintBumps(g, x, y, width, offset, 1, Color.WHITE); + paintBumps(g, x + 1, y + 1, width - 1, offset - 1, 1, Color.GRAY); + } + } + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicToolTipUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicToolTipUI.java new file mode 100644 index 0000000..b7a08aa --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicToolTipUI.java @@ -0,0 +1,288 @@ +/* BasicToolTipUI.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Rectangle; + +import javax.swing.JComponent; +import javax.swing.JToolTip; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.border.Border; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.ToolTipUI; + +/** + * This is the Basic Look and Feel UI class for JToolTip. + */ +public class BasicToolTipUI extends ToolTipUI +{ + /** The default Border around the JToolTip. */ + private static Border defaultBorder = new Border() + { + // FIXME: This needs to go into Basic Look and Feel + // defaults. + + /** + * This method returns the border insets. + * + * @param c The Component to find Border insets for. + * + * @return The Border insets. + */ + public Insets getBorderInsets(Component c) + { + return new Insets(4, 4, 4, 4); + } + + /** + * This method returns whether the border is opaque. + * + * @return Whether the border is opaque. + */ + public boolean isBorderOpaque() + { + return false; + } + + /** + * This method paints the border. + * + * @param c The Component to paint this border around. + * @param g The Graphics object to paint with. + * @param x The x coordinate to start painting at. + * @param y The y coordinate to start painting at. + * @param w The width of the Component. + * @param h The height of the Component. + */ + public void paintBorder(Component c, Graphics g, int x, int y, int w, + int h) + { + Color saved = g.getColor(); + g.setColor(Color.BLACK); + + g.drawRect(0, 0, w - 1, h - 1); + + g.setColor(saved); + } + }; + + /** The shared instance of BasicToolTipUI used for all ToolTips. */ + private static BasicToolTipUI shared; + + /** + * Creates a new BasicToolTipUI object. + */ + public BasicToolTipUI() + { + super(); + } + + /** + * This method creates a new BasicToolTip UI for the given + * JComponent. + * + * @param c The JComponent to create a UI for. + * + * @return A BasicToolTipUI that can be used by the given JComponent. + */ + public static ComponentUI createUI(JComponent c) + { + if (shared == null) + shared = new BasicToolTipUI(); + return shared; + } + + /** + * This method returns the msximum size of the given JComponent. + * + * @param c The JComponent to find a maximum size for. + * + * @return The maximum size. + */ + public Dimension getMaximumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the minimum size of the given JComponent. + * + * @param c The JComponent to find a minimum size for. + * + * @return The minimum size. + */ + public Dimension getMinimumSize(JComponent c) + { + return getPreferredSize(c); + } + + /** + * This method returns the preferred size of the given JComponent. + * + * @param c The JComponent to find a preferred size for. + * + * @return The preferred size. + */ + public Dimension getPreferredSize(JComponent c) + { + JToolTip tip = (JToolTip) c; + Rectangle vr = new Rectangle(); + Rectangle ir = new Rectangle(); + Rectangle tr = new Rectangle(); + Insets insets = tip.getInsets(); + FontMetrics fm = tip.getToolkit().getFontMetrics(tip.getFont()); + SwingUtilities.layoutCompoundLabel(tip, fm, tip.getTipText(), null, + SwingConstants.CENTER, + SwingConstants.CENTER, + SwingConstants.CENTER, + SwingConstants.CENTER, vr, ir, tr, 0); + return new Dimension(insets.left + tr.width + insets.right, + insets.top + tr.height + insets.bottom); + } + + /** + * This method installs the defaults for the given JComponent. + * + * @param c The JComponent to install defaults for. + */ + protected void installDefaults(JComponent c) + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + c.setBackground(defaults.getColor("ToolTip.background")); + c.setForeground(defaults.getColor("ToolTip.foreground")); + c.setFont(defaults.getFont("ToolTip.font")); + c.setBorder(defaultBorder); + } + + /** + * This method installs the listeners for the given JComponent. + * + * @param c The JComponent to install listeners for. + */ + protected void installListeners(JComponent c) + { + } + + /** + * This method installs the UI for the given JComponent. + * + * @param c The JComponent to install the UI for. + */ + public void installUI(JComponent c) + { + c.setOpaque(true); + installDefaults(c); + installListeners(c); + } + + /** + * This method paints the given JComponent with the given Graphics object. + * + * @param g The Graphics object to paint with. + * @param c The JComponent to paint. + */ + public void paint(Graphics g, JComponent c) + { + JToolTip tip = (JToolTip) c; + + String text = tip.getTipText(); + if (text == null) + return; + + Rectangle vr = new Rectangle(); + vr = SwingUtilities.calculateInnerArea(tip, vr); + Rectangle ir = new Rectangle(); + Rectangle tr = new Rectangle(); + FontMetrics fm = tip.getToolkit().getFontMetrics(tip.getFont()); + SwingUtilities.layoutCompoundLabel(tip, fm, tip.getTipText(), null, + SwingConstants.CENTER, + SwingConstants.CENTER, + SwingConstants.CENTER, + SwingConstants.CENTER, vr, ir, tr, 0); + + Color saved = g.getColor(); + g.setColor(Color.BLACK); + + g.drawString(text, vr.x, vr.y + fm.getAscent()); + + g.setColor(saved); + } + + /** + * This method uninstalls the defaults for the given JComponent. + * + * @param c The JComponent to uninstall defaults for. + */ + protected void uninstallDefaults(JComponent c) + { + c.setForeground(null); + c.setBackground(null); + c.setFont(null); + c.setBorder(null); + } + + /** + * This method uninstalls listeners for the given JComponent. + * + * @param c The JComponent to uninstall listeners for. + */ + protected void uninstallListeners(JComponent c) + { + } + + /** + * This method uninstalls the UI for the given JComponent. + * + * @param c The JComponent to uninstall. + */ + public void uninstallUI(JComponent c) + { + uninstallDefaults(c); + uninstallListeners(c); + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTreeUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTreeUI.java new file mode 100644 index 0000000..b9d3b62 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTreeUI.java @@ -0,0 +1,2813 @@ +/* BasicTreeUI.java -- + Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.CellRendererPane; +import javax.swing.Icon; +import javax.swing.JComponent; +import javax.swing.JScrollBar; +import javax.swing.JScrollPane; +import javax.swing.JTree; +import javax.swing.SwingUtilities; +import javax.swing.Timer; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.event.CellEditorListener; +import javax.swing.event.ChangeEvent; +import javax.swing.event.MouseInputListener; +import javax.swing.event.TreeExpansionEvent; +import javax.swing.event.TreeExpansionListener; +import javax.swing.event.TreeModelEvent; +import javax.swing.event.TreeModelListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.TreeUI; +import javax.swing.tree.AbstractLayoutCache; +import javax.swing.tree.FixedHeightLayoutCache; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeCellEditor; +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.tree.TreeCellEditor; +import javax.swing.tree.TreeCellRenderer; +import javax.swing.tree.TreeSelectionModel; +import javax.swing.tree.TreeModel; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; + +import java.util.Enumeration; +import java.util.Hashtable; + +/** + * A delegate providing the user interface for <code>JTree</code> according to + * the Basic look and feel. + * + * @see javax.swing.JTree + * @author Sascha Brawer (brawer@dandelis.ch) + * @author Lillian Angel (langel@redhat.com) + */ +public class BasicTreeUI + extends TreeUI +{ + + /** Collapse Icon for the tree. */ + protected transient Icon collapsedIcon; + + /** Expanded Icon for the tree. */ + protected transient Icon expandedIcon; + + /** Distance between left margin and where vertical dashes will be drawn. */ + protected int leftChildIndent; + + /** + * Distance between leftChildIndent and where cell contents will be drawn. + */ + protected int rightChildIndent; + + /** + * Total fistance that will be indented. The sum of leftChildIndent and + * rightChildIndent . + */ + protected int totalChildIndent; + + /** Minimum preferred size. */ + protected Dimension preferredMinsize; + + /** Index of the row that was last selected. */ + protected int lastSelectedRow; + + /** Component that we're going to be drawing onto. */ + protected JTree tree; + + /** Renderer that is being used to do the actual cell drawing. */ + protected transient TreeCellRenderer currentCellRenderer; + + /** + * Set to true if the renderer that is currently in the tree was created by + * this instance. + */ + protected boolean createdRenderer; + + /** Editor for the tree. */ + protected transient TreeCellEditor cellEditor; + + /** + * Set to true if editor that is currently in the tree was created by this + * instance. + */ + protected boolean createdCellEditor; + + /** + * Set to false when editing and shouldSelectCall() returns true meaning the + * node should be selected before editing, used in completeEditing. + */ + protected boolean stopEditingInCompleteEditing; + + /** Used to paint the TreeCellRenderer. */ + protected CellRendererPane rendererPane; + + /** Size needed to completely display all the nodes. */ + protected Dimension preferredSize; + + /** Is the preferredSize valid? */ + protected boolean validCachedPreferredSize; + + /** Object responsible for handling sizing and expanded issues. */ + protected AbstractLayoutCache treeState; + + /** Used for minimizing the drawing of vertical lines. */ + protected Hashtable drawingCache; + + /** + * True if doing optimizations for a largeModel. Subclasses that don't + * support this may wish to override createLayoutCache to not return a + * FixedHeightLayoutCache instance. + */ + protected boolean largeModel; + + /** Responsible for telling the TreeState the size needed for a node. */ + protected AbstractLayoutCache.NodeDimensions nodeDimensions; + + /** Used to determine what to display. */ + protected TreeModel treeModel; + + /** Model maintaining the selection. */ + protected TreeSelectionModel treeSelectionModel; + + /** + * How much the depth should be offset to properly calculate x locations. + * This is based on whether or not the root is visible, and if the root + * handles are visible. + */ + protected int depthOffset; + + /** + * When editing, this will be the Component that is doing the actual editing. + */ + protected Component editingComponent; + + /** Path that is being edited. */ + protected TreePath editingPath; + + /** + * Row that is being edited. Should only be referenced if editingComponent is + * null. + */ + protected int editingRow; + + /** Set to true if the editor has a different size than the renderer. */ + protected boolean editorHasDifferentSize; + + /** Listeners */ + private PropertyChangeListener propertyChangeListener; + + private FocusListener focusListener; + + private TreeSelectionListener treeSelectionListener; + + private MouseInputListener mouseInputListener; + + private KeyListener keyListener; + + private PropertyChangeListener selectionModelPropertyChangeListener; + + private ComponentListener componentListener; + + private CellEditorListener cellEditorListener; + + private TreeExpansionListener treeExpansionListener; + + private TreeModelListener treeModelListener; + + /** + * Creates a new BasicTreeUI object. + */ + public BasicTreeUI() + { + drawingCache = new Hashtable(); + cellEditor = createDefaultCellEditor(); + currentCellRenderer = createDefaultCellRenderer(); + nodeDimensions = createNodeDimensions(); + rendererPane = createCellRendererPane(); + configureLayoutCache(); + + propertyChangeListener = createPropertyChangeListener(); + focusListener = createFocusListener(); + treeSelectionListener = createTreeSelectionListener(); + mouseInputListener = new MouseInputHandler(null, null, null); + keyListener = createKeyListener(); + selectionModelPropertyChangeListener = createSelectionModelPropertyChangeListener(); + componentListener = createComponentListener(); + cellEditorListener = createCellEditorListener(); + treeExpansionListener = createTreeExpansionListener(); + treeModelListener = createTreeModelListener(); + + createdRenderer = true; + createdCellEditor = true; + editingRow = -1; + lastSelectedRow = -1; + } + + /** + * Returns an instance of the UI delegate for the specified component. + * + * @param c the <code>JComponent</code> for which we need a UI delegate + * for. + * @return the <code>ComponentUI</code> for c. + */ + public static ComponentUI createUI(JComponent c) + { + return new BasicTreeUI(); + } + + /** + * Returns the Hash color. + * + * @return the <code>Color</code> of the Hash. + */ + protected Color getHashColor() + { + return UIManager.getLookAndFeelDefaults().getColor("Tree.hash"); + } + + /** + * Sets the Hash color. + * + * @param the <code>Color</code> to set the Hash to. + */ + protected void setHashColor(Color color) + { + // FIXME: not implemented + + } + + /** + * Sets the left child's indent value. + * + * @param newAmount is the new indent value for the left child. + */ + public void setLeftChildIndent(int newAmount) + { + leftChildIndent = newAmount; + } + + /** + * Returns the indent value for the left child. + * + * @return the indent value for the left child. + */ + public int getLeftChildIndent(int newAmount) + { + return leftChildIndent; + } + + /** + * Sets the right child's indent value. + * + * @param newAmount is the new indent value for the right child. + */ + public void setRightChildIndent(int newAmount) + { + rightChildIndent = newAmount; + } + + /** + * Returns the indent value for the right child. + * + * @return the indent value for the right child. + */ + public int getRightChildIndent(int newAmount) + { + return rightChildIndent; + } + + /** + * Sets the expanded icon. + * + * @param newG is the new expanded icon. + */ + public void setExpandedIcon(Icon newG) + { + expandedIcon = newG; + } + + /** + * Returns the current expanded icon. + * + * @return the current expanded icon. + */ + public Icon getExpandedIcon() + { + return expandedIcon; + } + + /** + * Sets the collapsed icon. + * + * @param newG is the new collapsed icon. + */ + public void setCollapsedIcon(Icon newG) + { + collapsedIcon = newG; + } + + /** + * Returns the current collapsed icon. + * + * @return the current collapsed icon. + */ + public Icon getCollapsedIcon() + { + return collapsedIcon; + } + + /** + * Updates the componentListener, if necessary. + * + * @param largeModel sets this.largeModel to it. + */ + protected void setLargeModel(boolean largeModel) + { + if (largeModel != this.largeModel) + { + tree.removeComponentListener(componentListener); + this.largeModel = largeModel; + tree.addComponentListener(componentListener); + } + } + + /** + * Returns true if largeModel is set + * + * @return true if largeModel is set, otherwise false. + */ + protected boolean isLargeModel() + { + return largeModel; + } + + /** + * Sets the row height. + * + * @param rowHeight is the height to set this.rowHeight to. + */ + protected void setRowHeight(int rowHeight) + { + treeState.setRowHeight(rowHeight); + } + + /** + * Returns the current row height. + * + * @return current row height. + */ + protected int getRowHeight() + { + return treeState.getRowHeight(); + } + + /** + * Sets the TreeCellRenderer to <code>tcr</code>. This invokes + * <code>updateRenderer</code>. + * + * @param tcr is the new TreeCellRenderer. + */ + protected void setCellRenderer(TreeCellRenderer tcr) + { + currentCellRenderer = tcr; + updateRenderer(); + } + + /** + * Return currentCellRenderer, which will either be the trees renderer, or + * defaultCellRenderer, which ever was not null. + * + * @return the current Cell Renderer + */ + protected TreeCellRenderer getCellRenderer() + { + if (currentCellRenderer != null) + return currentCellRenderer; + + return createDefaultCellRenderer(); + } + + /** + * Sets the tree's model. + * + * @param model to set the treeModel to. + */ + protected void setModel(TreeModel model) + { + treeState.setModel(model); + treeModel = model; + } + + /** + * Returns the tree's model + * + * @return treeModel + */ + protected TreeModel getModel() + { + return treeModel; + } + + /** + * Sets the root to being visible. + * + * @param newValue sets the visibility of the root + */ + protected void setRootVisible(boolean newValue) + { + treeState.setRootVisible(newValue); + } + + /** + * Returns true if the root is visible. + * + * @return true if the root is visible. + */ + protected boolean isRootVisible() + { + return treeState.isRootVisible(); + } + + /** + * Determines whether the node handles are to be displayed. + * + * @param newValue sets whether or not node handles should be displayed. + */ + protected void setShowsRootHandles(boolean newValue) + { + tree.setShowsRootHandles(newValue); + } + + /** + * Returns true if the node handles are to be displayed. + * + * @return true if the node handles are to be displayed. + */ + protected boolean getShowsRootHandles() + { + return tree.getShowsRootHandles(); + } + + /** + * Sets the cell editor. + * + * @param editor to set the cellEditor to. + */ + protected void setCellEditor(TreeCellEditor editor) + { + cellEditor = editor; + } + + /** + * Returns the <code>TreeCellEditor</code> for this tree. + * + * @return the cellEditor for this tree. + */ + protected TreeCellEditor getCellEditor() + { + return cellEditor; + } + + /** + * Configures the receiver to allow, or not allow, editing. + * + * @param newValue sets the receiver to allow editing if true. + */ + protected void setEditable(boolean newValue) + { + tree.setEditable(newValue); + } + + /** + * Returns true if the receiver allows editing. + * + * @return true if the receiver allows editing. + */ + protected boolean isEditable() + { + return tree.isEditable(); + } + + /** + * Resets the selection model. The appropriate listeners are installed on the + * model. + * + * @param newLSM resets the selection model. + */ + protected void setSelectionModel(TreeSelectionModel newLSM) + { + if (newLSM != null) + { + treeSelectionModel = newLSM; + tree.setSelectionModel(treeSelectionModel); + } + } + + /** + * Returns the current selection model. + * + * @return the current selection model. + */ + protected TreeSelectionModel getSelectionModel() + { + return treeSelectionModel; + } + + /** + * Returns the Rectangle enclosing the label portion that the last item in + * path will be drawn to. Will return null if any component in path is + * currently valid. + * + * @param tree is the current tree the path will be drawn to. + * @param path is the current path the tree to draw to. + * @return the Rectangle enclosing the label portion that the last item in + * the path will be drawn to. + */ + public Rectangle getPathBounds(JTree tree, TreePath path) + { + Object cell = path.getLastPathComponent(); + TreeModel mod = tree.getModel(); + Point loc = getCellLocation(0, 0, tree, mod, cell, mod.getRoot()); + int x = (int) loc.getX(); + int y = (int) loc.getY(); + return getCellBounds(x, y, cell); + } + + /** + * Returns the path for passed in row. If row is not visible null is + * returned. + * + * @param tree is the current tree to return path for. + * @param row is the row number of the row to return. + * @return the path for passed in row. If row is not visible null is + * returned. + */ + public TreePath getPathForRow(JTree tree, int row) + { + DefaultMutableTreeNode node = ((DefaultMutableTreeNode) (tree.getModel()) + .getRoot()); + + for (int i = 0; i < row; i++) + node = getNextVisibleNode(node); + + // in case nothing was found + if (node == null) + return null; + + // something was found + return new TreePath(node.getPath()); + } + + /** + * Get next visible node in the tree. + * Package private for use in inner classes. + * @param the current node + * @return the next visible node in the JTree. Return null if there are no + * more. + */ + DefaultMutableTreeNode getNextVisibleNode(DefaultMutableTreeNode node) + { + DefaultMutableTreeNode next = null; + TreePath current = null; + + if (node != null) + next = node.getNextNode(); + + if (next != null) + { + current = new TreePath(next.getPath()); + if (tree.isVisible(current)) + return next; + + while (next != null && !tree.isVisible(current)) + { + next = next.getNextNode(); + + if (next != null) + current = new TreePath(next.getPath()); + } + } + return next; + } + + /** + * Get previous visible node in the tree. + * Package private for use in inner classes. + * + * @param the current node + * @return the next visible node in the JTree. Return null if there are no + * more. + */ + DefaultMutableTreeNode getPreviousVisibleNode + (DefaultMutableTreeNode node) + { + DefaultMutableTreeNode prev = null; + TreePath current = null; + + if (node != null) + prev = node.getPreviousNode(); + + if (prev != null) + { + current = new TreePath(prev.getPath()); + if (tree.isVisible(current)) + return prev; + + while (prev != null && !tree.isVisible(current)) + { + prev = prev.getPreviousNode(); + + if (prev != null) + current = new TreePath(prev.getPath()); + } + } + return prev; + } + + /** + * Returns the row that the last item identified in path is visible at. Will + * return -1 if any of the elments in the path are not currently visible. + * + * @param tree is the current tree to return the row for. + * @param path is the path used to find the row. + * @return the row that the last item identified in path is visible at. Will + * return -1 if any of the elments in the path are not currently + * visible. + */ + public int getRowForPath(JTree tree, TreePath path) + { + // FIXME: check visibility + // right now, just returns last element because + // expand/collapse is not implemented + return path.getPathCount() - 1; + } + + /** + * Returns the number of rows that are being displayed. + * + * @param tree is the current tree to return the number of rows for. + * @return the number of rows being displayed. + */ + public int getRowCount(JTree tree) + { + DefaultMutableTreeNode node = ((DefaultMutableTreeNode) (tree.getModel()) + .getRoot()); + int count = 0; + + while (node != null) + { + count++; + node = getNextVisibleNode(node); + } + + return count; + } + + /** + * Returns the path to the node that is closest to x,y. If there is nothing + * currently visible this will return null, otherwise it'll always return a + * valid path. If you need to test if the returned object is exactly at x,y + * you should get the bounds for the returned path and test x,y against that. + * + * @param tree the tree to search for the closest path + * @param x is the x coordinate of the location to search + * @param y is the y coordinate of the location to search + * @return the tree path closes to x,y. + */ + public TreePath getClosestPathForLocation(JTree tree, int x, int y) + { + return treeState.getPathClosestTo(x, y); + } + + /** + * Returns true if the tree is being edited. The item that is being edited + * can be returned by getEditingPath(). + * + * @param tree is the tree to check for editing. + * @return true if the tree is being edited. + */ + public boolean isEditing(JTree tree) + { + // FIXME: not implemented + return false; + } + + /** + * Stops the current editing session. This has no effect if the tree is not + * being edited. Returns true if the editor allows the editing session to + * stop. + * + * @param tree is the tree to stop the editing on + * @return true if the editor allows the editing session to stop. + */ + public boolean stopEditing(JTree tree) + { + // FIXME: not implemented + return false; + } + + /** + * Cancels the current editing session. + * + * @param tree is the tree to cancel the editing session on. + */ + public void cancelEditing(JTree tree) + { + // FIXME: not implemented + } + + /** + * Selects the last item in path and tries to edit it. Editing will fail if + * the CellEditor won't allow it for the selected item. + * + * @param tree is the tree to edit on. + * @param path is the path in tree to edit on. + */ + public void startEditingAtPath(JTree tree, TreePath path) + { + // FIXME: not implemented + } + + /** + * Returns the path to the element that is being editted. + * + * @param tree is the tree to get the editing path from. + * @return the path that is being edited. + */ + public TreePath getEditingPath(JTree tree) + { + // FIXME: not implemented + return null; + } + + /** + * Invoked after the tree instance variable has been set, but before any + * default/listeners have been installed. + */ + protected void prepareForUIInstall() + { + // FIXME: not implemented + } + + /** + * Invoked from installUI after all the defaults/listeners have been + * installed. + */ + protected void completeUIInstall() + { + // FIXME: not implemented + } + + /** + * Invoked from uninstallUI after all the defaults/listeners have been + * uninstalled. + */ + protected void completeUIUninstall() + { + // FIXME: not implemented + } + + /** + * Installs the subcomponents of the tree, which is the renderer pane. + */ + protected void installComponents() + { + // FIXME: not implemented + } + + /** + * Creates an instance of NodeDimensions that is able to determine the size + * of a given node in the tree. + * + * @return the NodeDimensions of a given node in the tree + */ + protected AbstractLayoutCache.NodeDimensions createNodeDimensions() + { + // FIXME: not implemented + return null; + } + + /** + * Creates a listener that is reponsible for the updates the UI based on how + * the tree changes. + * + * @return the PropertyChangeListener that is reposnsible for the updates + */ + protected PropertyChangeListener createPropertyChangeListener() + { + return new PropertyChangeHandler(); + } + + /** + * Creates the listener responsible for updating the selection based on mouse + * events. + * + * @return the MouseListener responsible for updating. + */ + protected MouseListener createMouseListener() + { + return new MouseHandler(); + } + + /** + * Creates the listener that is responsible for updating the display when + * focus is lost/grained. + * + * @return the FocusListener responsible for updating. + */ + protected FocusListener createFocusListener() + { + return new FocusHandler(); + } + + /** + * Creates the listener reponsible for getting key events from the tree. + * + * @return the KeyListener responsible for getting key events. + */ + protected KeyListener createKeyListener() + { + return new KeyHandler(); + } + + /** + * Creates the listener responsible for getting property change events from + * the selection model. + * + * @returns the PropertyChangeListener reponsible for getting property change + * events from the selection model. + */ + protected PropertyChangeListener createSelectionModelPropertyChangeListener() + { + return new SelectionModelPropertyChangeHandler(); + } + + /** + * Creates the listener that updates the display based on selection change + * methods. + * + * @return the TreeSelectionListener responsible for updating. + */ + protected TreeSelectionListener createTreeSelectionListener() + { + return new TreeSelectionHandler(); + } + + /** + * Creates a listener to handle events from the current editor + * + * @return the CellEditorListener that handles events from the current editor + */ + protected CellEditorListener createCellEditorListener() + { + return new CellEditorHandler(); + } + + /** + * Creates and returns a new ComponentHandler. This is used for the large + * model to mark the validCachedPreferredSize as invalid when the component + * moves. + * + * @return a new ComponentHandler. + */ + protected ComponentListener createComponentListener() + { + return new ComponentHandler(); + } + + /** + * Creates and returns the object responsible for updating the treestate when + * a nodes expanded state changes. + * + * @return the TreeExpansionListener responsible for updating the treestate + */ + protected TreeExpansionListener createTreeExpansionListener() + { + return new TreeExpansionHandler(); + } + + /** + * Creates the object responsible for managing what is expanded, as well as + * the size of nodes. + * + * @return the object responsible for managing what is expanded. + */ + protected AbstractLayoutCache createLayoutCache() + { + return new FixedHeightLayoutCache(); + } + + /** + * Returns the renderer pane that renderer components are placed in. + * + * @return the rendererpane that render components are placed in. + */ + protected CellRendererPane createCellRendererPane() + { + return new CellRendererPane(); + } + + /** + * Creates a default cell editor. + * + * @return the default cell editor. + */ + protected TreeCellEditor createDefaultCellEditor() + { + return new DefaultTreeCellEditor(tree, + (DefaultTreeCellRenderer) createDefaultCellRenderer(), cellEditor); + } + + /** + * Returns the default cell renderer that is used to do the stamping of each + * node. + * + * @return the default cell renderer that is used to do the stamping of each + * node. + */ + protected TreeCellRenderer createDefaultCellRenderer() + { + return new DefaultTreeCellRenderer(); + } + + /** + * Returns a listener that can update the tree when the model changes. + * + * @return a listener that can update the tree when the model changes. + */ + protected TreeModelListener createTreeModelListener() + { + return new TreeModelHandler(); + } + + /** + * Uninstall all registered listeners + */ + protected void uninstallListeners() + { + tree.removePropertyChangeListener(propertyChangeListener); + tree.removeFocusListener(focusListener); + tree.removeTreeSelectionListener(treeSelectionListener); + tree.removeMouseListener(mouseInputListener); + tree.removeKeyListener(keyListener); + tree.removePropertyChangeListener(selectionModelPropertyChangeListener); + tree.removeComponentListener(componentListener); + tree.getCellEditor().removeCellEditorListener(cellEditorListener); + tree.removeTreeExpansionListener(treeExpansionListener); + tree.getModel().removeTreeModelListener(treeModelListener); + } + + /** + * Uninstall all keyboard actions. + */ + protected void uninstallKeyboardActions() + { + } + + /** + * Uninstall the rendererPane. + */ + protected void uninstallComponents() + { + // FIXME: not implemented + } + + /** + * The vertical element of legs between nodes starts at the bottom of the + * parent node by default. This method makes the leg start below that. + * + * @return the vertical leg buffer + */ + protected int getVerticalLegBuffer() + { + // FIXME: not implemented + return 0; + } + + /** + * The horizontal element of legs between nodes starts at the right of the + * left-hand side of the child node by default. This method makes the leg end + * before that. + * + * @return the horizontal leg buffer + */ + protected int getHorizontalLegBuffer() + { + // FIXME: not implemented + return 0; + } + + /** + * Make all the nodes that are expanded in JTree expanded in LayoutCache. + * This invokes update ExpandedDescendants with the root path. + */ + protected void updateLayoutCacheExpandedNodes() + { + // FIXME: not implemented + } + + /** + * Updates the expanded state of all the descendants of the <code>path</code> + * by getting the expanded descendants from the tree and forwarding to the + * tree state. + * + * @param path the path used to update the expanded states + */ + protected void updateExpandedDescendants(TreePath path) + { + // FIXME: not implemented + } + + /** + * Returns a path to the last child of <code>parent</code> + * + * @param parent is the topmost path to specified + * @return a path to the last child of parent + */ + protected TreePath getLastChildPath(TreePath parent) + { + return ((TreePath) parent.getLastPathComponent()); + } + + /** + * Updates how much each depth should be offset by. + */ + protected void updateDepthOffset() + { + // FIXME: not implemented + } + + /** + * Updates the cellEditor based on editability of the JTree that we're + * contained in. Ig the tree is editable but doesn't have a cellEditor, a + * basic one will be used. + */ + protected void updateCellEditor() + { + // FIXME: not implemented + } + + /** + * Messaged from the tree we're in when the renderer has changed. + */ + protected void updateRenderer() + { + // FIXME: not implemented + } + + /** + * Resets the treeState instance based on the tree we're providing the look + * and feel for. + */ + protected void configureLayoutCache() + { + treeState = createLayoutCache(); + } + + /** + * Marks the cached size as being invalid, and messages the tree with + * <code>treeDidChange</code>. + */ + protected void updateSize() + { + // FIXME: not implemented + } + + /** + * Updates the <code>preferredSize</code> instance variable, which is + * returned from <code>getPreferredSize()</code>. For left to right + * orientations, the size is determined from the current AbstractLayoutCache. + * For RTL orientations, the preferred size becomes the width minus the + * minimum x position. + */ + protected void updateCachedPreferredSize() + { + // FIXME: not implemented + } + + /** + * Messaged from the VisibleTreeNode after it has been expanded. + * + * @param path is the path that has been expanded. + */ + protected void pathWasExpanded(TreePath path) + { + // FIXME: not implemented + } + + /** + * Messaged from the VisibleTreeNode after it has collapsed + */ + protected void pathWasCollapsed(TreePath path) + { + // FIXME: not implemented + } + + /** + * Install all defaults for the tree. + * + * @param tree is the JTree to install defaults for + */ + protected void installDefaults(JTree tree) + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + + tree.setFont(defaults.getFont("Tree.font")); + tree.setForeground(defaults.getColor("Tree.foreground")); + tree.setBackground(defaults.getColor("Tree.background")); + tree.setOpaque(true); + + rightChildIndent = defaults.getInt("Tree.rightChildIndent"); + leftChildIndent = defaults.getInt("Tree.leftChildIndent"); + setRowHeight(defaults.getInt("Tree.rowHeight")); + } + + /** + * Install all keyboard actions for this + */ + protected void installKeyboardActions() + { + } + + /** + * Install all listeners for this + */ + protected void installListeners() + { + tree.addPropertyChangeListener(propertyChangeListener); + tree.addFocusListener(focusListener); + tree.addTreeSelectionListener(treeSelectionListener); + tree.addMouseListener(mouseInputListener); + tree.addKeyListener(keyListener); + tree.addPropertyChangeListener(selectionModelPropertyChangeListener); + tree.addComponentListener(componentListener); + cellEditor.addCellEditorListener(cellEditorListener); + tree.addTreeExpansionListener(treeExpansionListener); + treeModel.addTreeModelListener(treeModelListener); + } + + /** + * Install the UI for the component + * + * @param c the component to install UI for + */ + public void installUI(JComponent c) + { + super.installUI(c); + installDefaults((JTree) c); + tree = (JTree) c; + setModel(tree.getModel()); + tree.setRootVisible(true); + tree.expandPath(new TreePath(((DefaultMutableTreeNode) + (tree.getModel()).getRoot()).getPath())); + treeSelectionModel = tree.getSelectionModel(); + installListeners(); + installKeyboardActions(); + completeUIInstall(); + } + + /** + * Uninstall the defaults for the tree + * + * @param tree to uninstall defaults for + */ + protected void uninstallDefaults(JTree tree) + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + tree.setFont(null); + tree.setForeground(null); + tree.setBackground(null); + tree.setCellRenderer(null); + } + + /** + * Uninstall the UI for the component + * + * @param c the component to uninstall UI for + */ + public void uninstallUI(JComponent c) + { + uninstallDefaults((JTree) c); + uninstallKeyboardActions(); + uninstallListeners(); + tree = null; + completeUIUninstall(); + } + + /** + * Paints the specified component appropriate for the look and feel. This + * method is invoked from the ComponentUI.update method when the specified + * component is being painted. Subclasses should override this method and use + * the specified Graphics object to render the content of the component. + * + * @param g the Graphics context in which to paint + * @param c the component being painted; this argument is often ignored, but + * might be used if the UI object is stateless and shared by multiple + * components + */ + public void paint(Graphics g, JComponent c) + { + JTree tree = (JTree) c; + TreeModel mod = tree.getModel(); + g.translate(10, 10); + paintRecursive(g, 0, 0, 0, 0, tree, mod, mod.getRoot()); + paintControlIcons(g, 0, 0, 0, 0, tree, mod, mod.getRoot()); + g.translate(-10, -10); + } + + /** + * Ensures that the rows identified by beginRow through endRow are visible. + * + * @param beginRow is the first row + * @param endRow is the last row + */ + protected void ensureRowsAreVisible(int beginRow, int endRow) + { + // FIXME: not implemented + } + + /** + * Sets the preferred minimum size. + * + * @param newSize is the new preferred minimum size. + */ + public void setPreferredMinSize(Dimension newSize) + { + // FIXME: not implemented + } + + /** + * Gets the preferred minimum size. + * + * @returns the preferred minimum size. + */ + public Dimension getPreferredMinSize() + { + // FIXME: not implemented + return null; + } + + /** + * Returns the preferred size to properly display the tree, this is a cover + * method for getPreferredSize(c, false). + * + * @param c the component whose preferred size is being queried; this + * argument is often ignored but might be used if the UI object is + * stateless and shared by multiple components + * @return the preferred size + */ + public Dimension getPreferredSize(JComponent c) + { + return getPreferredSize(c, false); + } + + /** + * Returns the preferred size to represent the tree in c. If checkConsistancy + * is true, checkConsistancy is messaged first. + * + * @param c the component whose preferred size is being queried. + * @param checkConsistancy if true must check consistancy + * @return the preferred size + */ + public Dimension getPreferredSize(JComponent c, boolean checkConsistancy) + { + // FIXME: checkConsistancy not implemented, c not used + DefaultMutableTreeNode node = ((DefaultMutableTreeNode) (tree.getModel()) + .getRoot()); + int maxWidth = 0; + int count = 0; + if (node != null) + { + maxWidth = (int) (getCellBounds(0, 0, node).getWidth()); + while (node != null) + { + count++; + DefaultMutableTreeNode nextNode = node.getNextNode(); + if (nextNode != null) + maxWidth = Math.max(maxWidth, (int) (getCellBounds(0, 0, nextNode) + .getWidth())); + node = nextNode; + } + } + + return new Dimension(maxWidth, (getRowHeight() * count)); + } + + /** + * Returns the minimum size for this component. Which will be the min + * preferred size or (0,0). + * + * @param c the component whose min size is being queried. + * @returns the preferred size or null + */ + public Dimension getMinimumSize(JComponent c) + { + // FIXME: not implemented + return getPreferredSize(c); + } + + /** + * Returns the maximum size for the component, which will be the preferred + * size if the instance is currently in JTree or (0,0). + * + * @param c the component whose preferred size is being queried + * @return the max size or null + */ + public Dimension getMaximumSize(JComponent c) + { + // FIXME: not implemented + return getPreferredSize(c); + } + + /** + * Messages to stop the editing session. If the UI the receiver is providing + * the look and feel for returns true from + * <code>getInvokesStopCellEditing</code>, stopCellEditing will be invoked + * on the current editor. Then completeEditing will be messaged with false, + * true, false to cancel any lingering editing. + */ + protected void completeEditing() + { + // FIXME: not implemented + } + + /** + * Stops the editing session. If messageStop is true, the editor is messaged + * with stopEditing, if messageCancel is true the editor is messaged with + * cancelEditing. If messageTree is true, the treeModel is messaged with + * valueForPathChanged. + * + * @param messageStop message to stop editing + * @param messageCancel message to cancel editing + * @param messageTree message to treeModel + */ + protected void completeEditing(boolean messageStop, boolean messageCancel, + boolean messageTree) + { + // FIXME: not implemented + } + + /** + * Will start editing for node if there is a cellEditor and shouldSelectCall + * returns true. This assumes that path is valid and visible. + * + * @param path is the path to start editing + * @param event is the MouseEvent performed on the path + * @return true if successful + */ + protected boolean startEditing(TreePath path, MouseEvent event) + { + // FIXME: not implemented + return false; + } + + /** + * If the <code>mouseX</code> and <code>mouseY</code> are in the expand + * or collapse region of the row, this will toggle the row. + * + * @param path the path we are concerned with + * @param mouseX is the cursor's x position + * @param mouseY is the cursor's y position + */ + protected void checkForClickInExpandControl(TreePath path, int mouseX, + int mouseY) + { + // FIXME: not implemented + } + + /** + * Returns true if the <code>mouseX</code> and <code>mouseY</code> fall + * in the area of row that is used to expand/collpse the node and the node at + * row does not represent a leaf. + * + * @param path the path we are concerned with + * @param mouseX is the cursor's x position + * @param mouseY is the cursor's y position + * @return true if the <code>mouseX</code> and <code>mouseY</code> fall + * in the area of row that is used to expand/collpse the node and the + * node at row does not represent a leaf. + */ + protected boolean isLocationInExpandControl(TreePath path, int mouseX, + int mouseY) + { + // FIXME: not implemented + return false; + } + + /** + * Messaged when the user clicks the particular row, this invokes + * toggleExpandState. + * + * @param path the path we are concerned with + * @param mouseX is the cursor's x position + * @param mouseY is the cursor's y position + */ + protected void handleExpandControlClick(TreePath path, int mouseX, int mouseY) + { + // FIXME: not implemented + } + + /** + * Expands path if it is not expanded, or collapses row if it is expanded. If + * expanding a path and JTree scroll on expand, ensureRowsAreVisible is + * invoked to scroll as many of the children to visible as possible (tries to + * scroll to last visible descendant of path). + * + * @param path the path we are concerned with + */ + protected void toggleExpandState(TreePath path) + { + // FIXME: not implemented + } + + /** + * Returning true signifies a mouse event on the node should toggle the + * selection of only the row under the mouse. + * + * @param event is the MouseEvent performed on the row. + * @return true signifies a mouse event on the node should toggle the + * selection of only the row under the mouse. + */ + protected boolean isToggleSelectionEvent(MouseEvent event) + { + // FIXME: not implemented + return false; + } + + /** + * Returning true signifies a mouse event on the node should select from the + * anchor point. + * + * @param event is the MouseEvent performed on the node. + * @return true signifies a mouse event on the node should select from the + * anchor point. + */ + protected boolean isMultiSelectEvent(MouseEvent event) + { + // FIXME: not implemented + return false; + } + + /** + * Returning true indicates the row under the mouse should be toggled based + * on the event. This is invoked after checkForClickInExpandControl, implying + * the location is not in the expand (toggle) control. + * + * @param event is the MouseEvent performed on the row. + * @return true indicates the row under the mouse should be toggled based on + * the event. + */ + protected boolean isToggleEvent(MouseEvent event) + { + // FIXME: not implemented + return false; + } + + /** + * Messaged to update the selection based on a MouseEvent over a particular + * row. If the even is a toggle selection event, the row is either selected, + * or deselected. If the event identifies a multi selection event, the + * selection is updated from the anchor point. Otherwise, the row is + * selected, and if the even specified a toggle event the row is + * expanded/collapsed. + * + * @param path is the path selected for an event + * @param event is the MouseEvent performed on the path. + */ + protected void selectPathForEvent(TreePath path, MouseEvent event) + { + // FIXME: not implemented + } + + /** + * Returns true if the node at <code>row</code> is a leaf. + * + * @param row is the row we are concerned with. + * @return true if the node at <code>row</code> is a leaf. + */ + protected boolean isLeaf(int row) + { + TreePath pathForRow = getPathForRow(tree, row); + if (pathForRow == null) + return true; + + Object node = pathForRow.getLastPathComponent(); + + if (node instanceof TreeNode) + return ((TreeNode) node).isLeaf(); + else + return true; + } + + /** + * Selects the specified path in the tree depending on modes. + * Package private for use in inner classes. + * + * @param tree is the tree we are selecting the path in + * @param path is the path we are selecting + */ + void selectPath(JTree tree, TreePath path) + { + if (path != null) + { + if (tree.isPathSelected(path)) + tree.removeSelectionPath(path); + else if (tree.getSelectionModel().getSelectionMode() + == TreeSelectionModel.SINGLE_TREE_SELECTION) + { + tree.getSelectionModel().clearSelection(); + tree.addSelectionPath(path); + tree.setLeadSelectionPath(path); + } + else if (tree.getSelectionModel().getSelectionMode() + == TreeSelectionModel.CONTIGUOUS_TREE_SELECTION) + { + // TODO + } + else + { + tree.getSelectionModel().setSelectionMode( + TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); + tree.addSelectionPath(path); + tree.setLeadSelectionPath(path); + } + } + } + + /* * INTERNAL CLASSES * */ + + /** + * Updates the preferred size when scrolling, if necessary. + */ + public class ComponentHandler + extends ComponentAdapter + implements ActionListener + { + /** + * Timer used when inside a scrollpane and the scrollbar is adjusting + */ + protected Timer timer; + + /** ScrollBar that is being adjusted */ + protected JScrollBar scrollBar; + + /** + * Constructor + */ + public ComponentHandler() + { + } + + /** + * Invoked when the component's position changes. + * + * @param e the event that occurs when moving the component + */ + public void componentMoved(ComponentEvent e) + { + } + + /** + * Creats, if necessary, and starts a Timer to check if needed to resize + * the bounds + */ + protected void startTimer() + { + } + + /** + * Returns the JScrollPane housing the JTree, or null if one isn't found. + * + * @return JScrollPane housing the JTree, or null if one isn't found. + */ + protected JScrollPane getScrollPane() + { + return null; + } + + /** + * Public as a result of Timer. If the scrollBar is null, or not + * adjusting, this stops the timer and updates the sizing. + * + * @param ae is the action performed + */ + public void actionPerformed(ActionEvent ae) + { + } + }// ComponentHandler + + /** + * Listener responsible for getting cell editing events and updating the tree + * accordingly. + */ + public class CellEditorHandler + implements CellEditorListener + { + /** + * Constructor + */ + public CellEditorHandler() + { + } + + /** + * Messaged when editing has stopped in the tree. Tells the listeners + * editing has stopped. + * + * @param e is the notification event + */ + public void editingStopped(ChangeEvent e) + { + } + + /** + * Messaged when editing has been canceled in the tree. This tells the + * listeners the editor has canceled editing. + * + * @param e is the notification event + */ + public void editingCanceled(ChangeEvent e) + { + } + }// CellEditorHandler + + /** + * Repaints the lead selection row when focus is lost/grained. + */ + public class FocusHandler + implements FocusListener + { + /** + * Constructor + */ + public FocusHandler() + { + } + + /** + * Invoked when focus is activated on the tree we're in, redraws the lead + * row. Invoked when a component gains the keyboard focus. + * + * @param e is the focus event that is activated + */ + public void focusGained(FocusEvent e) + { + } + + /** + * Invoked when focus is deactivated on the tree we're in, redraws the + * lead row. Invoked when a component loses the keyboard focus. + * + * @param e is the focus event that is deactivated + */ + public void focusLost(FocusEvent e) + { + } + }// FocusHandler + + /** + * This is used to get multiple key down events to appropriately genereate + * events. + */ + public class KeyHandler + extends KeyAdapter + { + /** Key code that is being generated for. */ + protected Action repeatKeyAction; + + /** Set to true while keyPressed is active */ + protected boolean isKeyDown; + + /** + * Constructor + */ + public KeyHandler() + { + } + + /** + * Invoked when a key has been typed. Moves the keyboard focus to the + * first element whose first letter matches the alphanumeric key pressed + * by the user. Subsequent same key presses move the keyboard focus to the + * next object that starts with the same letter. + * + * @param e the key typed + */ + public void keyTyped(KeyEvent e) + { + } + + /** + * Invoked when a key has been pressed. + * + * @param e the key pressed + */ + public void keyPressed(KeyEvent e) + { + TreePath start = BasicTreeUI.this.tree.getLeadSelectionPath(); + DefaultMutableTreeNode last = null; + + if (start != null) + last = (DefaultMutableTreeNode) start.getLastPathComponent(); + if (last != null) + { + if (e.getKeyCode() == KeyEvent.VK_DOWN) + { + DefaultMutableTreeNode next = (DefaultMutableTreeNode) + BasicTreeUI.this.getNextVisibleNode(last); + + if (next != null) + BasicTreeUI.this.selectPath(BasicTreeUI.this.tree, + new TreePath(next.getPath())); + } + else if (e.getKeyCode() == KeyEvent.VK_UP) + { + DefaultMutableTreeNode prev = (DefaultMutableTreeNode) + BasicTreeUI.this.getPreviousVisibleNode(last); + + if (prev != null) + BasicTreeUI.this.selectPath(BasicTreeUI.this.tree, + new TreePath(prev.getPath())); + } + else if (e.getKeyCode() == KeyEvent.VK_LEFT) + { + TreePath path = new TreePath(last.getPath()); + + if (!last.isLeaf() && BasicTreeUI.this.tree.isExpanded(path)) + { + BasicTreeUI.this.tree.collapsePath(path); + BasicTreeUI.this.tree.fireTreeCollapsed(path); + } + } + else if (e.getKeyCode() == KeyEvent.VK_RIGHT) + { + TreePath path = new TreePath(last.getPath()); + + if (!last.isLeaf() && BasicTreeUI.this.tree.isCollapsed(path)) + { + BasicTreeUI.this.tree.expandPath(path); + BasicTreeUI.this.tree.fireTreeExpanded(path); + } + } + } + } + + /** + * Invoked when a key has been released + * + * @param e the key released + */ + public void keyReleased(KeyEvent e) + { + } + }// KeyHandler + + /** + * MouseListener is responsible for updating the selevtion based on mouse + * events. + */ + public class MouseHandler + extends MouseAdapter + implements MouseMotionListener + { + /** + * Constructor + */ + public MouseHandler() + { + } + + /** + * Invoked when a mouse button has been pressed on a component. + * + * @param e is the mouse event that occured + */ + public void mousePressed(MouseEvent e) + { + } + + /** + * Invoked when a mouse button is pressed on a component and then dragged. + * MOUSE_DRAGGED events will continue to be delivered to the component + * where the drag originated until the mouse button is released + * (regardless of whether the mouse position is within the bounds of the + * component). + * + * @param e is the mouse event that occured + */ + public void mouseDragged(MouseEvent e) + { + } + + /** + * Invoked when the mouse button has been moved on a component (with no + * buttons no down). + * + * @param e the mouse event that occured + */ + public void mouseMoved(MouseEvent e) + { + } + + /** + * Invoked when a mouse button has been released on a component. + * + * @param e is the mouse event that occured + */ + public void mouseReleased(MouseEvent e) + { + } + }// MouseHandler + + /** + * MouseInputHandler handles passing all mouse events, including mouse motion + * events, until the mouse is released to the destination it is constructed + * with. + */ + public class MouseInputHandler + implements MouseInputListener + { + /** Source that events are coming from */ + protected Component source; + + /** Destination that receives all events. */ + protected Component destination; + + /** Number of mouse clicks on a non-leaf */ + private int clickCount = 0; + + /** + * Constructor + * + * @param source that events are coming from + * @param destination that receives all events + * @param event is the event received + */ + public MouseInputHandler(Component source, Component destination, + MouseEvent e) + { + } + + /** + * Invoked when the mouse button has been clicked (pressed and released) + * on a component. + * + * @param e mouse event that occured + */ + public void mouseClicked(MouseEvent e) + { + Point click = e.getPoint(); + int clickX = (int) click.getX(); + int clickY = (int) click.getY(); + int row = (clickY / getRowHeight()) - 1; + TreePath path = BasicTreeUI.this.tree.getPathForRow(row); + + boolean inBounds = false; + boolean cntlClick = false; + Rectangle bounds = BasicTreeUI.this.getPathBounds( + BasicTreeUI.this.tree, path); + int x = (int) bounds.getX(); + int y = (int) bounds.getY(); + + if (clickY > y && clickY < (y + bounds.height + 10)) + { + if (clickX > x && clickX < (x + bounds.width + 20)) + inBounds = true; + else if (clickX < (x - rightChildIndent + 5) && + clickX > (x - rightChildIndent - 5)) + cntlClick = true; + } + + if ((inBounds || cntlClick) && path != null && + BasicTreeUI.this.tree.isVisible(path)) + { + if (!cntlClick && !BasicTreeUI.this.isLeaf(row)) + clickCount++; + + if (clickCount == 2 || cntlClick == true) + { + clickCount = 0; + BasicTreeUI.this.tree.getSelectionModel().clearSelection(); + if (BasicTreeUI.this.tree.isExpanded(path)) + { + BasicTreeUI.this.tree.collapsePath(path); + BasicTreeUI.this.tree.fireTreeCollapsed(path); + } + else + { + BasicTreeUI.this.tree.expandPath(path); + BasicTreeUI.this.tree.fireTreeExpanded(path); + } + } + + BasicTreeUI.this.selectPath(BasicTreeUI.this.tree, path); + } + } + + /** + * Invoked when a mouse button has been pressed on a component. + * + * @param e mouse event that occured + */ + public void mousePressed(MouseEvent e) + { + } + + /** + * Invoked when a mouse button has been released on a component. + * + * @param e mouse event that occured + */ + public void mouseReleased(MouseEvent e) + { + } + + /** + * Invoked when the mouse enters a component. + * + * @param e mouse event that occured + */ + public void mouseEntered(MouseEvent e) + { + } + + /** + * Invoked when the mouse exits a component. + * + * @param e mouse event that occured + */ + public void mouseExited(MouseEvent e) + { + } + + /** + * Invoked when a mouse button is pressed on a component and then dragged. + * MOUSE_DRAGGED events will continue to be delivered to the component + * where the drag originated until the mouse button is released + * (regardless of whether the mouse position is within the bounds of the + * component). + * + * @param e mouse event that occured + */ + public void mouseDragged(MouseEvent e) + { + } + + /** + * Invoked when the mouse cursor has been moved onto a component but no + * buttons have been pushed. + * + * @param e mouse event that occured + */ + public void mouseMoved(MouseEvent e) + { + } + + /** + * Removes event from the source + */ + protected void removeFromSource() + { + } + }// MouseInputHandler + + /** + * Class responsible for getting size of node, method is forwarded to + * BasicTreeUI method. X location does not include insets, that is handled in + * getPathBounds. + */ + public class NodeDimensionsHandler + extends AbstractLayoutCache.NodeDimensions + { + /** + * Constructor + */ + public NodeDimensionsHandler() + { + } + + /** + * Responsible for getting the size of a particular node. + * + * @param value the value to be represented + * @param row row being queried + * @param depth the depth of the row + * @param expanded true if row is expanded + * @param size a Rectangle containing the size needed to represent value + * @return containing the node dimensions, or null if node has no + * dimension + */ + public Rectangle getNodeDimensions(Object value, int row, int depth, + boolean expanded, Rectangle size) + { + return null; + } + + /** + * Returns the amount to indent the given row + * + * @return amount to indent the given row. + */ + protected int getRowX(int row, int depth) + { + return 0; + } + }// NodeDimensionsHandler + + /** + * PropertyChangeListener for the tree. Updates the appropriate varaible, or + * TreeState, based on what changes. + */ + public class PropertyChangeHandler + implements PropertyChangeListener + { + + /** + * Constructor + */ + public PropertyChangeHandler() + { + } + + /** + * This method gets called when a bound property is changed. + * + * @param event A PropertyChangeEvent object describing the event source + * and the property that has changed. + */ + public void propertyChange(PropertyChangeEvent event) + { + } + }// PropertyChangeHandler + + /** + * Listener on the TreeSelectionModel, resets the row selection if any of the + * properties of the model change. + */ + public class SelectionModelPropertyChangeHandler + implements PropertyChangeListener + { + + /** + * Constructor + */ + public SelectionModelPropertyChangeHandler() + { + } + + /** + * This method gets called when a bound property is changed. + * + * @param event A PropertyChangeEvent object describing the event source + * and the property that has changed. + */ + public void propertyChange(PropertyChangeEvent event) + { + } + }// SelectionModelPropertyChangeHandler + + /** + * ActionListener that invokes cancelEditing when action performed. + */ + public class TreeCancelEditingAction + extends AbstractAction + { + + /** + * Constructor + */ + public TreeCancelEditingAction() + { + } + + /** + * Invoked when an action occurs. + * + * @param e event that occured + */ + public void actionPerformed(ActionEvent e) + { + } + + /** + * Returns true if the action is enabled. + * + * @return true if the action is enabled, false otherwise + */ + public boolean isEnabled() + { + return false; + } + }// TreeCancelEditingAction + + /** + * Updates the TreeState in response to nodes expanding/collapsing. + */ + public class TreeExpansionHandler + implements TreeExpansionListener + { + + /** + * Constructor + */ + public TreeExpansionHandler() + { + } + + /** + * Called whenever an item in the tree has been expanded. + * + * @param event is the event that occured + */ + public void treeExpanded(TreeExpansionEvent event) + { + BasicTreeUI.this.tree.repaint(); + } + + /** + * Called whenever an item in the tree has been collapsed. + * + * @param event is the event that occured + */ + public void treeCollapsed(TreeExpansionEvent event) + { + BasicTreeUI.this.tree.repaint(); + } + }// TreeExpansionHandler + + /** + * TreeHomeAction is used to handle end/home actions. Scrolls either the + * first or last cell to be visible based on direction. + */ + public class TreeHomeAction + extends AbstractAction + { + + /** direction is either home or end */ + protected int direction; + + /** + * Constructor + * + * @param direction - it is home or end + * @param name is the name of the direction + */ + public TreeHomeAction(int direction, String name) + { + } + + /** + * Invoked when an action occurs. + * + * @param e is the event that occured + */ + public void actionPerformed(ActionEvent e) + { + } + + /** + * Returns true if the action is enabled. + * + * @return true if the action is enabled. + */ + public boolean isEnabled() + { + return false; + } + }// TreeHomeAction + + /** + * TreeIncrementAction is used to handle up/down actions. Selection is moved + * up or down based on direction. + */ + public class TreeIncrementAction + extends AbstractAction + { + + /** Specifies the direction to adjust the selection by. */ + protected int direction; + + /** + * Constructor + * + * @param direction up or down + * @param name is the name of the direction + */ + public TreeIncrementAction(int direction, String name) + { + } + + /** + * Invoked when an action occurs. + * + * @param e is the event that occured + */ + public void actionPerformed(ActionEvent e) + { + } + + /** + * Returns true if the action is enabled. + * + * @return true if the action is enabled. + */ + public boolean isEnabled() + { + return false; + } + }// TreeIncrementAction + + /** + * Forwards all TreeModel events to the TreeState. + */ + public class TreeModelHandler + implements TreeModelListener + { + /** + * Constructor + */ + public TreeModelHandler() + { + } + + /** + * Invoked after a node (or a set of siblings) has changed in some way. + * The node(s) have not changed locations in the tree or altered their + * children arrays, but other attributes have changed and may affect + * presentation. Example: the name of a file has changed, but it is in the + * same location in the file system. To indicate the root has changed, + * childIndices and children will be null. Use e.getPath() to get the + * parent of the changed node(s). e.getChildIndices() returns the + * index(es) of the changed node(s). + * + * @param e is the event that occured + */ + public void treeNodesChanged(TreeModelEvent e) + { + } + + /** + * Invoked after nodes have been inserted into the tree. Use e.getPath() + * to get the parent of the new node(s). e.getChildIndices() returns the + * index(es) of the new node(s) in ascending order. + * + * @param e is the event that occured + */ + public void treeNodesInserted(TreeModelEvent e) + { + } + + /** + * Invoked after nodes have been removed from the tree. Note that if a + * subtree is removed from the tree, this method may only be invoked once + * for the root of the removed subtree, not once for each individual set + * of siblings removed. Use e.getPath() to get the former parent of the + * deleted node(s). e.getChildIndices() returns, in ascending order, the + * index(es) the node(s) had before being deleted. + * + * @param e is the event that occured + */ + public void treeNodesRemoved(TreeModelEvent e) + { + } + + /** + * Invoked after the tree has drastically changed structure from a given + * node down. If the path returned by e.getPath() is of length one and the + * first element does not identify the current root node the first element + * should become the new root of the tree. Use e.getPath() to get the path + * to the node. e.getChildIndices() returns null. + * + * @param e is the event that occured + */ + public void treeStructureChanged(TreeModelEvent e) + { + } + }// TreeModelHandler + + /** + * TreePageAction handles page up and page down events. + */ + public class TreePageAction + extends AbstractAction + { + /** Specifies the direction to adjust the selection by. */ + protected int direction; + + /** + * Constructor + * + * @param direction up or down + * @param name is the name of the direction + */ + public TreePageAction(int direction, String name) + { + } + + /** + * Invoked when an action occurs. + * + * @param e is the event that occured + */ + public void actionPerformed(ActionEvent e) + { + } + + /** + * Returns true if the action is enabled. + * + * @return true if the action is enabled. + */ + public boolean isEnabled() + { + return false; + } + }// TreePageAction + + /** + * Listens for changes in the selection model and updates the display + * accordingly. + */ + public class TreeSelectionHandler + implements TreeSelectionListener + { + /** + * Constructor + */ + public TreeSelectionHandler() + { + } + + /** + * Messaged when the selection changes in the tree we're displaying for. + * Stops editing, messages super and displays the changed paths. + * + * @param event the event that characterizes the change. + */ + public void valueChanged(TreeSelectionEvent event) + { + } + }// TreeSelectionHandler + + /** + * For the first selected row expandedness will be toggled. + */ + public class TreeToggleAction + extends AbstractAction + { + /** + * Constructor + * + * @param name is the name of <code>Action</code> field + */ + public TreeToggleAction(String name) + { + } + + /** + * Invoked when an action occurs. + * + * @param e the event that occured + */ + public void actionPerformed(ActionEvent e) + { + } + + /** + * Returns true if the action is enabled. + * + * @return true if the action is enabled, false otherwise + */ + public boolean isEnabled() + { + return false; + } + } // TreeToggleAction + + /** + * TreeTraverseAction is the action used for left/right keys. Will toggle + * the expandedness of a node, as well as potentially incrementing the + * selection. + */ + public class TreeTraverseAction + extends AbstractAction + { + /** + * Determines direction to traverse, 1 means expand, -1 means collapse. + */ + protected int direction; + + /** + * Constructor + * + * @param direction to traverse + * @param name is the name of the direction + */ + public TreeTraverseAction(int direction, String name) + { + } + + /** + * Invoked when an action occurs. + * + * @param e the event that occured + */ + public void actionPerformed(ActionEvent e) + { + } + + /** + * Returns true if the action is enabled. + * + * @return true if the action is enabled, false otherwise + */ + public boolean isEnabled() + { + return false; + } + } // TreeTraverseAction + + /** + * Returns the cell bounds for painting selected cells + * + * @param x is the x location of the cell + * @param y is the y location of the cell + * @param cell is the Object to get the bounds for + * + * @returns Rectangle that represents the cell bounds + */ + private Rectangle getCellBounds(int x, int y, Object cell) + { + if (cell != null) + { + String s = cell.toString(); + Font f = tree.getFont(); + FontMetrics fm = tree.getToolkit().getFontMetrics(tree.getFont()); + + return new Rectangle(x, y, SwingUtilities.computeStringWidth(fm, s), + fm.getHeight()); + } + return null; + } + + /** + * Retrieves the location of some node, recursively starting at from + * some node. + * + * @param x is the starting x position, offset + * @param y is the starting y position, offset + * @param tree is the tree to traverse + * @param mod is the TreeModel to use + * @param node is the node to get the location for + * @param startNode is the node to start searching from + * + * @return Point - the location of node + */ + private Point getCellLocation(int x, int y, JTree tree, TreeModel mod, + Object node, Object startNode) + { + int rowHeight = getRowHeight(); + if (startNode == null || startNode.equals(node)) + return new Point(x + ((((DefaultMutableTreeNode) node). + getLevel() + 1) * rightChildIndent), y); + + if (!mod.isLeaf(startNode) + && tree.isExpanded(new TreePath( + ((DefaultMutableTreeNode) startNode).getPath()))) + { + Object child = mod.getChild(startNode, 0); + if (child != null) + return getCellLocation(x, y + rowHeight, tree, mod, + node, child); + } + + return getCellLocation(x, y + rowHeight, tree, mod, node, + getNextVisibleNode((DefaultMutableTreeNode) startNode)); + } + + /** + * Paints a leaf in the tree + * + * @param g the Graphics context in which to paint + * @param x the x location of the leaf + * @param y the y location of the leaf + * @param tree the tree to draw on + * @param leaf the object to draw + */ + private void paintLeaf(Graphics g, int x, int y, JTree tree, Object leaf) + { + TreePath curr = new TreePath(((DefaultMutableTreeNode) leaf).getPath()); + boolean selected = tree.isPathSelected(curr); + + if (tree.isVisible(curr)) + { + DefaultTreeCellRenderer dtcr = (DefaultTreeCellRenderer) + tree.getCellRenderer(); + boolean hasIcons = false; + Icon li = dtcr.getLeafIcon(); + if (li != null) + hasIcons = true; + + if (selected) + { + Component c = dtcr.getTreeCellRendererComponent(tree, leaf, + true, false, true, 0, false); + + if (hasIcons) + { + li.paintIcon(c, g, x, y + 2); + x += li.getIconWidth() + 4; + } + rendererPane.paintComponent(g, c, tree, + getCellBounds(x, y, leaf)); + } + else + { + Component c = dtcr.getTreeCellRendererComponent( + tree, leaf, false, false, true, 0, false); + + g.translate(x, y); + + if (hasIcons) + { + Component icon = dtcr.getTreeCellRendererComponent(tree, + li, false, false, true, 0, false); + icon.paint(g); + } + + c.paint(g); + g.translate(-x, -y); + } + } + } + + /** + * Paints a non-leaf in the tree + * + * @param g the Graphics context in which to paint + * @param x the x location of the non-leaf + * @param y the y location of the non-leaf + * @param tree the tree to draw on + * @param nonLeaf the object to draw + */ + private void paintNonLeaf(Graphics g, int x, int y, JTree tree, + Object nonLeaf) + { + TreePath curr = new TreePath(((DefaultMutableTreeNode) nonLeaf).getPath()); + boolean selected = tree.isPathSelected(curr); + boolean expanded = tree.isExpanded(curr); + + if (tree.isVisible(curr)) + { + DefaultTreeCellRenderer dtcr = (DefaultTreeCellRenderer) + tree.getCellRenderer(); + boolean hasIcons = false; + boolean hasOtherIcons = false; + Icon oi = dtcr.getOpenIcon(); + Icon ci = dtcr.getClosedIcon(); + + if (oi != null || ci != null) + hasIcons = true; + + if (selected) + { + Component c = dtcr.getTreeCellRendererComponent(tree, nonLeaf, + true, expanded, false, 0, false); + + if (hasIcons) + { + if (expanded) + { + oi.paintIcon(c, g, x, y + 2); + x += (oi.getIconWidth() + 4); + } + else + { + ci.paintIcon(c, g, x, y + 2); + x += (ci.getIconWidth() + 4); + } + + } + rendererPane.paintComponent(g, c, tree, + getCellBounds(x, y, nonLeaf)); + } + else + { + Component c = dtcr.getTreeCellRendererComponent(tree, nonLeaf, + false, expanded, false, 0, false); + g.translate(x, y); + + if (hasIcons) + { + Component icon; + if (expanded) + icon = dtcr.getTreeCellRendererComponent(tree, + oi, false, false, false, 0, false); + else + icon = dtcr.getTreeCellRendererComponent(tree, + ci, false, false, false, 0, false); + + icon.paint(g); + } + c.paint(g); + g.translate(-x, -y); + } + } + } + + /** + * Recursively paints all elements of the tree + * + * @param g the Graphics context in which to paint + * @param indentation of the current object + * @param descent is the number of elements drawn + * @param childNumber is the index of the current child in the tree + * @param depth is the depth of the current object in the tree + * @param tree is the tree to draw to + * @param mod is the TreeModel we are using to draw + * @param curr is the current object to draw + * + * @return int - current descent of the tree + */ + private int paintRecursive(Graphics g, int indentation, int descent, + int childNumber, int depth, JTree tree, TreeModel mod, Object curr) + { + Rectangle clip = g.getClipBounds(); + if (indentation > clip.x + clip.width + rightChildIndent + || descent > clip.y + clip.height + getRowHeight()) + return descent; + + int halfHeight = getRowHeight() / 2; + int halfWidth = rightChildIndent / 2; + int y0 = descent + halfHeight; + int heightOfLine = descent + halfHeight; + + if (mod.isLeaf(curr)) + { + paintLeaf(g, indentation + 4, descent, tree, curr); + descent += getRowHeight(); + } + else + { + if (depth > 0 || tree.isRootVisible()) + { + paintNonLeaf(g, indentation + 4, descent, tree, curr); + descent += getRowHeight(); + y0 += halfHeight; + } + + int max = mod.getChildCount(curr); + if (tree.isExpanded(new TreePath(((DefaultMutableTreeNode) curr) + .getPath()))) + { + for (int i = 0; i < max; ++i) + { + g.setColor(getHashColor()); + heightOfLine = descent + halfHeight; + g.drawLine(indentation + halfWidth, heightOfLine, + indentation + rightChildIndent, heightOfLine); + + descent = paintRecursive(g, indentation + rightChildIndent, + descent, i, depth + 1, tree, mod, mod.getChild(curr, i)); + } + } + } + + if (tree.isExpanded(new TreePath(((DefaultMutableTreeNode) curr) + .getPath()))) + if (y0 != heightOfLine) + { + g.setColor(getHashColor()); + g.drawLine(indentation + halfWidth, y0, indentation + halfWidth, + heightOfLine); + } + + return descent; + } + + /** + * Recursively paints all the control icons on the tree. + * + * @param g the Graphics context in which to paint + * @param indentation of the current object + * @param descent is the number of elements drawn + * @param childNumber is the index of the current child in the tree + * @param depth is the depth of the current object in the tree + * @param tree is the tree to draw to + * @param mod is the TreeModel we are using to draw + * @param curr is the current object to draw + * + * @return int - current descent of the tree + */ + private int paintControlIcons(Graphics g, int indentation, int descent, + int childNumber, int depth, JTree tree, TreeModel mod, Object node) + { + int h = descent; + int rowHeight = getRowHeight(); + Icon ei = UIManager.getLookAndFeelDefaults(). + getIcon("Tree.expandedIcon"); + Icon ci = UIManager.getLookAndFeelDefaults(). + getIcon("Tree.collapsedIcon"); + Rectangle clip = g.getClipBounds(); + if (ci == null || ei == null || indentation > clip.x + clip.width + + rightChildIndent || descent > clip.y + clip.height + + getRowHeight()) + return descent; + + if (mod.isLeaf(node)) + descent += rowHeight; + else + { + if (depth > 0 || tree.isRootVisible()) + descent += rowHeight; + + int max = mod.getChildCount(node); + if (tree.isExpanded(new TreePath(((DefaultMutableTreeNode) node) + .getPath()))) + { + if (!node.equals(mod.getRoot())) + ei.paintIcon(tree, g, indentation - rightChildIndent - 3, h); + + for (int i = 0; i < max; ++i) + { + descent = paintControlIcons(g, indentation + rightChildIndent, + descent, i, depth + 1, tree, mod, mod.getChild(node, i)); + } + } + else if (!node.equals(mod.getRoot())) + ci.paintIcon(tree, g, indentation - rightChildIndent - 3, + descent - getRowHeight()); + } + + return descent; + } +} // BasicTreeUI
\ No newline at end of file diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicViewportUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicViewportUI.java new file mode 100644 index 0000000..8ce772b --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/BasicViewportUI.java @@ -0,0 +1,234 @@ +/* BasicViewportUI.java -- + Copyright (C) 2002, 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Image; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.image.ImageObserver; + +import javax.swing.JComponent; +import javax.swing.JViewport; +import javax.swing.ViewportLayout; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.ViewportUI; + +public class BasicViewportUI extends ViewportUI +{ + + ChangeListener changeListener; + Image backingStoreImage; + int backingStoreWidth = -1; + int backingStoreHeight = -1; + + class ChangeHandler implements ChangeListener + { + public void stateChanged(ChangeEvent event) + { + JViewport v = (JViewport) event.getSource(); + v.repaint(); + } + } + + void installDefaults(JComponent c) + { + c.setOpaque(true); + } + + void uninstallDefaults(JComponent c) + { + } + + void installListeners(JComponent c) + { + ((JViewport)c).addChangeListener(changeListener); + } + + void uninstallListeners(JComponent c) + { + ((JViewport)c).removeChangeListener(changeListener); + } + + public BasicViewportUI() + { + changeListener = new ChangeHandler(); + } + + public static ComponentUI createUI(JComponent c) + { + return new BasicViewportUI(); + } + + public void installUI(JComponent c) + { + super.installUI(c); + installListeners(c); + } + + public void uninstallUI(JComponent c) + { + uninstallListeners(c); + } + + + public Dimension getPreferredSize(JComponent c) + { + // let the ViewportLayout decide + return null; + } + + public void paint(Graphics g, JComponent c) + { + JViewport port = (JViewport)c; + Component view = port.getView(); + + if (view == null) + return; + + Point pos = port.getViewPosition(); + Rectangle viewBounds = view.getBounds(); + Rectangle portBounds = port.getBounds(); + + if (viewBounds.width == 0 + || viewBounds.height == 0 + || portBounds.width == 0 + || portBounds.height == 0) + return; + + switch (port.getScrollMode()) + { + + case JViewport.BACKINGSTORE_SCROLL_MODE: + paintBackingStore(g, port, view, pos, viewBounds, portBounds); + break; + + case JViewport.BLIT_SCROLL_MODE: + // FIXME: implement separate blit mode + + case JViewport.SIMPLE_SCROLL_MODE: + default: + paintSimple(g, port, view, pos, viewBounds, portBounds); + break; + } + } + + private void paintSimple(Graphics g, + JViewport v, + Component view, + Point pos, + Rectangle viewBounds, + Rectangle portBounds) + { + Rectangle oldClip = g.getClipBounds (); + g.setClip (oldClip.intersection (viewBounds)); + g.translate (-pos.x, -pos.y); + try + { + view.paint(g); + } + finally + { + g.translate (pos.x, pos.y); + g.setClip (oldClip); + } + } + + private void paintBackingStore(Graphics g, + JViewport v, + Component view, + Point pos, + Rectangle viewBounds, + Rectangle portBounds) + { + if (backingStoreImage == null + || backingStoreWidth != viewBounds.width + || backingStoreHeight != viewBounds.height) + { + backingStoreImage = v.createImage(viewBounds.width, viewBounds.height); + backingStoreWidth = viewBounds.width; + backingStoreHeight = viewBounds.height; + } + + Graphics g2 = backingStoreImage.getGraphics(); + + if (v.getBackground() != null) + { + // fill the backing store background + java.awt.Color save = g2.getColor(); + g2.setColor(v.getBackground()); + g2.fillRect (0, 0, backingStoreWidth, backingStoreHeight); + g2.setColor(save); + + // fill the viewport background + save = g.getColor(); + g.setColor(v.getBackground()); + g.fillRect (0, 0, portBounds.width, portBounds.height); + g.setColor(save); + + } + else + { + // clear the backing store background + g2.clearRect(0, 0, backingStoreWidth, backingStoreHeight); + + // clear the viewport background + g.clearRect(0, 0, portBounds.width, portBounds.height); + } + + g2.setClip(g.getClipBounds()); + g2.translate(-pos.x, -pos.y); + try + { + view.paint(g2); + } + finally + { + g2.translate(pos.x, pos.y); + } + g2 = null; + g.drawImage(backingStoreImage, + 0, 0, + (ImageObserver)null); + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/ComboPopup.java b/libjava/classpath/javax/swing/plaf/basic/ComboPopup.java new file mode 100644 index 0000000..8bdcc51 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/ComboPopup.java @@ -0,0 +1,103 @@ +/* ComboPopup.java -- + Copyright (C) 2004 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.basic; + +import java.awt.event.KeyListener; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; + +import javax.swing.JList; + +public interface ComboPopup +{ + /** + * This method display popup menu containing list of JComboBox's items to + * the screen + */ + void show(); + + /** + * This method hides popup menu with list of JComboBox's item from the + * screen + */ + void hide(); + + /** + * Retursn true if popup menu with JComboBOx's item is currently visible on + * the screen and false otherwise + * + * @return true if JComboBox's popup menu with list of items is currently + * visible on the screen and false otherwise. + */ + boolean isVisible(); + + /** + * Return JList that is used to draw cells of the JComboBox. + * + * @return JList that is used to draw cells of the JcomboBox + */ + JList getList(); + + /** + * This method returns MouseListener that listen's to mouse events occuring + * in the combo box + * + * @return MouseListenere + */ + MouseListener getMouseListener(); + + /** + * This method returns MouseListener that listen's to mouse events occuring + * in the combo box. + * + * @return MouseMotionListener + */ + MouseMotionListener getMouseMotionListener(); + + /** + * This method returns KeyListener that listen's to key events occuring in + * the combo box. + * + * @return KeyListener + */ + KeyListener getKeyListener(); + + /* This method removes any listeners that were installed */ + void uninstallingUI(); +} diff --git a/libjava/classpath/javax/swing/plaf/basic/DefaultMenuLayout.java b/libjava/classpath/javax/swing/plaf/basic/DefaultMenuLayout.java new file mode 100644 index 0000000..9760e82 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/DefaultMenuLayout.java @@ -0,0 +1,78 @@ +/* DefaultMenuLayout.java + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf.basic; + +import java.awt.Container; +import java.awt.Dimension; + +import javax.swing.BoxLayout; +import javax.swing.plaf.UIResource; + +/** + * The LayoutManager that is used in PopupMenus. This is a derived from + * {@link BoxLayout}. + * + * @author Roman Kennke (roman@kennke.org) + */ +public class DefaultMenuLayout + extends BoxLayout + implements UIResource +{ + + /** + * Creates a new instance of DefaultMenuLayout. + * + * @param target the component that is laid out + * @param axis the axis along which the component is laid out + */ + public DefaultMenuLayout(Container target, int axis) + { + super(target, axis); + } + + /** + * Returns the preferred size for the layout of the menu. + * + * @param target the Container which's preferred size we calculate + */ + public Dimension preferredLayoutSize(Container target) + { + return super.preferredLayoutSize(target); + } + +} diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders-1.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders-1.png Binary files differnew file mode 100644 index 0000000..daeb16c --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders-1.png diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders-2.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders-2.png Binary files differnew file mode 100644 index 0000000..60f6a8a --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders-2.png diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.ButtonBorder-1.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.ButtonBorder-1.png Binary files differnew file mode 100644 index 0000000..54047dc --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.ButtonBorder-1.png diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.FieldBorder-1.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.FieldBorder-1.png Binary files differnew file mode 100644 index 0000000..7c89911 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.FieldBorder-1.png diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.MarginBorder-1.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.MarginBorder-1.png Binary files differnew file mode 100644 index 0000000..a3841ba --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.MarginBorder-1.png diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.MenuBarBorder-1.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.MenuBarBorder-1.png Binary files differnew file mode 100644 index 0000000..13a9fa4e --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.MenuBarBorder-1.png diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.RadioButtonBorder-1.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.RadioButtonBorder-1.png Binary files differnew file mode 100644 index 0000000..a6408ec --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.RadioButtonBorder-1.png diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.SplitPaneBorder-1.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.SplitPaneBorder-1.png Binary files differnew file mode 100644 index 0000000..db283c2 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.SplitPaneBorder-1.png diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.SplitPaneBorder-2.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.SplitPaneBorder-2.png Binary files differnew file mode 100644 index 0000000..65381bd --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.SplitPaneBorder-2.png diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.SplitPaneDividerBorder-1.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.SplitPaneDividerBorder-1.png Binary files differnew file mode 100644 index 0000000..c22763a --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.SplitPaneDividerBorder-1.png diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.ToggleButtonBorder-1.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.ToggleButtonBorder-1.png Binary files differnew file mode 100644 index 0000000..f898bee --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.ToggleButtonBorder-1.png diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-1.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-1.png Binary files differnew file mode 100644 index 0000000..99f8c6e --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-1.png diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-2.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-2.png Binary files differnew file mode 100644 index 0000000..59d9a61 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-2.png diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-3.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-3.png Binary files differnew file mode 100644 index 0000000..5b0971c --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-3.png diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-4.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-4.png Binary files differnew file mode 100644 index 0000000..ceba0b6e --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-4.png diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-5.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-5.png Binary files differnew file mode 100644 index 0000000..fa3055f --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-5.png diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-6.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-6.png Binary files differnew file mode 100644 index 0000000..c760313 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-6.png diff --git a/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-7.png b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-7.png Binary files differnew file mode 100644 index 0000000..6a557a0 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-7.png diff --git a/libjava/classpath/javax/swing/plaf/basic/package.html b/libjava/classpath/javax/swing/plaf/basic/package.html new file mode 100644 index 0000000..700c8cd --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/basic/package.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in javax.swing.plaf.basic package. + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. --> + +<html> +<head><title>GNU Classpath - javax.swing.plaf.basic</title></head> + +<body> +<p>Provides a "basic" look and feel implementation.</p> + +</body> +</html> diff --git a/libjava/classpath/javax/swing/plaf/doc-files/ComponentUI-1.dia b/libjava/classpath/javax/swing/plaf/doc-files/ComponentUI-1.dia Binary files differnew file mode 100644 index 0000000..02bfbbe --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/doc-files/ComponentUI-1.dia diff --git a/libjava/classpath/javax/swing/plaf/doc-files/ComponentUI-1.png b/libjava/classpath/javax/swing/plaf/doc-files/ComponentUI-1.png Binary files differnew file mode 100644 index 0000000..def4cbc --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/doc-files/ComponentUI-1.png diff --git a/libjava/classpath/javax/swing/plaf/doc-files/TreeUI-1.png b/libjava/classpath/javax/swing/plaf/doc-files/TreeUI-1.png Binary files differnew file mode 100644 index 0000000..0f01ab0 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/doc-files/TreeUI-1.png diff --git a/libjava/classpath/javax/swing/plaf/metal/DefaultMetalTheme.java b/libjava/classpath/javax/swing/plaf/metal/DefaultMetalTheme.java new file mode 100644 index 0000000..673aec1 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/DefaultMetalTheme.java @@ -0,0 +1,221 @@ +/* DefaultMetalTheme.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.metal; + +import java.awt.Font; + +import javax.swing.plaf.ColorUIResource; +import javax.swing.plaf.FontUIResource; + +/** + * The default theme for the {@link MetalLookAndFeel}. + * + * @see MetalLookAndFeel#setCurrentTheme(MetalTheme) + */ +public class DefaultMetalTheme extends MetalTheme +{ + private static final ColorUIResource PRIMARY1 = + new ColorUIResource(102, 102, 153); + private static final ColorUIResource PRIMARY2 = + new ColorUIResource(153, 153, 204); + private static final ColorUIResource PRIMARY3 = + new ColorUIResource(204, 204, 255); + private static final ColorUIResource SECONDARY1 = + new ColorUIResource(102, 102, 102); + private static final ColorUIResource SECONDARY2 = + new ColorUIResource(153, 153, 153); + private static final ColorUIResource SECONDARY3 = + new ColorUIResource(204, 204, 204); + + private static final FontUIResource CONTROL_TEXT_FONT = + new FontUIResource("Dialog", Font.BOLD, 12); + private static final FontUIResource MENU_TEXT_FONT = + new FontUIResource("Dialog", Font.BOLD, 12); + private static final FontUIResource SUB_TEXT_FONT = + new FontUIResource("Dialog", Font.PLAIN, 10); + private static final FontUIResource SYSTEM_TEXT_FONT = + new FontUIResource("Dialog", Font.PLAIN, 12); + private static final FontUIResource USER_TEXT_FONT = + new FontUIResource("Dialog", Font.PLAIN, 12); + private static final FontUIResource WINDOW_TITLE_FONT = + new FontUIResource("Dialog", Font.BOLD, 12); + + /** + * Creates a new instance of this theme. + */ + public DefaultMetalTheme() + { + // Do nothing here. + } + + /** + * Returns the name of the theme. + * + * @return <code>"Steel"</code>. + */ + public String getName() + { + return "Steel"; + } + + /** + * Returns the first primary color for this theme. + * + * @return The first primary color. + */ + protected ColorUIResource getPrimary1() + { + return PRIMARY1; + } + + /** + * Returns the second primary color for this theme. + * + * @return The second primary color. + */ + protected ColorUIResource getPrimary2() + { + return PRIMARY2; + } + + /** + * Returns the third primary color for this theme. + * + * @return The third primary color. + */ + protected ColorUIResource getPrimary3() + { + return PRIMARY3; + } + + /** + * Returns the first secondary color for this theme. + * + * @return The first secondary color. + */ + protected ColorUIResource getSecondary1() + { + return SECONDARY1; + } + + /** + * Returns the second secondary color for this theme. + * + * @return The second secondary color. + */ + protected ColorUIResource getSecondary2() + { + return SECONDARY2; + } + + /** + * Returns the third secondary color for this theme. + * + * @return The third secondary color. + */ + protected ColorUIResource getSecondary3() + { + return SECONDARY3; + } + + /** + * Returns the font used for text on controls. In this case, the font is + * <code>FontUIResource("Dialog", Font.BOLD, 12)</code>. + * + * @return The font. + */ + public FontUIResource getControlTextFont() + { + return CONTROL_TEXT_FONT; + } + /** + * Returns the font used for text in menus. In this case, the font is + * <code>FontUIResource("Dialog", Font.BOLD, 12)</code>. + * + * @return The font used for text in menus. + */ + public FontUIResource getMenuTextFont() + { + return MENU_TEXT_FONT; + } + + /** + * Returns the font used for sub text. In this case, the font is + * <code>FontUIResource("Dialog", Font.PLAIN, 10)</code>. + * + * @return The font used for sub text. + */ + public FontUIResource getSubTextFont() + { + return SUB_TEXT_FONT; + } + + /** + * Returns the font used for system text. In this case, the font is + * <code>FontUIResource("Dialog", Font.PLAIN, 12)</code>. + * + * @return The font used for system text. + */ + public FontUIResource getSystemTextFont() + { + return SYSTEM_TEXT_FONT; + } + + /** + * Returns the font used for user text. In this case, the font is + * <code>FontUIResource("Dialog", Font.PLAIN, 12)</code>. + * + * @return The font used for user text. + */ + public FontUIResource getUserTextFont() + { + return USER_TEXT_FONT; + } + + /** + * Returns the font used for window titles. In this case, the font is + * <code>FontUIResource("Dialog", Font.BOLD, 12)</code>. + * + * @return The font used for window titles. + */ + public FontUIResource getWindowTitleFont() + { + return WINDOW_TITLE_FONT; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalBorders.java b/libjava/classpath/javax/swing/plaf/metal/MetalBorders.java new file mode 100644 index 0000000..f260ef6 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalBorders.java @@ -0,0 +1,443 @@ +/* MetalBorders.java + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.metal; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Insets; + +import javax.swing.AbstractButton; +import javax.swing.ButtonModel; +import javax.swing.JButton; +import javax.swing.border.AbstractBorder; +import javax.swing.border.Border; +import javax.swing.plaf.BorderUIResource; +import javax.swing.plaf.UIResource; +import javax.swing.plaf.basic.BasicGraphicsUtils; +import javax.swing.plaf.basic.BasicBorders; + +/** + * This factory class creates borders for the different Swing components + * UI. + * + * @author Roman Kennke (roman@kennke.org) + */ +public class MetalBorders +{ + + /** The shared instance for getButtonBorder(). */ + private static Border buttonBorder; + + /** The shared instance for getRolloverButtonBorder(). */ + private static Border toolbarButtonBorder; + + /** + * A MarginBorder that gets shared by multiple components. + * Created on demand by the private helper function {@link + * #getMarginBorder()}. + */ + private static BasicBorders.MarginBorder marginBorder; + + /** + * The border that is drawn around Swing buttons. + */ + public static class ButtonBorder + extends AbstractBorder + implements UIResource + { + /** The borders insets. */ + protected static Insets borderInsets = new Insets(3, 3, 3, 3); + + /** + * Creates a new instance of ButtonBorder. + */ + public ButtonBorder() + { + } + + /** + * Paints the button border. + * + * @param c the component for which we paint the border + * @param g the Graphics context to use + * @param x the X coordinate of the upper left corner of c + * @param y the Y coordinate of the upper left corner of c + * @param w the width of c + * @param h the height of c + */ + public void paintBorder(Component c, Graphics g, int x, int y, int w, + int h) + { + ButtonModel bmodel = null; + + if (c instanceof AbstractButton) + bmodel = ((AbstractButton) c).getModel(); + + Color darkShadow = MetalLookAndFeel.getControlDarkShadow(); + Color shadow = MetalLookAndFeel.getControlShadow(); + Color light = MetalLookAndFeel.getWhite(); + Color middle = MetalLookAndFeel.getControl(); + + // draw dark border + g.setColor(darkShadow); + g.drawRect(x, y, w - 2, h - 2); + + if (!bmodel.isPressed()) + { + // draw light border + g.setColor(light); + g.drawRect(x + 1, y + 1, w - 2, h - 2); + + // draw crossing pixels of both borders + g.setColor(middle); + g.drawRect(x + 1, y + h - 2, 0, 0); + g.drawRect(x + w - 2, y + 1, 0, 0); + } + else + { + // draw light border + g.setColor(light); + g.drawLine(x + w - 1, y + 1, x + w - 1, y + h - 1); + g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1); + + // draw shadow border + g.setColor(middle); + g.drawLine(x + 1, y + 1, x + w - 2, y + 1); + g.drawLine(x + 1, y + 1, x + 1, y + h - 2); + + // draw crossing pixels of both borders + g.setColor(shadow); + g.drawRect(x + 1, y + h - 2, 0, 0); + g.drawRect(x + w - 2, y + 1, 0, 0); + } + } + + /** + * Returns the insets of the ButtonBorder. + * + * @param c the component for which the border is used + * + * @return the insets of the ButtonBorder + */ + public Insets getBorderInsets(Component c) + { + return getBorderInsets(c, null); + } + + /** + * Returns the insets of the ButtonBorder in the specified Insets object. + * + * @param c the component for which the border is used + * @param newInsets the insets object where to put the values + * + * @return the insets of the ButtonBorder + */ + public Insets getBorderInsets(Component c, Insets newInsets) + { + if (newInsets == null) + newInsets = new Insets(0, 0, 0, 0); + + AbstractButton b = (AbstractButton) c; + newInsets.bottom = borderInsets.bottom; + newInsets.left = borderInsets.left; + newInsets.right = borderInsets.right; + newInsets.top = borderInsets.top; + return newInsets; + } + } + + /** + * A border for JScrollPanes. + */ + public static class ScrollPaneBorder + extends AbstractBorder + implements UIResource + { + /** The border insets. */ + private static Insets insets = new Insets(1, 1, 2, 2); + + /** + * Constructs a new ScrollPaneBorder. + */ + public ScrollPaneBorder() + { + } + + /** + * Returns the insets of the border for the Component <code>c</code>. + * + * @param c the Component for which we return the border insets + */ + public Insets getBorderInsets(Component c) + { + return insets; + } + + /** + * Paints the border. + * + * @param c the Component for which the border is painted + * @param g the Graphics context + * @param x the X coordinate of the upper left corner of the border + * @param y the Y coordinate of the upper left corner of the border + * @param w the width of the border + * @param h the height of the border + */ + public void paintBorder(Component c, Graphics g, int x, int y, + int w, int h) + { + Color darkShadow = MetalLookAndFeel.getControlDarkShadow(); + Color shadow = MetalLookAndFeel.getControlShadow(); + Color light = MetalLookAndFeel.getWhite(); + Color middle = MetalLookAndFeel.getControl(); + + // paint top border line + g.setColor(darkShadow); + g.drawLine(x, y, x + w - 2, y); + + // paint left border line + g.drawLine(x, y, x, y + h - 2); + + // paint right inner border line + g.drawLine(x + w - 2, y, x + w - 2, y + h + 1); + + // paint bottom inner border line + g.drawLine(x + 2, y + h - 2, x + w - 2, y + h - 2); + + // draw right outer border line + g.setColor(light); + g.drawLine(x + w - 1, y, x + w - 1, y + h - 1); + + // draw bottom outer border line + g.drawLine(x, y + h - 1, x + w - 1, y + h - 1); + + // paint the lighter points + g.setColor(middle); + g.drawLine(x + w - 1, y, x + w - 1, y); + g.drawLine(x + w - 2, y + 2, x + w - 2, y + 2); + g.drawLine(x, y + h - 1, x, y + h - 1); + g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2); + + } + + } + + /** + * This border is used in Toolbar buttons as inner border. + */ + static class RolloverMarginBorder extends AbstractBorder + { + /** The borders insets. */ + protected static Insets borderInsets = new Insets(3, 3, 3, 3); + + /** + * Creates a new instance of RolloverBorder. + */ + public RolloverMarginBorder() + { + } + + /** + * Returns the insets of the RolloverBorder. + * + * @param c the component for which the border is used + * + * @return the insets of the RolloverBorder + */ + public Insets getBorderInsets(Component c) + { + return getBorderInsets(c, null); + } + + /** + * Returns the insets of the RolloverMarginBorder in the specified + * Insets object. + * + * @param c the component for which the border is used + * @param newInsets the insets object where to put the values + * + * @return the insets of the RolloverMarginBorder + */ + public Insets getBorderInsets(Component c, Insets newInsets) + { + if (newInsets == null) + newInsets = new Insets(0, 0, 0, 0); + + AbstractButton b = (AbstractButton) c; + Insets margin = b.getMargin(); + newInsets.bottom = borderInsets.bottom; + newInsets.left = borderInsets.left; + newInsets.right = borderInsets.right; + newInsets.top = borderInsets.top; + return newInsets; + } + } + + /** + * A border implementation for popup menus. + */ + public static class PopupMenuBorder + extends AbstractBorder + implements UIResource + { + + /** The border's insets. */ + protected static Insets borderInsets = new Insets(2, 2, 1, 1); + + /** + * Constructs a new PopupMenuBorder. + */ + public PopupMenuBorder() + { + } + + /** + * Returns the insets of the border, creating a new Insets instance + * with each call. + * + * @param c the component for which we return the border insets + * (not used here) + */ + public Insets getBorderInsets(Component c) + { + return getBorderInsets(c, null); + } + + /** + * Returns the insets of the border, using the supplied Insets instance. + * + * @param c the component for which we return the border insets + * (not used here) + * @param i the Insets instance to fill with the Insets values + */ + public Insets getBorderInsets(Component c, Insets i) + { + Insets insets; + if (i == null) + insets = new Insets(borderInsets.top, borderInsets.left, + borderInsets.bottom, borderInsets.right); + else + { + insets = i; + insets.top = borderInsets.top; + insets.left = borderInsets.left; + insets.bottom = borderInsets.bottom; + insets.right = borderInsets.right; + } + + return insets; + } + + /** + * Paints the border for component <code>c</code> using the + * Graphics context <code>g</code> with the dimension + * <code>x, y, w, h</code>. + * + * @param c the component for which we paint the border + * @param g the Graphics context to use + * @param x the X coordinate of the upper left corner of c + * @param y the Y coordinate of the upper left corner of c + * @param w the width of c + * @param h the height of c + */ + public void paintBorder(Component c, Graphics g, int x, int y, int w, + int h) + { + Color darkShadow = MetalLookAndFeel.getPrimaryControlDarkShadow(); + Color light = MetalLookAndFeel.getPrimaryControlHighlight(); + + // draw dark outer border + g.setColor(darkShadow); + g.drawRect(x, y, w - 1, h - 1); + + // draw highlighted inner border (only top and left) + g.setColor(light); + g.drawLine(x + 1, y + 1, x + 1, y + h - 2); + g.drawLine(x + 1, y + 1, x + w - 2, y + 1); + } + + } + + /** + * Returns a border for Swing buttons in the Metal Look & Feel. + * + * @return a border for Swing buttons in the Metal Look & Feel + */ + public static Border getButtonBorder() + { + if (buttonBorder == null) + { + Border outer = new ButtonBorder(); + Border inner = getMarginBorder(); + buttonBorder = new BorderUIResource.CompoundBorderUIResource + (outer, inner); + } + return buttonBorder; + } + + /** + * Returns a border for Toolbar buttons in the Metal Look & Feel. + * + * @return a border for Toolbar buttons in the Metal Look & Feel + */ + static Border getToolbarButtonBorder() + { + if (toolbarButtonBorder == null) + { + Border outer = new ButtonBorder(); + Border inner = new RolloverMarginBorder(); + toolbarButtonBorder = new BorderUIResource.CompoundBorderUIResource + (outer, inner); + } + return toolbarButtonBorder; + } + + /** + * Returns a shared instance of {@link BasicBorders.MarginBorder}. + * + * @return a shared instance of {@link BasicBorders.MarginBorder} + */ + static Border getMarginBorder() + { + if (marginBorder == null) + marginBorder = new BasicBorders.MarginBorder(); + return marginBorder; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalButtonUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalButtonUI.java new file mode 100644 index 0000000..a7b53c4 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalButtonUI.java @@ -0,0 +1,101 @@ +/* MetalButtonUI.java + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.metal; + +import javax.swing.AbstractButton; +import javax.swing.JComponent; +import javax.swing.JToolBar; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicButtonUI; + +/** + * The Metal Look & Feel implementation for + * {@link javax.swing.AbstractButton}s. + * + * @author Roman Kennke (roman@kennke.org) + */ +public class MetalButtonUI + extends BasicButtonUI +{ + + // FIXME: probably substitute with a Map in the future in the case + // that this UI becomes stateful + + /** The cached MetalButtonUI instance. */ + private static MetalButtonUI instance = null; + + /** + * Creates a new instance of MetalButtonUI. + */ + public MetalButtonUI() + { + super(); + } + + /** + * Returns an instance of MetalButtonUI. + * + * @param component a button for which a UI instance should be returned + */ + public static ComponentUI createUI(JComponent component) + { + if (instance == null) + instance = new MetalButtonUI(); + return instance; + } + + /** + * Install the Look & Feel defaults for Buttons. + * + * @param button the button for which to install the Look & Feel + */ + public void installDefaults(AbstractButton button) + { + super.installDefaults(button); + + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + button.setFont(defaults.getFont("Button.font")); + + if (button.getParent() instanceof JToolBar) + button.setBorder(MetalBorders.getToolbarButtonBorder()); + } + +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxIcon.java b/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxIcon.java new file mode 100644 index 0000000..eba21a4 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxIcon.java @@ -0,0 +1,136 @@ +/* MetalCheckBoxIcon.java -- An icon for JCheckBoxes in the Metal L&F + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.metal; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; + +import java.io.Serializable; + +import javax.swing.Icon; +import javax.swing.JCheckBox; +import javax.swing.plaf.UIResource; + +/** + * An {@link Icon} implementation for {@link JCheckBox}es in the + * Metal Look & Feel. + * + * @author Roman Kennke (roman@kennke.org) + */ +public class MetalCheckBoxIcon + implements Icon, UIResource, Serializable +{ + + /** Used to paint the border of the icon. */ + MetalBorders.ButtonBorder border; + + /** + * Creates a new MetalCheckBoxIcon instance. + */ + public MetalCheckBoxIcon() + { + border = new MetalBorders.ButtonBorder(); + } + + /** + * Draws the check in the CheckBox. + * + * @param c the component to draw on + * @param g the Graphics context to draw with + * @param x the X position + * @param y the Y position + */ + protected void drawCheck(Component c, Graphics g, int x, int y) + { + g.setColor(Color.BLACK); + g.drawLine(3, 5, 3, 9); + g.drawLine(4, 5, 4, 9); + g.drawLine(5, 7, 9, 3); + g.drawLine(5, 8, 9, 4); + } + + /** + * Returns the size (both X and Y) of the checkbox icon. + * + * @return the size of the checkbox icon + */ + protected int getControlSize() + { + return 13; + } + + /** + * Returns the width of the icon in pixels. + * + * @return the width of the icon in pixels + */ + public int getIconWidth() + { + return getControlSize(); + } + + /** + * Returns the height of the icon in pixels. + * + * @return the height of the icon in pixels + */ + public int getIconHeight() + { + return getControlSize(); + } + + /** + * Paints the icon. This first paints the border of the CheckBox and + * if the CheckBox is selected it calls {@link #drawCheck} to draw + * the check. + * + * @param c the Component to draw on (gets casted to JCheckBox) + * @param g the Graphics context to draw with + * @param x the X position + * @param x the Y position + */ + public void paintIcon(Component c, Graphics g, int x, int y) + { + border.paintBorder(c, g, x, y, getIconWidth(), getIconHeight()); + JCheckBox cb = (JCheckBox) c; + if (cb.isSelected()) + drawCheck(c, g, x, y); + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxUI.java new file mode 100644 index 0000000..d59e38c --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxUI.java @@ -0,0 +1,74 @@ +/* MetalCheckBoxUI.java + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.metal; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicCheckBoxUI; + +public class MetalCheckBoxUI + extends BasicCheckBoxUI +{ + + // FIXME: maybe replace by a Map of instances when this becomes stateful + /** The shared UI instance for JCheckBoxes. */ + private static MetalCheckBoxUI instance = null; + + /** + * Constructs a new instance of MetalCheckBoxUI. + */ + public MetalCheckBoxUI() + { + super(); + } + + /** + * Returns an instance of MetalCheckBoxUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalCheckBoxUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instance == null) + instance = new MetalCheckBoxUI(); + return instance; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxIcon.java b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxIcon.java new file mode 100644 index 0000000..ce4fa7d --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxIcon.java @@ -0,0 +1,100 @@ +/* MetalComboBoxButton.java + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.metal; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.io.Serializable; + +import javax.swing.Icon; + +/** + * An icon used by the {@link MetalComboBoxUI} class. + */ +public class MetalComboBoxIcon implements Icon, Serializable { + + /** + * Creates a new icon. + */ + public MetalComboBoxIcon() + { + // nothing required. + } + + /** + * Returns the icon width, which for this icon is 10 pixels. + * + * @return <code>10</code>. + */ + public int getIconWidth() + { + return 10; + } + + /** + * Returns the icon height, which for this icon is 5 pixels. + * + * @return <code>5</code>. + */ + public int getIconHeight() + { + return 5; + } + + /** + * Paints the icon at the location (x, y). + * + * @param c the combo box (ignored here). + * @param g the graphics device. + * @param x the x coordinate. + * @param y the y coordinate. + */ + public void paintIcon(Component c, Graphics g, int x, int y) + { + // TODO: work out whether/how the icon changes with different component + // states (and also different metal themes) + Color savedColor = g.getColor(); + g.setColor(Color.black); + for (int i = 0; i < 5; i++) + g.drawLine(x + i, y + i, x + 9 - i, y + i); + g.setColor(savedColor); + } + +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxUI.java new file mode 100644 index 0000000..28c279d --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxUI.java @@ -0,0 +1,86 @@ +/* MetalComboBoxUI.java + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.metal; + +import java.util.HashMap; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicComboBoxUI; + +public class MetalComboBoxUI + extends BasicComboBoxUI +{ + + /** The UI instances for JComboBoxes. */ + private static HashMap instances = null; + + /** + * Constructs a new instance of MetalComboBoxUI. + */ + public MetalComboBoxUI() + { + super(); + } + + /** + * Returns an instance of MetalComboBoxUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalComboBoxUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instances == null) + instances = new HashMap(); + + Object o = instances.get(component); + MetalComboBoxUI instance; + if (o == null) + { + instance = new MetalComboBoxUI(); + instances.put(component, instance); + } + else + instance = (MetalComboBoxUI) o; + + return instance; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalDesktopIconUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalDesktopIconUI.java new file mode 100644 index 0000000..0087054 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalDesktopIconUI.java @@ -0,0 +1,74 @@ +/* MetalDesktopIconUI.java + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.metal; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicDesktopIconUI; + +public class MetalDesktopIconUI + extends BasicDesktopIconUI +{ + + // FIXME: maybe replace by a Map of instances when this becomes stateful + /** The shared UI instance for MetalDesktopIcons */ + private static MetalDesktopIconUI instance = null; + + /** + * Constructs a new instance of MetalDesktopIconUI. + */ + public MetalDesktopIconUI() + { + super(); + } + + /** + * Returns an instance of MetalDesktopIconUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalDesktopIconUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instance == null) + instance = new MetalDesktopIconUI(); + return instance; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalIconFactory.java b/libjava/classpath/javax/swing/plaf/metal/MetalIconFactory.java new file mode 100644 index 0000000..e770f47 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalIconFactory.java @@ -0,0 +1,672 @@ +/* MetalIconFactory.java -- + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.metal; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Graphics; +import java.io.Serializable; + +import javax.swing.Icon; +import javax.swing.JSlider; + +/** + * Creates icons for the {@link MetalLookAndFeel}. + */ +public class MetalIconFactory implements Serializable +{ + + /** A constant representing "dark". */ + public static final boolean DARK = false; + + /** A constant representing "light". */ + public static final boolean LIGHT = true; + + /** + * An icon representing a file (drawn as a piece of paper with the top-right + * corner turned down). + */ + public static class FileIcon16 implements Icon, Serializable + { + /** + * Returns the width of the icon, in pixels. + * + * @return The width of the icon. + */ + public int getIconWidth() + { + return 16; + } + + /** + * Returns the height of the icon, in pixels. + * + * @return The height of the icon. + */ + public int getIconHeight() + { + return 16; + } + + /** + * Paints the icon at the location (x, y). + * + * @param c the component. + * @param g the graphics context. + * @param x the x coordinate. + * @param y the y coordinate. + */ + public void paintIcon(Component c, Graphics g, int x, int y) + { + // TODO: pick up appropriate UI colors + g.setColor(Color.black); + g.drawLine(x, y, x + 9, y); + g.drawLine(x, y + 1, x, y + 15); + g.drawLine(x, y + 15, x + 12, y + 15); + g.drawLine(x + 12, y + 15, x + 12, y + 6); + g.drawLine(x + 12, y + 6, x + 9, y); + + g.drawLine(x + 7, y + 2, x + 11, y + 6); + g.drawLine(x + 8, y + 1, x + 9, y + 1); + + g.setColor(new Color(204, 204, 255)); + g.drawLine(x + 1, y + 1, x + 7, y + 1); + g.drawLine(x + 1, y + 1, x + 1, y + 14); + g.drawLine(x + 1, y + 14, x + 11, y + 14); + g.drawLine(x + 11, y + 14, x + 11, y + 7); + g.drawLine(x + 8, y + 2, x + 10, y + 4); + } + + /** + * Returns the additional height (???). + * + * @return The additional height. + */ + public int getAdditionalHeight() + { + return 0; + } + + /** + * Returns the shift (???). + * + * @return The shift. + */ + public int getShift() + { + return 0; + } + + } + + /** + * An icon representing a folder. + */ + public static class FolderIcon16 implements Icon, Serializable + { + /** + * Returns the width of the icon, in pixels. + * + * @return The width of the icon. + */ + public int getIconWidth() { + return 16; + } + + /** + * Returns the height of the icon, in pixels. + * + * @return The height of the icon. + */ + public int getIconHeight() + { + return 16; + } + + /** + * Paints the icon at the location (x, y). + * + * @param c the component. + * @param g the graphics device. + * @param x the x coordinate. + * @param y the y coordinate. + */ + public void paintIcon(Component c, Graphics g, int x, int y) + { + // TODO: pick up appropriate UI colors + g.setColor(Color.black); + g.drawLine(x, y + 3, x, y + 12); + g.drawLine(x, y + 12, x + 15, y + 12); + g.drawLine(x + 15, y + 12, x + 15, y + 2); + g.drawLine(x + 14, y + 3, x + 9, y + 3); + g.drawLine(x + 8, y + 2, x + 1, y + 2); + g.setColor(new Color(204, 204, 255)); + g.fillRect(x + 2, y + 4, 7, 8); + g.fillRect(x + 9, y + 5, 6, 7); + g.setColor(new Color(102, 102, 153)); + g.drawLine(x + 9, y + 2, x + 14, y + 2); + g.setColor(new Color(50, 50, 120)); + g.drawLine(x + 9, y + 1, x + 15, y + 1); + g.drawLine(x + 10, y, x + 15, y); + } + + /** + * Returns the additional height (???). + * + * @return The additional height. + */ + public int getAdditionalHeight() + { + return 0; + } + + /** + * Returns the shift (???). + * + * @return The shift. + */ + public int getShift() + { + return 0; + } + + } + + /** + * The icon used to display the thumb control on a horizontally oriented + * {@link JSlider} component. + */ + private static class HorizontalSliderThumbIcon + implements Icon, Serializable + { + + /** + * Creates a new instance. + */ + public HorizontalSliderThumbIcon() + { + } + + /** + * Returns the width of the icon, in pixels. + * + * @return The width of the icon. + */ + public int getIconWidth() + { + return 15; + } + + /** + * Returns the height of the icon, in pixels. + * + * @return The height of the icon. + */ + public int getIconHeight() + { + return 16; + } + + /** + * Paints the icon, taking into account whether or not the component has + * the focus. + * + * @param c the component. + * @param g the graphics device. + * @param x the x-coordinate. + * @param y the y-coordinate. + */ + public void paintIcon(Component c, Graphics g, int x, int y) + { + boolean focus = false; + if (c != null) + focus = c.hasFocus(); + // TODO: pick up the colors from the look and feel + + // draw the outline + g.setColor(Color.black); + g.drawLine(x + 1, y, x + 13, y); + g.drawLine(x + 14, y + 1, x + 14, y + 7); + g.drawLine(x + 14, y + 8, x + 7, y + 15); + g.drawLine(x + 6, y + 14, x, y + 8); + g.drawLine(x, y + 7, x, y + 1); + + // fill the icon + g.setColor(focus ? new Color(153, 153, 204) : new Color(204, 204, 204)); // medium + g.fillRect(x + 2, y + 2, 12, 7); + g.drawLine(x + 2, y + 9, x + 12, y + 9); + g.drawLine(x + 3, y + 10, x + 11, y + 10); + g.drawLine(x + 4, y + 11, x + 10, y + 11); + g.drawLine(x + 5, y + 12, x + 9, y + 12); + g.drawLine(x + 6, y + 13, x + 8, y + 13); + g.drawLine(x + 7, y + 14, x + 7, y + 14); + + // draw highlights + g.setColor(focus ? new Color(204, 204, 255) : new Color(255, 255, 255)); // light + g.drawLine(x + 1, y + 1, x + 13, y + 1); + g.drawLine(x + 1, y + 2, x + 1, y + 8); + g.drawLine(x + 2, y + 2, x + 2, y + 2); + g.drawLine(x + 6, y + 2, x + 6, y + 2); + g.drawLine(x + 10, y + 2, x + 10, y + 2); + + g.drawLine(x + 4, y + 4, x + 4, y + 4); + g.drawLine(x + 8, y + 4, x + 8, y + 4); + + g.drawLine(x + 2, y + 6, x + 2, y + 6); + g.drawLine(x + 6, y + 6, x + 6, y + 6); + g.drawLine(x + 10, y + 6, x + 10, y + 6); + + // draw dots + g.setColor(focus ? new Color(102, 102, 153) : Color.black); // dark + g.drawLine(x + 3, y + 3, x + 3, y + 3); + g.drawLine(x + 7, y + 3, x + 7, y + 3); + g.drawLine(x + 11, y + 3, x + 11, y + 3); + + g.drawLine(x + 5, y + 5, x + 5, y + 5); + g.drawLine(x + 9, y + 5, x + 9, y + 5); + + g.drawLine(x + 3, y + 7, x + 3, y + 7); + g.drawLine(x + 7, y + 7, x + 7, y + 7); + g.drawLine(x + 11, y + 7, x + 11, y + 7); + + } + } + + /** + * The icon used to display the thumb control on a horizontally oriented + * {@link JSlider} component. + */ + private static class VerticalSliderThumbIcon implements Icon, Serializable + { + /** + * Creates a new instance. + */ + public VerticalSliderThumbIcon() + { + } + + /** + * Returns the width of the icon, in pixels. + * + * @return The width of the icon. + */ + public int getIconWidth() + { + return 16; + } + + /** + * Returns the height of the icon, in pixels. + * + * @return The height of the icon. + */ + public int getIconHeight() + { + return 15; + } + + /** + * Paints the icon taking into account whether the slider control has the + * focus or not. + * + * @param c the slider (must be a non-<code>null</code> instance of + * {@link JSlider}. + * @param g the graphics device. + * @param x the x-coordinate. + * @param y the y-coordinate. + */ + public void paintIcon(Component c, Graphics g, int x, int y) + { + boolean focus = false; + if (c != null) + focus = c.hasFocus(); + // TODO: pick up the colors from the look and feel + + // draw the outline + g.setColor(Color.black); + g.drawLine(x + 1, y, x + 7, y); + g.drawLine(x + 8, y, x + 15, y + 7); + g.drawLine(x + 14, y + 8, x + 8, y + 14); + g.drawLine(x + 8, y + 14, x + 1, y + 14); + g.drawLine(x, y + 13, x, y + 1); + + // fill the icon + g.setColor(focus ? new Color(153, 153, 204) : new Color(204, 204, 204)); // medium + g.fillRect(x + 2, y + 2, 7, 12); + g.drawLine(x + 9, y + 2, x + 9, y + 12); + g.drawLine(x + 10, y + 3, x + 10, y + 11); + g.drawLine(x + 11, y + 4, x + 11, y + 10); + g.drawLine(x + 12, y + 5, x + 12, y + 9); + g.drawLine(x + 13, y + 6, x + 13, y + 8); + g.drawLine(x + 14, y + 7, x + 14, y + 7); + + // draw highlights + g.setColor(focus ? new Color(204, 204, 255) : new Color(255, 255, 255)); // light + g.drawLine(x + 1, y + 1, x + 8, y + 1); + g.drawLine(x + 1, y + 2, x + 1, y + 13); + g.drawLine(x + 2, y + 2, x + 2, y + 2); + g.drawLine(x + 2, y + 6, x + 2, y + 6); + g.drawLine(x + 2, y + 10, x + 2, y + 10); + + g.drawLine(x + 4, y + 4, x + 4, y + 4); + g.drawLine(x + 4, y + 8, x + 4, y + 8); + + g.drawLine(x + 6, y + 2, x + 6, y + 2); + g.drawLine(x + 6, y + 6, x + 6, y + 6); + g.drawLine(x + 6, y + 10, x + 6, y + 10); + + // draw dots + g.setColor(focus ? new Color(102, 102, 153) : Color.black); // dark + g.drawLine(x + 3, y + 3, x + 3, y + 3); + g.drawLine(x + 3, y + 7, x + 3, y + 7); + g.drawLine(x + 3, y + 11, x + 3, y + 11); + + g.drawLine(x + 5, y + 5, x + 5, y + 5); + g.drawLine(x + 5, y + 9, x + 5, y + 9); + + g.drawLine(x + 7, y + 3, x + 7, y + 3); + g.drawLine(x + 7, y + 7, x + 7, y + 7); + g.drawLine(x + 7, y + 11, x + 7, y + 11); + } + } + + /** + * A tree control icon. This icon can be in one of two states: expanded and + * collapsed. + */ + public static class TreeControlIcon implements Icon, Serializable + { + + /** ???. */ + protected boolean isLight; + + /** A flag that controls whether or not the icon is collapsed. */ + private boolean collapsed; + + /** + * Creates a new icon. + * + * @param isCollapsed a flag that controls whether the icon is in the + * collapsed state or the expanded state. + */ + public TreeControlIcon(boolean isCollapsed) + { + collapsed = isCollapsed; + } + + /** + * Returns the width of the icon, in pixels. + * + * @return The width of the icon. + */ + public int getIconWidth() + { + return 18; + } + /** + * Returns the height of the icon, in pixels. + * + * @return The height of the icon. + */ + public int getIconHeight() + { + return 18; + } + + /** + * Paints the icon at the location (x, y). + * + * @param c the component. + * @param g the graphics device. + * @param x the x coordinate. + * @param y the y coordinate. + */ + public void paintIcon(Component c, Graphics g, int x, int y) + { + x = x + 5; + y = y + 5; + if (collapsed) + { + // TODO: pick up appropriate UI colors + g.setColor(Color.black); + g.drawLine(x + 2, y, x + 5, y); + g.drawLine(x + 6, y + 1, x + 7, y + 2); + g.fillRect(x + 7, y + 3, 5, 2); + g.drawLine(x + 7, y + 5, x + 6, y + 6); + g.drawLine(x + 1, y + 1, x + 1, y + 1); + g.drawLine(x, y + 2, x, y + 5); + g.drawLine(x + 1, y + 6, x + 1, y + 6); + g.drawLine(x + 2, y + 7, x + 5, y + 7); + g.fillRect(x + 3, y + 3, 2, 2); + + g.setColor(new Color(204, 204, 255)); + g.drawLine(x + 3, y + 2, x + 4, y + 2); + g.drawLine(x + 2, y + 3, x + 2, y + 4); + g.drawLine(x + 3, y + 5, x + 3, y + 5); + g.drawLine(x + 5, y + 3, x + 5, y + 3); + + g.setColor(new Color(153, 153, 204)); + g.drawLine(x + 2, y + 2, x + 2, y + 2); + g.drawLine(x + 2, y + 5, x + 2, y + 5); + g.drawLine(x + 2, y + 6, x + 5, y + 6); + g.drawLine(x + 5, y + 2, x + 5, y + 2); + g.drawLine(x + 6, y + 2, x + 6, y + 5); + + g.setColor(new Color(102, 102, 153)); + g.drawLine(x + 2, y + 1, x + 5, y + 1); + g.drawLine(x + 1, y + 2, x + 1, y + 5); + } + else + { + // TODO: pick up appropriate UI colors + g.setColor(Color.black); + g.drawLine(x + 2, y, x + 5, y); + g.drawLine(x + 6, y + 1, x + 7, y + 2); + g.drawLine(x + 7, y + 2, x + 7, y + 5); + g.fillRect(x + 3, y + 7, 2, 5); + g.drawLine(x + 7, y + 5, x + 6, y + 6); + g.drawLine(x + 1, y + 1, x + 1, y + 1); + g.drawLine(x, y + 2, x, y + 5); + g.drawLine(x + 1, y + 6, x + 1, y + 6); + g.drawLine(x + 2, y + 7, x + 5, y + 7); + g.fillRect(x + 3, y + 3, 2, 2); + + g.setColor(new Color(204, 204, 255)); + g.drawLine(x + 3, y + 2, x + 4, y + 2); + g.drawLine(x + 2, y + 3, x + 2, y + 4); + g.drawLine(x + 3, y + 5, x + 3, y + 5); + g.drawLine(x + 5, y + 3, x + 5, y + 3); + + g.setColor(new Color(153, 153, 204)); + g.drawLine(x + 2, y + 2, x + 2, y + 2); + g.drawLine(x + 2, y + 5, x + 2, y + 5); + g.drawLine(x + 2, y + 6, x + 5, y + 6); + g.drawLine(x + 5, y + 2, x + 5, y + 2); + g.drawLine(x + 6, y + 2, x + 6, y + 5); + + g.setColor(new Color(102, 102, 153)); + g.drawLine(x + 2, y + 1, x + 5, y + 1); + g.drawLine(x + 1, y + 2, x + 1, y + 5); + } + } + + /** + * Simply calls {@link #paintIcon(Component, Graphics, int, int)}. + * + * @param c the component. + * @param g the graphics device. + * @param x the x coordinate. + * @param y the y coordinate. + */ + public void paintMe(Component c, Graphics g, int x, int y) + { + paintIcon(c, g, x, y); + } + } + + /** + * A tree folder icon. + */ + public static class TreeFolderIcon extends FolderIcon16 + { + /** + * Creates a new instance. + */ + public TreeFolderIcon() + { + } + + /** + * Returns the additional height (???). + * + * @return The additional height. + */ + public int getAdditionalHeight() + { + return 2; + } + + /** + * Returns the shift (???). + * + * @return The shift. + */ + public int getShift() + { + return -1; + } + } + + /** + * A tree leaf icon. + */ + public static class TreeLeafIcon extends FileIcon16 + { + /** + * Creates a new instance. + */ + public TreeLeafIcon() + { + } + + /** + * Returns the additional height (???). + * + * @return The additional height. + */ + public int getAdditionalHeight() + { + return 4; + } + + /** + * Returns the shift (???). + * + * @return The shift. + */ + public int getShift() + { + return 2; + } + } + + /** + * Creates a new instance. All the methods are static, so creating an + * instance isn't necessary. + */ + public MetalIconFactory() + { + } + + /** + * Returns the icon used to display the thumb for a horizontally oriented + * {@link JSlider}. + * + * @return The icon. + */ + public static Icon getHorizontalSliderThumbIcon() + { + return new HorizontalSliderThumbIcon(); + } + + /** + * Returns the icon used to display the thumb for a vertically oriented + * {@link JSlider}. + * + * @return The icon. + */ + public static Icon getVerticalSliderThumbIcon() + { + return new VerticalSliderThumbIcon(); + } + + /** + * Creates and returns a new tree folder icon. + * + * @return A new tree folder icon. + */ + public static Icon getTreeFolderIcon() + { + return new TreeFolderIcon(); + } + + /** + * Creates and returns a new tree leaf icon. + * + * @return A new tree leaf icon. + */ + public static Icon getTreeLeafIcon() + { + return new TreeLeafIcon(); + } + + /** + * Creates and returns a tree control icon. + * + * @param isCollapsed a flag that controls whether the icon is in the + * collapsed or expanded state. + * + * @return A tree control icon. + */ + public static Icon getTreeControlIcon(boolean isCollapsed) + { + return new TreeControlIcon(isCollapsed); + } + +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameUI.java new file mode 100644 index 0000000..1414351 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameUI.java @@ -0,0 +1,88 @@ +/* MetalInternalFrameUI.java + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.metal; + +import java.util.HashMap; + +import javax.swing.JComponent; +import javax.swing.JInternalFrame; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicInternalFrameUI; + +public class MetalInternalFrameUI + extends BasicInternalFrameUI +{ + + /** The instances of MetalInternalFrameUI*/ + private static HashMap instances; + + /** + * Constructs a new instance of MetalInternalFrameUI. + */ + public MetalInternalFrameUI(JInternalFrame frame) + { + super(frame); + } + + /** + * Returns an instance of MetalInternalFrameUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalInternalFrameUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instances == null) + instances = new HashMap(); + + + Object o = instances.get(component); + MetalInternalFrameUI instance; + if (o == null) + { + instance = new MetalInternalFrameUI((JInternalFrame) component); + instances.put(component, instance); + } + else + instance = (MetalInternalFrameUI) o; + + return instance; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalLabelUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalLabelUI.java new file mode 100644 index 0000000..cdd8612 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalLabelUI.java @@ -0,0 +1,74 @@ +/* MetalLabelUI.java + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.metal; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicLabelUI; + +public class MetalLabelUI + extends BasicLabelUI +{ + + // FIXME: maybe replace by a Map of instances when this becomes stateful + /** The shared UI instance for JLabels. */ + private static MetalLabelUI instance = null; + + /** + * Constructs a new instance of MetalLabelUI. + */ + public MetalLabelUI() + { + super(); + } + + /** + * Returns an instance of MetalLabelUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalLabelUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instance == null) + instance = new MetalLabelUI(); + return instance; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java b/libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java new file mode 100644 index 0000000..46519fc --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java @@ -0,0 +1,853 @@ +/* MetalLookAndFeel.java + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.metal; + +import java.awt.Color; +import java.awt.Font; +import java.awt.Insets; + +import javax.swing.ImageIcon; +import javax.swing.UIDefaults; +import javax.swing.plaf.ColorUIResource; +import javax.swing.plaf.FontUIResource; +import javax.swing.plaf.IconUIResource; +import javax.swing.plaf.basic.BasicLookAndFeel; + +/** + * A custom look and feel that is designed to look similar across different + * operating systems. + */ +public class MetalLookAndFeel extends BasicLookAndFeel +{ + private static final long serialVersionUID = 6680646159193457980L; + + /** The current theme. */ + private static MetalTheme theme; + + /** The look and feel defaults. */ + private UIDefaults LAF_defaults; + + /** + * Creates a new instance of the Metal look and feel. + */ + public MetalLookAndFeel() + { + createDefaultTheme(); + } + + /** + * Sets the current theme to a new instance of {@link DefaultMetalTheme}. + */ + protected void createDefaultTheme() + { + setCurrentTheme(new DefaultMetalTheme()); + } + + /** + * Returns <code>false</code> to indicate that this look and feel does not + * attempt to emulate the look and feel of native applications on the host + * platform. + * + * @return <code>false</code>. + */ + public boolean isNativeLookAndFeel() + { + return false; + } + + /** + * Returns <code>true</code> to indicate that this look and feel is supported + * on all platforms. + * + * @return <code>true</code>. + */ + public boolean isSupportedLookAndFeel() + { + return true; + } + + /** + * Returns a string describing the look and feel. In this case, the method + * returns "Metal look and feel". + * + * @return A string describing the look and feel. + */ + public String getDescription() + { + return "Metal look and feel"; + } + + /** + * Returns the look and feel identifier. + * + * @return "MetalLookAndFeel". + */ + public String getID() + { + return "MetalLookAndFeel"; + } + + /** + * Returns the look and feel name. + * + * @return "MetalLookAndFeel". + */ + public String getName() + { + return "MetalLookAndFeel"; + } + + public UIDefaults getDefaults() + { + if (LAF_defaults == null) + { + LAF_defaults = super.getDefaults(); + + // add custom theme entries to the table + theme.addCustomEntriesToTable(LAF_defaults); + } + + // Returns the default values for this look and feel. + return LAF_defaults; + } + + /** + * Returns the accelerator foreground color from the installed theme. + * + * @return The accelerator foreground color. + */ + public static ColorUIResource getAcceleratorForeground() + { + return theme.getAcceleratorForeground(); + } + + /** + * Returns the accelerator selected foreground color from the installed + * theme. + * + * @return The accelerator selected foreground color. + */ + public static ColorUIResource getAcceleratorSelectedForeground() + { + return theme.getAcceleratorSelectedForeground(); + } + + /** + * Returns the color black from the installed theme. + * + * @return The color black. + */ + public static ColorUIResource getBlack() + { + return theme.getBlack(); + } + + /** + * Returns the control color from the installed theme. + * + * @return The control color. + */ + public static ColorUIResource getControl() + { + return theme.getControl(); + } + + /** + * Returns the color used for dark shadows on controls, from the installed + * theme. + * + * @return The color used for dark shadows on controls. + */ + public static ColorUIResource getControlDarkShadow() + { + return theme.getControlDarkShadow(); + } + + /** + * Returns the color used for disabled controls, from the installed theme. + * + * @return The color used for disabled controls. + */ + public static ColorUIResource getControlDisabled() + { + return theme.getControlDisabled(); + } + + /** + * Returns the color used to draw highlights for controls, from the installed + * theme. + * + * @return The color used to draw highlights for controls. + */ + public static ColorUIResource getControlHighlight() + { + return theme.getControlHighlight(); + } + + /** + * Returns the color used to display control info, from the installed + * theme. + * + * @return The color used to display control info. + */ + public static ColorUIResource getControlInfo() + { + return theme.getControlInfo(); + } + + /** + * Returns the color used to draw shadows for controls, from the installed + * theme. + * + * @return The color used to draw shadows for controls. + */ + public static ColorUIResource getControlShadow() + { + return theme.getControlShadow(); + } + + /** + * Returns the color used for text on controls, from the installed theme. + * + * @return The color used for text on controls. + */ + public static ColorUIResource getControlTextColor() + { + return theme.getControlTextColor(); + } + + /** + * Returns the font used for text on controls, from the installed theme. + * + * @return The font used for text on controls. + */ + public static FontUIResource getControlTextFont() + { + return theme.getControlTextFont(); + } + + /** + * Returns the color used for the desktop background, from the installed + * theme. + * + * @return The color used for the desktop background. + */ + public static ColorUIResource getDesktopColor() + { + return theme.getDesktopColor(); + } + + /** + * Returns the color used to draw focus highlights, from the installed + * theme. + * + * @return The color used to draw focus highlights. + */ + public static ColorUIResource getFocusColor() + { + return theme.getFocusColor(); + } + + /** + * Returns the color used to draw highlighted text, from the installed + * theme. + * + * @return The color used to draw highlighted text. + */ + public static ColorUIResource getHighlightedTextColor() + { + return theme.getHighlightedTextColor(); + } + + /** + * Returns the color used to draw text on inactive controls, from the + * installed theme. + * + * @return The color used to draw text on inactive controls. + */ + public static ColorUIResource getInactiveControlTextColor() + { + return theme.getInactiveControlTextColor(); + } + + /** + * Returns the color used to draw inactive system text, from the installed + * theme. + * + * @return The color used to draw inactive system text. + */ + public static ColorUIResource getInactiveSystemTextColor() + { + return theme.getInactiveSystemTextColor(); + } + + /** + * Returns the background color for menu items, from the installed theme. + * + * @return The background color for menu items. + * + * @see #getMenuSelectedBackground() + */ + public static ColorUIResource getMenuBackground() + { + return theme.getMenuBackground(); + } + + /** + * Returns the foreground color for disabled menu items, from the installed + * theme. + * + * @return The foreground color for disabled menu items. + * + * @see #getMenuForeground() + */ + public static ColorUIResource getMenuDisabledForeground() + { + return theme.getMenuDisabledForeground(); + } + + /** + * Returns the foreground color for menu items, from the installed theme. + * + * @return The foreground color for menu items. + * + * @see #getMenuDisabledForeground() + * @see #getMenuSelectedForeground() + */ + public static ColorUIResource getMenuForeground() + { + return theme.getMenuForeground(); + } + + /** + * Returns the background color for selected menu items, from the installed + * theme. + * + * @return The background color for selected menu items. + * + * @see #getMenuBackground() + */ + public static ColorUIResource getMenuSelectedBackground() + { + return theme.getMenuSelectedBackground(); + } + + /** + * Returns the foreground color for selected menu items, from the installed + * theme. + * + * @return The foreground color for selected menu items. + * + * @see #getMenuForeground() + */ + public static ColorUIResource getMenuSelectedForeground() + { + return theme.getMenuSelectedForeground(); + } + + /** + * Returns the font used for text in menus, from the installed theme. + * + * @return The font used for text in menus. + */ + public static FontUIResource getMenuTextFont() + { + return theme.getMenuTextFont(); + } + + /** + * Returns the primary color for controls, from the installed theme. + * + * @return The primary color for controls. + */ + public static ColorUIResource getPrimaryControl() + { + return theme.getPrimaryControl(); + } + + /** + * Returns the primary color for the dark shadow on controls, from the + * installed theme. + * + * @return The primary color for the dark shadow on controls. + */ + public static ColorUIResource getPrimaryControlDarkShadow() + { + return theme.getPrimaryControlDarkShadow(); + } + + /** + * Returns the primary color for the highlight on controls, from the + * installed theme. + * + * @return The primary color for the highlight on controls. + */ + public static ColorUIResource getPrimaryControlHighlight() + { + return theme.getPrimaryControlHighlight(); + } + + /** + * Returns the primary color for the information on controls, from the + * installed theme. + * + * @return The primary color for the information on controls. + */ + public static ColorUIResource getPrimaryControlInfo() + { + return theme.getPrimaryControlInfo(); + } + + /** + * Returns the primary color for the shadow on controls, from the installed + * theme. + * + * @return The primary color for the shadow on controls. + */ + public static ColorUIResource getPrimaryControlShadow() + { + return theme.getPrimaryControlShadow(); + } + + /** + * Returns the background color for separators, from the installed theme. + * + * @return The background color for separators. + */ + public static ColorUIResource getSeparatorBackground() + { + return theme.getSeparatorBackground(); + } + + /** + * Returns the foreground color for separators, from the installed theme. + * + * @return The foreground color for separators. + */ + public static ColorUIResource getSeparatorForeground() + { + return theme.getSeparatorForeground(); + } + + /** + * Returns the font used for sub text, from the installed theme. + * + * @return The font used for sub text. + */ + public static FontUIResource getSubTextFont() + { + return theme.getSubTextFont(); + } + + /** + * Returns the color used for system text, from the installed theme. + * + * @return The color used for system text. + */ + public static ColorUIResource getSystemTextColor() + { + return theme.getSystemTextColor(); + } + + /** + * Returns the font used for system text, from the installed theme. + * + * @return The font used for system text. + */ + public static FontUIResource getSystemTextFont() + { + return theme.getSystemTextFont(); + } + + /** + * Returns the color used to highlight text, from the installed theme. + * + * @return The color used to highlight text. + */ + public static ColorUIResource getTextHighlightColor() + { + return theme.getTextHighlightColor(); + } + + /** + * Returns the color used to display user text, from the installed theme. + * + * @return The color used to display user text. + */ + public static ColorUIResource getUserTextColor() + { + return theme.getUserTextColor(); + } + + /** + * Returns the font used for user text, obtained from the current theme. + * + * @return The font used for user text. + */ + public static FontUIResource getUserTextFont() + { + return theme.getUserTextFont(); + } + + /** + * Returns the color used for white, from the installed theme. + * + * @return The color used for white. + */ + public static ColorUIResource getWhite() + { + return theme.getWhite(); + } + + /** + * Returns the window background color, from the installed theme. + * + * @return The window background color. + */ + public static ColorUIResource getWindowBackground() + { + return theme.getWindowBackground(); + } + + /** + * Returns the window title background color, from the installed theme. + * + * @return The window title background color. + */ + public static ColorUIResource getWindowTitleBackground() + { + return theme.getWindowTitleBackground(); + } + + /** + * Returns the window title font from the current theme. + * + * @return The window title font. + * + * @see MetalTheme + */ + public static FontUIResource getWindowTitleFont() + { + return theme.getWindowTitleFont(); + } + + /** + * Returns the window title foreground color, from the installed theme. + * + * @return The window title foreground color. + */ + public static ColorUIResource getWindowTitleForeground() + { + return theme.getWindowTitleForeground(); + } + + /** + * Returns the background color for an inactive window title, from the + * installed theme. + * + * @return The background color for an inactive window title. + */ + public static ColorUIResource getWindowTitleInactiveBackground() + { + return theme.getWindowTitleInactiveBackground(); + } + + /** + * Returns the foreground color for an inactive window title, from the + * installed theme. + * + * @return The foreground color for an inactive window title. + */ + public static ColorUIResource getWindowTitleInactiveForeground() + { + return theme.getWindowTitleInactiveForeground(); + } + + /** + * Sets the current theme for the look and feel. + * + * @param theme the theme. + */ + public static void setCurrentTheme(MetalTheme theme) + { + MetalLookAndFeel.theme = theme; + } + + /** + * Sets the ComponentUI classes for all Swing components to the Metal + * implementations. + * + * In particular this sets the following keys: + * + * <table> + * <tr> + * <th>Key</th><th>Value</th> + * </tr><tr> + * <td>ButtonUI</td><td>{@link MetalButtonUI}</td> + * </tr><tr> + * <td>CheckBoxUI</td><td>{@link MetalCheckBoxUI}</td> + * </tr><tr> + * <td>ComboBoxUI</td><td>{@link MetalComboBoxUI}</td> + * </tr><tr> + * <td>DesktopIconUI</td><td>{@link MetalDesktopIconUI}</td> + * </tr><tr> + * <td>InternalFrameUI</td><td>{@link MetalInternalFrameUI}</td> + * </tr><tr> + * <td>LabelUI</td><td>{@link MetalLabelUI}</td> + * </tr><tr> + * <td>PopupMenuSeparatorUI</td><td>{@link MetalPopupMenuSeparatorUI}</td> + * </tr><tr> + * <td>ProgressBarUI</td><td>{@link MetalProgressBarUI}</td> + * </tr><tr> + * <td>RadioButtonUI</td><td>{@link MetalRadioButtonUI}</td> + * </tr><tr> + * <td>RootPaneUI</td><td>{@link MetalRootPaneUI}</td> + * </tr><tr> + * <td>ScrollBarUI</td><td>{@link MetalScrollBarUI}</td> + * </tr><tr> + * <td>ScrollPaneUI</td><td>{@link MetalScrollPaneUI}</td> + * </tr><tr> + * <td>SeparatorUI</td><td>{@link MetalSeparatorUI}</td> + * </tr><tr> + * <td>SliderUI</td><td>{@link MetalSliderUI}</td> + * </tr><tr> + * <td>SplitPaneUI</td><td>{@link MetalSplitPaneUI}</td> + * </tr><tr> + * <td>TabbedPaneUI</td><td>{@link MetalTabbedPaneUI}</td> + * </tr><tr> + * <td>TextFieldUI</td><td>{@link MetalTextFieldUI}</td> + * </tr><tr> + * <td>ToggleButtonUI</td><td>{@link MetalToggleButtonUI}</td> + * </tr><tr> + * <td>ToolBarUI</td><td>{@link MetalToolBarUI}</td> + * </tr><tr> + * <td>ToolTipUI</td><td>{@link MetalToolTipUI}</td> + * </tr><tr> + * <td>TreeUI</td><td>{@link MetalTreeUI}</td> + * </tr><tr> + * </table> + * + * @param defaults the UIDefaults where the class defaults are added + */ + protected void initClassDefaults(UIDefaults defaults) + { + super.initClassDefaults(defaults); + + // Variables + Object[] uiDefaults; + // Initialize Class Defaults + uiDefaults = new Object[] { + "ButtonUI", "javax.swing.plaf.metal.MetalButtonUI", + "CheckBoxUI", "javax.swing.plaf.metal.MetalCheckBoxUI", + "ComboBoxUI", "javax.swing.plaf.metal.MetalComboBoxUI", + "DesktopIconUI", "javax.swing.plaf.metal.MetalDesktopIconUI", + "InternalFrameUI", "javax.swing.plaf.metal.MetalInternalFrameUI", + "LabelUI", "javax.swing.plaf.metal.MetalLabelUI", + "PopupMenuSeparatorUI", + "javax.swing.plaf.metal.MetalPopupMenuSeparatorUI", + "ProgressBarUI", "javax.swing.plaf.metal.MetalProgressBarUI", + "RadioButtonUI", "javax.swing.plaf.metal.MetalRadioButtonUI", + "RootPaneUI", "javax.swing.plaf.metal.MetalRootPaneUI", + "ScrollBarUI", "javax.swing.plaf.metal.MetalScrollBarUI", + "ScrollPaneUI", "javax.swing.plaf.metal.MetalScrollPaneUI", + "SeparatorUI", "javax.swing.plaf.metal.MetalSeparatorUI", + "SliderUI", "javax.swing.plaf.metal.MetalSliderUI", + "SplitPaneUI", "javax.swing.plaf.metal.MetalSplitPaneUI", + "TabbedPaneUI", "javax.swing.plaf.metal.MetalTabbedPaneUI", + "TextFieldUI", "javax.swing.plaf.metal.MetalTextFieldUI", + "ToggleButtonUI", "javax.swing.plaf.metal.MetalToggleButtonUI", + "ToolBarUI", "javax.swing.plaf.metal.MetalToolBarUI", + "ToolTipUI", "javax.swing.plaf.metal.MetalToolTipUI", + "TreeUI", "javax.swing.plaf.metal.MetalTreeUI", + }; + // Add Class Defaults to UI Defaults table + defaults.putDefaults(uiDefaults); + } + + /** + * Initializes the component defaults for the Metal Look & Feel. + * + * In particular this sets the following keys (the colors are given + * as RGB hex values): + * + * <table> + * <tr> + * <th>Key</th><th>Value</th> + * </tr><tr> + * <td>Button.background</td><td>0xcccccc</td> + * </tr><tr> + * <td>Button.border</td><td>{@link MetalBorders#getButtonBorder()}</td> + * </tr><tr> + * <td>Button.font</td><td>{@link #getControlTextFont}</td> + * </tr><tr> + * <td>Button.margin</td><td><code>new java.awt.Insets(2, 14, 2, 14)</code> + * </td> + * </tr><tr> + * <td>CheckBox.background</td><td>0xcccccc</td> + * </tr><tr> + * <td>CheckBoxMenuItem.background</td><td>0xcccccc</td> + * </tr><tr> + * <td>ToolBar.background</td><td>0xcccccc</td> + * </tr><tr> + * <td>Panel.background</td><td>0xcccccc</td> + * </tr><tr> + * <td>Slider.background</td><td>0xcccccc</td> + * </tr><tr> + * <td>OptionPane.background</td><td>0xcccccc</td> + * </tr><tr> + * <td>ProgressBar.background</td><td>0xcccccc</td> + * </tr><tr> + * <td>TabbedPane.background</td><td>0xcccccc</td> + * </tr><tr> + * <td>Label.background</td><td>0xcccccc</td> + * </tr><tr> + * <td>Label.font</td><td>{@link #getControlTextFont}</td> + * </tr><tr> + * <td>Menu.background</td><td>0xcccccc</td> + * </tr><tr> + * <td>MenuBar.background</td><td>0xcccccc</td> + * </tr><tr> + * <td>MenuItem.background</td><td>0xcccccc</td> + * </tr><tr> + * <td>ScrollBar.background</td><td>0xcccccc</td> + * </tr><tr> + * <td>PopupMenu.border</td> + * <td><code>new javax.swing.plaf.metal.MetalBorders.PopupMenuBorder()</td> + * </tr><tr> + * </table> + * + * @param defaults the UIDefaults instance to which the values are added + */ + protected void initComponentDefaults(UIDefaults defaults) + { + super.initComponentDefaults(defaults); + Object[] myDefaults = new Object[] { + "Button.background", new ColorUIResource(getControl()), + "Button.border", MetalBorders.getButtonBorder(), + "Button.darkShadow", new ColorUIResource(getControlDarkShadow()), + "Button.disabledText", new ColorUIResource(getControlDisabled()), + "Button.focus", new ColorUIResource(getFocusColor()), + "Button.font", getControlTextFont(), + "Button.foreground", new ColorUIResource(getSystemTextColor()), + "Button.highlight", new ColorUIResource(getControlHighlight()), + "Button.light", new ColorUIResource(getControlHighlight()), + "Button.margin", new Insets(2, 14, 2, 14), + "Button.select", new ColorUIResource(getPrimaryControlShadow()), + "Button.shadow", new ColorUIResource(getPrimaryControlShadow()), + "CheckBox.background", new ColorUIResource(getControl()), + "CheckBoxMenuItem.background", new ColorUIResource(getControl()), + "ToolBar.background", new ColorUIResource(getControl()), + "Panel.background", new ColorUIResource(getControl()), + "Slider.background", new ColorUIResource(getControl()), + "OptionPane.background", new ColorUIResource(getControl()), + "ProgressBar.background", new ColorUIResource(getControl()), + "ScrollPane.border", new MetalBorders.ScrollPaneBorder(), + "TabbedPane.background", new ColorUIResource(getControl()), + "Label.background", new ColorUIResource(getControl()), + "Label.font", getControlTextFont(), + "Label.disabledForeground", new ColorUIResource(getControlDisabled()), + "Label.foreground", new ColorUIResource(getSystemTextColor()), + "Menu.background", new ColorUIResource(getControl()), + "Menu.font", getControlTextFont(), + "MenuBar.background", new ColorUIResource(getControl()), + "MenuBar.font", getControlTextFont(), + "MenuItem.background", new ColorUIResource(getControl()), + "MenuItem.font", getControlTextFont(), + "ScrollBar.background", new ColorUIResource(getControl()), + "ScrollBar.shadow", new ColorUIResource(getControlShadow()), + "ScrollBar.thumb", new ColorUIResource(getPrimaryControlShadow()), + "ScrollBar.thumbDarkShadow", + new ColorUIResource(getPrimaryControlDarkShadow()), + "ScrollBar.thumbHighlight", + new ColorUIResource(getPrimaryControl()), + + "SplitPane.darkShadow", + new ColorUIResource(getControlDarkShadow()), + "SplitPane.highlight", + new ColorUIResource(getControlHighlight()), + + "Tree.openIcon", MetalIconFactory.getTreeFolderIcon(), + "Tree.closedIcon", MetalIconFactory.getTreeFolderIcon(), + "Tree.leafIcon", MetalIconFactory.getTreeLeafIcon(), + "Tree.collapsedIcon", MetalIconFactory.getTreeControlIcon(true), + "Tree.expandedIcon", MetalIconFactory.getTreeControlIcon(false), + "Tree.font", new FontUIResource(new Font("Helvetica", Font.PLAIN, 12)), + "Tree.background", new ColorUIResource(Color.white), + "Tree.foreground", new ColorUIResource(new Color(204, 204, 255)), + "Tree.hash", new ColorUIResource(new Color(204, 204, 255)), + "Tree.leftChildIndent", new Integer(7), + "Tree.rightChildIndent", new Integer(13), + "Tree.rowHeight", new Integer(20), + "Tree.scrollsOnExpand", Boolean.TRUE, + "Tree.selectionBackground", new ColorUIResource(new Color(204, 204, 255)), + "Tree.nonSelectionBackground", new ColorUIResource(Color.white), + "Tree.selectionBorderColor", new ColorUIResource(new Color(102, 102, 153)), + "Tree.selectionForeground", new ColorUIResource(Color.black), + "Tree.textBackground", new ColorUIResource(new Color(204, 204, 255)), + "Tree.textForeground", new ColorUIResource(Color.black), + "Tree.selectionForeground", new ColorUIResource(Color.black), + "PopupMenu.border", new MetalBorders.PopupMenuBorder() + }; + defaults.putDefaults(myDefaults); + } + + /** + * Initializes the system color defaults. + * + * In particular this sets the following keys: + * + * <table> + * <tr> + * <th>Key</th><th>Value</th><th>Description</th> + * </tr><tr> + * <td>control</td><td>0xcccccc</td><td>The default color for components</td> + * </tr> + * </table> + */ + protected void initSystemColorDefaults(UIDefaults defaults) + { + super.initSystemColorDefaults(defaults); + Object[] uiDefaults; + uiDefaults = new Object[] { + "control", new ColorUIResource(getControl()) + }; + defaults.putDefaults(uiDefaults); + } + +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalPopupMenuSeparatorUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalPopupMenuSeparatorUI.java new file mode 100644 index 0000000..ec9bf2b --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalPopupMenuSeparatorUI.java @@ -0,0 +1,73 @@ +/* MetalPopupMenuSeparatorUI.java + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.metal; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; + +public class MetalPopupMenuSeparatorUI + extends MetalSeparatorUI +{ + + // FIXME: maybe replace by a Map of instances when this becomes stateful + /** The shared UI instance for MetalPopupMenuSeparatorUIs */ + private static MetalPopupMenuSeparatorUI instance = null; + + /** + * Constructs a new instance of MetalPopupMenuSeparatorUI. + */ + public MetalPopupMenuSeparatorUI() + { + super(); + } + + /** + * Returns an instance of MetalPopupMenuSeparatorUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalPopupMenuSeparatorUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instance == null) + instance = new MetalPopupMenuSeparatorUI(); + return instance; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalProgressBarUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalProgressBarUI.java new file mode 100644 index 0000000..96d1988 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalProgressBarUI.java @@ -0,0 +1,74 @@ +/* MetalProgressBarUI.java + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.metal; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicProgressBarUI; + +public class MetalProgressBarUI + extends BasicProgressBarUI +{ + + // FIXME: maybe replace by a Map of instances when this becomes stateful + /** The shared UI instance for MetalProgressBarUIs */ + private static MetalProgressBarUI instance = null; + + /** + * Constructs a new instance of MetalProgressBarUI. + */ + public MetalProgressBarUI() + { + super(); + } + + /** + * Returns an instance of MetalProgressBarUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalProgressBarUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instance == null) + instance = new MetalProgressBarUI(); + return instance; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalRadioButtonUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalRadioButtonUI.java new file mode 100644 index 0000000..a668f91 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalRadioButtonUI.java @@ -0,0 +1,74 @@ +/* MetalRadioButtonUI.java + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.metal; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicRadioButtonUI; + +public class MetalRadioButtonUI + extends BasicRadioButtonUI +{ + + // FIXME: maybe replace by a Map of instances when this becomes stateful + /** The shared UI instance for JRadioButtons. */ + private static MetalRadioButtonUI instance = null; + + /** + * Constructs a new instance of MetalRadioButtonUI. + */ + public MetalRadioButtonUI() + { + super(); + } + + /** + * Returns an instance of MetalRadioButtonUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalRadioButtonUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instance == null) + instance = new MetalRadioButtonUI(); + return instance; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java new file mode 100644 index 0000000..4196a4e --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java @@ -0,0 +1,74 @@ +/* MetalRootPaneUI.java + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.metal; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicRootPaneUI; + +public class MetalRootPaneUI + extends BasicRootPaneUI +{ + + // FIXME: maybe replace by a Map of instances when this becomes stateful + /** The shared UI instance for MetalRootPaneUIs */ + private static MetalRootPaneUI instance = null; + + /** + * Constructs a new instance of MetalRootPaneUI. + */ + public MetalRootPaneUI() + { + super(); + } + + /** + * Returns an instance of MetalRootPaneUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalRootPaneUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instance == null) + instance = new MetalRootPaneUI(); + return instance; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java new file mode 100644 index 0000000..526dfb5 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java @@ -0,0 +1,146 @@ +/* MetalScrollBarUI.java + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.metal; + +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.util.HashMap; + +import javax.swing.JComponent; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicScrollBarUI; + +public class MetalScrollBarUI + extends BasicScrollBarUI +{ + + /** The minimum thumb size */ + private static final Dimension MIN_THUMB_SIZE = new Dimension(18, 18); + + // FIXME: maybe replace by a Map of instances when this becomes stateful + /** The shared UI instance for JScrollBars. */ + private static HashMap instances = null; + + /** + * Constructs a new instance of MetalScrollBarUI. + */ + public MetalScrollBarUI() + { + super(); + } + + /** + * Returns an instance of MetalScrollBarUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalScrollBarUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instances == null) + instances = new HashMap(); + + Object o = instances.get(component); + MetalScrollBarUI instance; + if (o == null) + { + instance = new MetalScrollBarUI(); + instances.put(component, instance); + } + else + instance = (MetalScrollBarUI) o; + + return instance; + } + + /** + * Paints the slider button of the ScrollBar. + * + * @param g the Graphics context to use + * @param c the JComponent on which we paint + * @param thumbBounds the rectangle that is the slider button + */ + protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds) + { + // first we fill the background + g.setColor(thumbColor); + g.fillRect(thumbBounds.x, thumbBounds.y, thumbBounds.width, + thumbBounds.height); + + // draw the outer dark line + g.setColor(thumbDarkShadowColor); + g.drawRect(thumbBounds.x, thumbBounds.y, thumbBounds.width - 1, + thumbBounds.height - 1); + + // draw the inner light line + g.setColor(thumbHighlightColor); + g.drawLine(thumbBounds.x + 1, thumbBounds.y + 1, + thumbBounds.x + thumbBounds.width - 2, + thumbBounds.y + 1); + g.drawLine(thumbBounds.x + 1, thumbBounds.y + 1, + thumbBounds.x + 1, + thumbBounds.y + thumbBounds.height - 2); + + // draw the shadow line + UIDefaults def = UIManager.getLookAndFeelDefaults(); + g.setColor(def.getColor("ScrollBar.shadow")); + g.drawLine(thumbBounds.x + 1, thumbBounds.y + thumbBounds.height, + thumbBounds.x + thumbBounds.width, + thumbBounds.y + thumbBounds.height); + + // draw the pattern + MetalUtils.fillMetalPattern(g, thumbBounds.x + 3, thumbBounds.y + 3, + thumbBounds.width - 6, thumbBounds.height - 6, + thumbHighlightColor, thumbDarkShadowColor); + } + + /** + * This method returns the minimum thumb size. + * + * @return The minimum thumb size. + */ + protected Dimension getMinimumThumbSize() + { + return MIN_THUMB_SIZE; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalScrollPaneUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalScrollPaneUI.java new file mode 100644 index 0000000..3e1198b --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalScrollPaneUI.java @@ -0,0 +1,74 @@ +/* MetalScrollPaneUI.java + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.metal; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicScrollPaneUI; + +public class MetalScrollPaneUI + extends BasicScrollPaneUI +{ + + // FIXME: maybe replace by a Map of instances when this becomes stateful + /** The shared UI instance for JScrollPanes. */ + private static MetalScrollPaneUI instance = null; + + /** + * Constructs a new instance of MetalScrollPaneUI. + */ + public MetalScrollPaneUI() + { + super(); + } + + /** + * Returns an instance of MetalScrollPaneUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalScrollPaneUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instance == null) + instance = new MetalScrollPaneUI(); + return instance; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalSeparatorUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalSeparatorUI.java new file mode 100644 index 0000000..6e78ccb --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalSeparatorUI.java @@ -0,0 +1,74 @@ +/* MetalSeparatorUI.java + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.metal; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicSeparatorUI; + +public class MetalSeparatorUI + extends BasicSeparatorUI +{ + + // FIXME: maybe replace by a Map of instances when this becomes stateful + /** The shared UI instance for MetalSeparatorUIs */ + private static MetalSeparatorUI instance = null; + + /** + * Constructs a new instance of MetalSeparatorUI. + */ + public MetalSeparatorUI() + { + super(); + } + + /** + * Returns an instance of MetalSeparatorUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalSeparatorUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instance == null) + instance = new MetalSeparatorUI(); + return instance; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalSliderUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalSliderUI.java new file mode 100644 index 0000000..a857d6a --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalSliderUI.java @@ -0,0 +1,87 @@ +/* MetalSliderUI.java + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.metal; + +import java.util.HashMap; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicSliderUI; + +public class MetalSliderUI + extends BasicSliderUI +{ + + /** The UI instances for MetalSliderUIs */ + private static HashMap instances; + + /** + * Constructs a new instance of MetalSliderUI. + */ + public MetalSliderUI() + { + super(null); + } + + /** + * Returns an instance of MetalSliderUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalSliderUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instances == null) + instances = new HashMap(); + + + Object o = instances.get(component); + MetalSliderUI instance; + if (o == null) + { + instance = new MetalSliderUI(); + instances.put(component, instance); + } + else + instance = (MetalSliderUI) o; + + return instance; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneDivider.java b/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneDivider.java new file mode 100644 index 0000000..60e9c05 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneDivider.java @@ -0,0 +1,84 @@ +/* MetalSplitPaneDivider.java +Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf.metal; + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; + +import javax.swing.plaf.basic.BasicSplitPaneDivider; + +/** + * The divider that is used by the MetalSplitPaneUI. + * + * @author Roman Kennke (roman@kennke.org) + * + */ +class MetalSplitPaneDivider extends BasicSplitPaneDivider +{ + /** The dark color in the pattern. */ + Color dark; + + /** The light color in the pattern. */ + Color light; + + /** + * Creates a new instance of MetalSplitPaneDivider. + * + * @param ui the <code>MetalSplitPaneUI</code> that uses this divider + */ + public MetalSplitPaneDivider(MetalSplitPaneUI ui, Color light, Color dark) + { + super(ui); + this.light = light; + this.dark = dark; + } + + /** + * Paints the divider. + * + * @param g the <code>Graphics</code> context to use for painting + */ + public void paint(Graphics g) + { + //super.paint(g); + Dimension s = getSize(); + MetalUtils.fillMetalPattern(g, 2, 2, s.width - 4, s.height - 4, + light, dark); + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneUI.java new file mode 100644 index 0000000..b7ea898 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneUI.java @@ -0,0 +1,106 @@ +/* MetalSplitPaneUI.java + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.metal; + +import java.awt.Color; +import java.util.HashMap; + +import javax.swing.JComponent; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicSplitPaneUI; +import javax.swing.plaf.basic.BasicSplitPaneDivider; + +public class MetalSplitPaneUI + extends BasicSplitPaneUI +{ + + /** The UI instances for MetalSplitPaneUIs */ + private static HashMap instances; + + /** + * Constructs a new instance of MetalSplitPaneUI. + */ + public MetalSplitPaneUI() + { + super(); + } + + /** + * Returns an instance of MetalSplitPaneUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalSplitPaneUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instances == null) + instances = new HashMap(); + + Object o = instances.get(component); + MetalSplitPaneUI instance; + if (o == null) + { + instance = new MetalSplitPaneUI(); + instances.put(component, instance); + } + else + instance = (MetalSplitPaneUI) o; + + return instance; + } + + /** + * Returns the divider that is used by the <code>JSplitPane</code>. + * + * The divider returned by this method is a {@link BasicSplitPaneDivider} + * that is drawn using the Metal look. + * + * @return the default divider to use for <code>JSplitPane</code>s. + */ + public BasicSplitPaneDivider createDefaultDivider() + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + Color light = defaults.getColor("SplitPane.highlight"); + Color dark = defaults.getColor("SplitPane.darkShadow"); + return new MetalSplitPaneDivider(this, light, dark); + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java new file mode 100644 index 0000000..bf50f91 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java @@ -0,0 +1,86 @@ +/* MetalTabbedPaneUI.java + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.metal; + +import java.util.HashMap; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicTabbedPaneUI; + +public class MetalTabbedPaneUI + extends BasicTabbedPaneUI +{ + + /** The shared UI instance for JTabbedPanes. */ + private static HashMap instances = null; + + /** + * Constructs a new instance of MetalTabbedPaneUI. + */ + public MetalTabbedPaneUI() + { + super(); + } + + /** + * Returns an instance of MetalTabbedPaneUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalTabbedPaneUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instances == null) + instances = new HashMap(); + + Object o = instances.get(component); + MetalTabbedPaneUI instance; + if (o == null) + { + instance = new MetalTabbedPaneUI(); + instances.put(component, instance); + } + else + instance = (MetalTabbedPaneUI) o; + + return instance; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalTextFieldUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalTextFieldUI.java new file mode 100644 index 0000000..d6e50e1 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalTextFieldUI.java @@ -0,0 +1,86 @@ +/* MetalTextFieldUI.java + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.metal; + +import java.util.HashMap; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicTextFieldUI; + +public class MetalTextFieldUI + extends BasicTextFieldUI +{ + + /** The UI instances for MetalTextFieldUIs */ + private static HashMap instances = null; + + /** + * Constructs a new instance of MetalTextFieldUI. + */ + public MetalTextFieldUI() + { + super(); + } + + /** + * Returns an instance of MetalTextFieldUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalTextFieldUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instances == null) + instances = new HashMap(); + + Object o = instances.get(component); + MetalTextFieldUI instance; + if (o == null) + { + instance = new MetalTextFieldUI(); + instances.put(component, instance); + } + else + instance = (MetalTextFieldUI) o; + + return instance; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalTheme.java b/libjava/classpath/javax/swing/plaf/metal/MetalTheme.java new file mode 100644 index 0000000..d5131af --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalTheme.java @@ -0,0 +1,576 @@ +/* MetalTheme.java -- + Copyright (C) 2004, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + + +package javax.swing.plaf.metal; + +import java.awt.Color; + +import javax.swing.UIDefaults; +import javax.swing.plaf.ColorUIResource; +import javax.swing.plaf.FontUIResource; + +/** + * The base class for themes used by the {@link MetalLookAndFeel}. A default + * theme ({@link DefaultMetalTheme}) is provided, or you can create and use + * your own. + * + * @see MetalLookAndFeel#setCurrentTheme(MetalTheme) + */ +public abstract class MetalTheme +{ + private ColorUIResource BLACK = new ColorUIResource(Color.BLACK); + private ColorUIResource WHITE = new ColorUIResource(Color.WHITE); + + /** + * Default constructor. + */ + public MetalTheme() + { + // Do nothing here. + } + + /** + * Returns the name of the theme. + * + * @return The name of the theme. + */ + public abstract String getName(); + + /** + * Adds custom entries to the UI defaults table. This method is empty. + * + * @param table the table. + */ + public void addCustomEntriesToTable(UIDefaults table) + { + // Do nothing here. + // This method needs to be overridden to actually do something. + // It is called from MetalLookAndFeel.getDefaults(). + } + + /** + * Returns the accelerator foreground color. The default implementation + * returns the color from {@link #getPrimary1()}. + * + * @return The accelerator foreground color. + */ + public ColorUIResource getAcceleratorForeground() + { + return getPrimary1(); + } + + /** + * Returns the accelerator selected foreground color. The default + * implementation returns the color from {@link #getBlack()}. + * + * @return The accelerator selected foreground color. + */ + public ColorUIResource getAcceleratorSelectedForeground() + { + return getBlack(); + } + + /** + * Returns the control color. The default implementation returns the color + * from {@link #getSecondary3()}. + * + * @return The control color. + */ + public ColorUIResource getControl() + { + return getSecondary3(); + } + + /** + * Returns the color used for dark shadows on controls. The default + * implementation returns the color from {@link #getSecondary1()}. + * + * @return The color used for dark shadows on controls. + */ + public ColorUIResource getControlDarkShadow() + { + return getSecondary1(); + } + + /** + * Returns the color used for disabled controls. The default implementation + * returns the color from {@link #getSecondary1()}. + * + * @return The color used for disabled controls. + */ + public ColorUIResource getControlDisabled() + { + return getSecondary2(); + } + + /** + * Returns the color used to draw highlights for controls. The default + * implementation returns the color from {@link #getWhite()}. + * + * @return The color used to draw highlights for controls. + */ + public ColorUIResource getControlHighlight() + { + return getWhite(); + } + + /** + * Returns the color used to display control info. The default + * implementation returns the color from {@link #getBlack()}. + * + * @return The color used to display control info. + */ + public ColorUIResource getControlInfo() + { + return getBlack(); + } + + /** + * Returns the color used to draw shadows for controls. The default + * implementation returns the color from {@link #getSecondary2()}. + * + * @return The color used to draw shadows for controls. + */ + public ColorUIResource getControlShadow() + { + return getSecondary2(); + } + + /** + * Returns the color used for text on controls. The default implementation + * returns the color from {@link #getControlInfo()}. + * + * @return The color used for text on controls. + */ + public ColorUIResource getControlTextColor() + { + return getControlInfo(); + } + + /** + * Returns the color used for the desktop background. The default + * implementation returns the color from {@link #getPrimary2()}. + * + * @return The color used for the desktop background. + */ + public ColorUIResource getDesktopColor() + { + return getPrimary2(); + } + + /** + * Returns the color used to draw focus highlights. The default + * implementation returns the color from {@link #getPrimary2()}. + * + * @return The color used to draw focus highlights. + */ + public ColorUIResource getFocusColor() + { + return getPrimary2(); + } + + /** + * Returns the color used to draw highlighted text. The default + * implementation returns the color from {@link #getHighlightedTextColor()}. + * + * @return The color used to draw highlighted text. + */ + public ColorUIResource getHighlightedTextColor() + { + return getControlTextColor(); + } + + /** + * Returns the color used to draw text on inactive controls. The default + * implementation returns the color from {@link #getControlDisabled()}. + * + * @return The color used to draw text on inactive controls. + */ + public ColorUIResource getInactiveControlTextColor() + { + return getControlDisabled(); + } + + /** + * Returns the color used to draw inactive system text. The default + * implementation returns the color from {@link #getSecondary2()}. + * + * @return The color used to draw inactive system text. + */ + public ColorUIResource getInactiveSystemTextColor() + { + return getSecondary2(); + } + + /** + * Returns the background color for menu items. The default implementation + * returns the color from {@link #getSecondary3()}. + * + * @return The background color for menu items. + * + * @see #getMenuSelectedBackground() + */ + public ColorUIResource getMenuBackground() + { + return getSecondary3(); + } + + /** + * Returns the foreground color for disabled menu items. The default + * implementation returns the color from {@link #getSecondary2()}. + * + * @return The foreground color for disabled menu items. + * + * @see #getMenuForeground() + */ + public ColorUIResource getMenuDisabledForeground() + { + return getSecondary2(); + } + + /** + * Returns the foreground color for menu items. The default implementation + * returns the color from {@link #getBlack()}. + * + * @return The foreground color for menu items. + * + * @see #getMenuDisabledForeground() + * @see #getMenuSelectedForeground() + */ + public ColorUIResource getMenuForeground() + { + return getBlack(); + } + + /** + * Returns the background color for selected menu items. The default + * implementation returns the color from {@link #getPrimary2()}. + * + * @return The background color for selected menu items. + * + * @see #getMenuBackground() + */ + public ColorUIResource getMenuSelectedBackground() + { + return getPrimary2(); + } + + /** + * Returns the foreground color for selected menu items. The default + * implementation returns the value from {@link #getBlack()}. + * + * @return The foreground color for selected menu items. + * + * @see #getMenuForeground() + */ + public ColorUIResource getMenuSelectedForeground() + { + return getBlack(); + } + + /** + * Returns the primary color for controls. The default implementation + * returns the color from {@link #getPrimary3()}. + * + * @return The primary color for controls. + */ + public ColorUIResource getPrimaryControl() + { + return getPrimary3(); + } + + /** + * Returns the primary color for the dark shadow on controls. The default + * implementation returns the color from {@link #getPrimary1()}. + * + * @return The primary color for the dark shadow on controls. + */ + public ColorUIResource getPrimaryControlDarkShadow() + { + return getPrimary1(); + } + + /** + * Returns the primary color for the highlight on controls. The default + * implementation returns the color from {@link #getWhite()}. + * + * @return The primary color for the highlight on controls. + */ + public ColorUIResource getPrimaryControlHighlight() + { + return getWhite(); + } + + /** + * Returns the primary color for the information on controls. The default + * implementation returns the color from {@link #getBlack()}. + * + * @return The primary color for the information on controls. + */ + public ColorUIResource getPrimaryControlInfo() + { + return getBlack(); + } + + /** + * Returns the primary color for the shadow on controls. The default + * implementation returns the color from {@link #getPrimary2()}. + * + * @return The primary color for the shadow on controls. + */ + public ColorUIResource getPrimaryControlShadow() + { + return getPrimary2(); + } + + /** + * Returns the background color for separators. The default implementation + * returns the color from {@link #getWhite()}. + * + * @return The background color for separators. + */ + public ColorUIResource getSeparatorBackground() + { + return getWhite(); + } + + /** + * Returns the foreground color for separators. The default implementation + * returns the value from {@link #getPrimary1()}. + * + * @return The foreground color for separators. + */ + public ColorUIResource getSeparatorForeground() + { + return getPrimary1(); + } + + /** + * Returns the color used for system text. The default implementation + * returns the color from {@link #getBlack()}. + * + * @return The color used for system text. + */ + public ColorUIResource getSystemTextColor() + { + return getBlack(); + } + + /** + * Returns the color used to highlight text. The default implementation + * returns the color from {@link #getPrimary3()}. + * + * @return The color used to highlight text. + */ + public ColorUIResource getTextHighlightColor() + { + return getPrimary3(); + } + + /** + * Returns the color used to display user text. The default implementation + * returns the color from {@link #getBlack()}. + * + * @return The color used to display user text. + */ + public ColorUIResource getUserTextColor() + { + return getBlack(); + } + + /** + * Returns the window background color. The default implementation returns + * the color from {@link #getWhite()}. + * + * @return The window background color. + */ + public ColorUIResource getWindowBackground() + { + return getWhite(); + } + + /** + * Returns the window title background color. The default implementation + * returns the color from {@link #getPrimary3()}. + * + * @return The window title background color. + */ + public ColorUIResource getWindowTitleBackground() + { + return getPrimary3(); + } + + /** + * Returns the window title foreground color. The default implementation + * returns the color from {@link #getBlack()}. + * + * @return The window title foreground color. + */ + public ColorUIResource getWindowTitleForeground() + { + return getBlack(); + } + + /** + * Returns the background color for an inactive window title. The default + * implementation returns the color from {@link #getSecondary3()}. + * + * @return The background color for an inactive window title. + */ + public ColorUIResource getWindowTitleInactiveBackground() + { + return getSecondary3(); + } + + /** + * Returns the foreground color for an inactive window title. The default + * implementation returns the color from {@link #getBlack()}. + * + * @return The foreground color for an inactive window title. + */ + public ColorUIResource getWindowTitleInactiveForeground() + { + return getBlack(); + } + + /** + * Returns the color used for black. + * + * @return The color used for black. + */ + protected ColorUIResource getBlack() + { + return BLACK; + } + + /** + * Returns the color used for white. + * + * @return The color used for white. + */ + protected ColorUIResource getWhite() + { + return WHITE; + } + + /** + * Returns the first primary color for this theme. + * + * @return The first primary color. + */ + protected abstract ColorUIResource getPrimary1(); + + /** + * Returns the second primary color for this theme. + * + * @return The second primary color. + */ + protected abstract ColorUIResource getPrimary2(); + + /** + * Returns the third primary color for this theme. + * + * @return The third primary color. + */ + protected abstract ColorUIResource getPrimary3(); + + /** + * Returns the first secondary color for this theme. + * + * @return The first secondary color. + */ + protected abstract ColorUIResource getSecondary1(); + + /** + * Returns the second secondary color for this theme. + * + * @return The second secondary color. + */ + protected abstract ColorUIResource getSecondary2(); + + /** + * Returns the third secondary color for this theme. + * + * @return The third secondary color. + */ + protected abstract ColorUIResource getSecondary3(); + + /** + * Returns the font used for text on controls. + * + * @return The font used for text on controls. + */ + public abstract FontUIResource getControlTextFont(); + + /** + * Returns the font used for text in menus. + * + * @return The font used for text in menus. + */ + public abstract FontUIResource getMenuTextFont(); + + /** + * Returns the font used for sub text. + * + * @return The font used for sub text. + */ + public abstract FontUIResource getSubTextFont(); + + /** + * Returns the font used for system text. + * + * @return The font used for system text. + */ + public abstract FontUIResource getSystemTextFont(); + + /** + * Returns the font used for user text. + * + * @return The font used for user text. + */ + public abstract FontUIResource getUserTextFont(); + + /** + * Returns the font used for window titles. + * + * @return The font used for window titles. + */ + public abstract FontUIResource getWindowTitleFont(); + +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalToggleButtonUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalToggleButtonUI.java new file mode 100644 index 0000000..7913cdb --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalToggleButtonUI.java @@ -0,0 +1,74 @@ +/* MetalToggleButtonUI.java + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.metal; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicToggleButtonUI; + +public class MetalToggleButtonUI + extends BasicToggleButtonUI +{ + + // FIXME: maybe replace by a Map of instances when this becomes stateful + /** The shared UI instance for MetalToggleButtonUIs */ + private static MetalToggleButtonUI instance = null; + + /** + * Constructs a new instance of MetalToggleButtonUI. + */ + public MetalToggleButtonUI() + { + super(); + } + + /** + * Returns an instance of MetalToggleButtonUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalToggleButtonUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instance == null) + instance = new MetalToggleButtonUI(); + return instance; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalToolBarUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalToolBarUI.java new file mode 100644 index 0000000..39af001 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalToolBarUI.java @@ -0,0 +1,74 @@ +/* MetalToolBarUI.java + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.metal; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicToolBarUI; + +public class MetalToolBarUI + extends BasicToolBarUI +{ + + // FIXME: maybe replace by a Map of instances when this becomes stateful + /** The shared UI instance for MetalToolBarUIs */ + private static MetalToolBarUI instance = null; + + /** + * Constructs a new instance of MetalToolBarUI. + */ + public MetalToolBarUI() + { + super(); + } + + /** + * Returns an instance of MetalToolBarUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalToolBarUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instance == null) + instance = new MetalToolBarUI(); + return instance; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalToolTipUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalToolTipUI.java new file mode 100644 index 0000000..c88b653 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalToolTipUI.java @@ -0,0 +1,74 @@ +/* MetalToolTipUI.java + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.metal; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicToolTipUI; + +public class MetalToolTipUI + extends BasicToolTipUI +{ + + // FIXME: maybe replace by a Map of instances when this becomes stateful + /** The shared UI instance for MetalToolTipUIs */ + private static MetalToolTipUI instance = null; + + /** + * Constructs a new instance of MetalToolTipUI. + */ + public MetalToolTipUI() + { + super(); + } + + /** + * Returns an instance of MetalToolTipUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalToolTipUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instance == null) + instance = new MetalToolTipUI(); + return instance; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalTreeUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalTreeUI.java new file mode 100644 index 0000000..d85d61c --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalTreeUI.java @@ -0,0 +1,86 @@ +/* MetalTreeUI.java + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package javax.swing.plaf.metal; + +import java.util.HashMap; + +import javax.swing.JComponent; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicTreeUI; + +public class MetalTreeUI + extends BasicTreeUI +{ + + /** The UI instances for MetalTreeUIs */ + private static HashMap instances = null; + + /** + * Constructs a new instance of MetalTreeUI. + */ + public MetalTreeUI() + { + super(); + } + + /** + * Returns an instance of MetalTreeUI. + * + * @param component the component for which we return an UI instance + * + * @return an instance of MetalTreeUI + */ + public static ComponentUI createUI(JComponent component) + { + if (instances == null) + instances = new HashMap(); + + Object o = instances.get(component); + MetalTreeUI instance; + if (o == null) + { + instance = new MetalTreeUI(); + instances.put(component, instance); + } + else + instance = (MetalTreeUI) o; + + return instance; + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalUtils.java b/libjava/classpath/javax/swing/plaf/metal/MetalUtils.java new file mode 100644 index 0000000..a342ee0 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalUtils.java @@ -0,0 +1,87 @@ +/* Metaltils.java +Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + +package javax.swing.plaf.metal; + +import java.awt.Color; +import java.awt.Graphics; + +/** + * Some utility and helper methods for the Metal Look & Feel. + * + * @author Roman Kennke (roman@kennke.org) + */ +class MetalUtils +{ + + /** + * Fills a rectangle with the typical Metal pattern. + * + * @param g the <code>Graphics</code> context to use + * @param x the X coordinate of the upper left corner of the rectangle to + * fill + * @param y the Y coordinate of the upper left corner of the rectangle to + * fill + * @param w the width of the rectangle to fill + * @param w the height of the rectangle to fill + * @param light the light color to use + * @param dark the dark color to use + */ + static void fillMetalPattern(Graphics g, int x, int y, int w, int h, + Color light, Color dark) + { + int xOff = 0; + for (int mY = y; mY < (y + h); mY++) + { + // set color alternating with every line + if ((mY % 2) == 0) + g.setColor(light); + else + g.setColor(dark); + + for (int mX = x + (xOff); mX < (x + w); mX += 4) + { + g.drawLine(mX, mY, mX, mY); + } + + // increase x offset + xOff++; + if (xOff > 3) + xOff = 0; + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/package.html b/libjava/classpath/javax/swing/plaf/metal/package.html new file mode 100644 index 0000000..2ea787b --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/package.html @@ -0,0 +1,46 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in javax.swing.plaf.metal package. + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. --> + +<html> +<head><title>GNU Classpath - javax.swing.plaf.metal</title></head> + +<body> +<p>Provides a cross-platform look and feel known as "Metal".</p> + +</body> +</html> diff --git a/libjava/classpath/javax/swing/plaf/package.html b/libjava/classpath/javax/swing/plaf/package.html new file mode 100644 index 0000000..c266074 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/package.html @@ -0,0 +1,47 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> +<!-- package.html - describes classes in javax.swing.plaf package. + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. --> + +<html> +<head><title>GNU Classpath - javax.swing.plaf</title></head> + +<body> +<p>A base package for the "pluggable look and feel" (plaf) mechanism used by +the <code>javax.swing</code> classes.</p> + +</body> +</html> |