aboutsummaryrefslogtreecommitdiff
path: root/libjava/classpath/javax/swing/plaf
diff options
context:
space:
mode:
authorTom Tromey <tromey@gcc.gnu.org>2005-07-16 00:30:23 +0000
committerTom Tromey <tromey@gcc.gnu.org>2005-07-16 00:30:23 +0000
commitf911ba985aa7fe0096c386c5be385ac5825ea527 (patch)
treea0b991cf5866ae1d616639b906ac001811d74508 /libjava/classpath/javax/swing/plaf
parent6f4434b39b261de5317dc81ddfdd94d2e1d62b11 (diff)
downloadgcc-f911ba985aa7fe0096c386c5be385ac5825ea527.zip
gcc-f911ba985aa7fe0096c386c5be385ac5825ea527.tar.gz
gcc-f911ba985aa7fe0096c386c5be385ac5825ea527.tar.bz2
Initial revision
From-SVN: r102074
Diffstat (limited to 'libjava/classpath/javax/swing/plaf')
-rw-r--r--libjava/classpath/javax/swing/plaf/ActionMapUIResource.java64
-rw-r--r--libjava/classpath/javax/swing/plaf/BorderUIResource.java933
-rw-r--r--libjava/classpath/javax/swing/plaf/ButtonUI.java52
-rw-r--r--libjava/classpath/javax/swing/plaf/ColorChooserUI.java60
-rw-r--r--libjava/classpath/javax/swing/plaf/ColorUIResource.java123
-rw-r--r--libjava/classpath/javax/swing/plaf/ComboBoxUI.java96
-rw-r--r--libjava/classpath/javax/swing/plaf/ComponentInputMapUIResource.java70
-rw-r--r--libjava/classpath/javax/swing/plaf/ComponentUI.java326
-rw-r--r--libjava/classpath/javax/swing/plaf/DesktopIconUI.java56
-rw-r--r--libjava/classpath/javax/swing/plaf/DesktopPaneUI.java59
-rw-r--r--libjava/classpath/javax/swing/plaf/DimensionUIResource.java68
-rw-r--r--libjava/classpath/javax/swing/plaf/FileChooserUI.java138
-rw-r--r--libjava/classpath/javax/swing/plaf/FontUIResource.java101
-rw-r--r--libjava/classpath/javax/swing/plaf/IconUIResource.java122
-rw-r--r--libjava/classpath/javax/swing/plaf/InputMapUIResource.java63
-rw-r--r--libjava/classpath/javax/swing/plaf/InsetsUIResource.java77
-rw-r--r--libjava/classpath/javax/swing/plaf/InternalFrameUI.java59
-rw-r--r--libjava/classpath/javax/swing/plaf/LabelUI.java59
-rw-r--r--libjava/classpath/javax/swing/plaf/ListUI.java114
-rw-r--r--libjava/classpath/javax/swing/plaf/MenuBarUI.java59
-rw-r--r--libjava/classpath/javax/swing/plaf/MenuItemUI.java59
-rw-r--r--libjava/classpath/javax/swing/plaf/OptionPaneUI.java75
-rw-r--r--libjava/classpath/javax/swing/plaf/PanelUI.java58
-rw-r--r--libjava/classpath/javax/swing/plaf/PopupMenuUI.java117
-rw-r--r--libjava/classpath/javax/swing/plaf/ProgressBarUI.java59
-rw-r--r--libjava/classpath/javax/swing/plaf/RootPaneUI.java58
-rw-r--r--libjava/classpath/javax/swing/plaf/ScrollBarUI.java58
-rw-r--r--libjava/classpath/javax/swing/plaf/ScrollPaneUI.java59
-rw-r--r--libjava/classpath/javax/swing/plaf/SeparatorUI.java58
-rw-r--r--libjava/classpath/javax/swing/plaf/SliderUI.java59
-rw-r--r--libjava/classpath/javax/swing/plaf/SpinnerUI.java59
-rw-r--r--libjava/classpath/javax/swing/plaf/SplitPaneUI.java133
-rw-r--r--libjava/classpath/javax/swing/plaf/TabbedPaneUI.java111
-rw-r--r--libjava/classpath/javax/swing/plaf/TableHeaderUI.java59
-rw-r--r--libjava/classpath/javax/swing/plaf/TableUI.java59
-rw-r--r--libjava/classpath/javax/swing/plaf/TextUI.java284
-rw-r--r--libjava/classpath/javax/swing/plaf/ToolBarUI.java59
-rw-r--r--libjava/classpath/javax/swing/plaf/ToolTipUI.java59
-rw-r--r--libjava/classpath/javax/swing/plaf/TreeUI.java211
-rw-r--r--libjava/classpath/javax/swing/plaf/UIResource.java55
-rw-r--r--libjava/classpath/javax/swing/plaf/ViewportUI.java60
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicArrowButton.java350
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicBorders.java1814
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicButtonListener.java231
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicButtonUI.java421
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxMenuItemUI.java104
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxUI.java73
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicColorChooserUI.java339
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicComboBoxEditor.java170
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicComboBoxRenderer.java142
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicComboBoxUI.java1243
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicComboPopup.java1055
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicDesktopIconUI.java590
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicDesktopPaneUI.java464
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicDirectoryModel.java313
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicEditorPaneUI.java68
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicFileChooserUI.java1921
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicFormattedTextFieldUI.java62
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicGraphicsUtils.java641
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicIconFactory.java238
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameTitlePane.java940
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameUI.java1719
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicLabelUI.java425
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicListUI.java1004
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicLookAndFeel.java1058
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicMenuBarUI.java304
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicMenuItemUI.java1006
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicMenuUI.java541
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicOptionPaneUI.java1329
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicPanelUI.java67
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicPasswordFieldUI.java67
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuSeparatorUI.java114
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuUI.java674
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicProgressBarUI.java827
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonMenuItemUI.java102
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonUI.java87
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicRootPaneUI.java66
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicScrollBarUI.java1271
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicScrollPaneUI.java130
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicSeparatorUI.java269
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicSliderUI.java2239
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicSpinnerUI.java574
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneDivider.java912
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneUI.java1556
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicTabbedPaneUI.java3084
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicTableHeaderUI.java224
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicTableUI.java398
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicTextAreaUI.java68
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicTextFieldUI.java80
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicTextPaneUI.java68
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicTextUI.java635
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicToggleButtonUI.java62
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicToolBarSeparatorUI.java127
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicToolBarUI.java1435
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicToolTipUI.java288
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicTreeUI.java2813
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/BasicViewportUI.java234
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/ComboPopup.java103
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/DefaultMenuLayout.java78
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders-1.pngbin0 -> 454 bytes
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders-2.pngbin0 -> 857 bytes
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.ButtonBorder-1.pngbin0 -> 1787 bytes
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.FieldBorder-1.pngbin0 -> 5267 bytes
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.MarginBorder-1.pngbin0 -> 14735 bytes
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.MenuBarBorder-1.pngbin0 -> 3180 bytes
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.RadioButtonBorder-1.pngbin0 -> 2667 bytes
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.SplitPaneBorder-1.pngbin0 -> 8803 bytes
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.SplitPaneBorder-2.pngbin0 -> 5976 bytes
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.SplitPaneDividerBorder-1.pngbin0 -> 7169 bytes
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.ToggleButtonBorder-1.pngbin0 -> 1874 bytes
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-1.pngbin0 -> 4844 bytes
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-2.pngbin0 -> 3771 bytes
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-3.pngbin0 -> 13480 bytes
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-4.pngbin0 -> 4832 bytes
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-5.pngbin0 -> 6884 bytes
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-6.pngbin0 -> 6816 bytes
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-7.pngbin0 -> 3676 bytes
-rw-r--r--libjava/classpath/javax/swing/plaf/basic/package.html46
-rw-r--r--libjava/classpath/javax/swing/plaf/doc-files/ComponentUI-1.diabin0 -> 3085 bytes
-rw-r--r--libjava/classpath/javax/swing/plaf/doc-files/ComponentUI-1.pngbin0 -> 32683 bytes
-rw-r--r--libjava/classpath/javax/swing/plaf/doc-files/TreeUI-1.pngbin0 -> 8660 bytes
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/DefaultMetalTheme.java221
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalBorders.java443
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalButtonUI.java101
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxIcon.java136
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxUI.java74
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalComboBoxIcon.java100
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalComboBoxUI.java86
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalDesktopIconUI.java74
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalIconFactory.java672
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameUI.java88
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalLabelUI.java74
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java853
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalPopupMenuSeparatorUI.java73
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalProgressBarUI.java74
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalRadioButtonUI.java74
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java74
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java146
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalScrollPaneUI.java74
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalSeparatorUI.java74
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalSliderUI.java87
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneDivider.java84
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneUI.java106
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java86
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalTextFieldUI.java86
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalTheme.java576
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalToggleButtonUI.java74
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalToolBarUI.java74
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalToolTipUI.java74
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalTreeUI.java86
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/MetalUtils.java87
-rw-r--r--libjava/classpath/javax/swing/plaf/metal/package.html46
-rw-r--r--libjava/classpath/javax/swing/plaf/package.html47
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&#x2019;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>&#x2019;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>&#x2019;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>&#x2019;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>&#x2019;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&#x2019;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&#x2019;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&#x2019;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
+ * &#x201c;logical&#x201d; names are supported by any Java
+ * implementation. These are
+ * <code>&#x201c;Dialog&#x201d;</code>,
+ * <code>&#x201c;DialogInput&#x201d;</code>,
+ * <code>&#x201c;Monospaced&#x201d;</code>,
+ * <code>&#x201c;Serif&#x201d;</code>, and
+ * <code>&#x201c;SansSerif&#x201d;</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&#x2019;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>&#x201c;Button.shadow&#x201d;</code>,
+ * <code>&#x201c;Button.darkShadow&#x201d;</code>,
+ * <code>&#x201c;Button.light&#x201d;</code>, and
+ * <code>&#x201c;Button.highlight&#x201d;</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>&#x201c;RadioButton.shadow&#x201d;</code>,
+ * <code>&#x201c;RadioButton.darkShadow&#x201d;</code>,
+ * <code>&#x201c;RadioButton.light&#x201d;</code>, and
+ * <code>&#x201c;RadioButton.highlight&#x201d;</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>&#x201c;ToggleButton.shadow&#x201d;</code>,
+ * <code>&#x201c;ToggleButton.darkShadow&#x201d;</code>,
+ * <code>&#x201c;ToggleButton.light&#x201d;</code>, and
+ * <code>&#x201c;ToggleButton.highlight&#x201d;</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>&#x201c;MenuBar.shadow&#x201d;</code> and
+ * <code>&#x201c;MenuBar.highlight&#x201d;</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>&#x201c;SplitPane.darkShadow&#x201d;</code> and
+ * <code>&#x201c;SplitPane.highlight&#x201d;</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>&#x201c;SplitPane.darkShadow&#x201d;</code> and
+ * <code>&#x201c;SplitPane.highlight&#x201d;</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>&#x201c;TextField.shadow&#x201d;</code>,
+ * <code>&#x201c;TextField.darkShadow&#x201d;</code>,
+ * <code>&#x201c;TextField.light&#x201d;</code>, and
+ * <code>&#x201c;TextField.highlight&#x201d;</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>&#x201c;InternalFrame.borderShadow&#x201d;</code>,
+ * <code>&#x201c;InternalFrame.borderDarkShadow&#x201d;</code>,
+ * <code>&#x201c;InternalFrame.borderLight&#x201d;</code>,
+ * <code>&#x201c;InternalFrame.borderHighlight&#x201d;</code>, and
+ * (for the inner one-pixel thick line)
+ * <code>&#x201c;InternalFrame.borderColor&#x201d;</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&#x2019;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 &apos;Button&apos; 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 &#x201c;bug ID&#x201d; 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&#x2019;s text and icon.
+ *
+ * @param b the button whose preferred size is determined.
+ *
+ * @param textIconGap the gap between the button&#x2019;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 &apos;ToggleButton&apos; 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
new file mode 100644
index 0000000..daeb16c
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders-1.png
Binary files differ
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
new file mode 100644
index 0000000..60f6a8a
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders-2.png
Binary files differ
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
new file mode 100644
index 0000000..54047dc
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.ButtonBorder-1.png
Binary files differ
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
new file mode 100644
index 0000000..7c89911
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.FieldBorder-1.png
Binary files differ
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
new file mode 100644
index 0000000..a3841ba
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.MarginBorder-1.png
Binary files differ
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
new file mode 100644
index 0000000..13a9fa4e
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.MenuBarBorder-1.png
Binary files differ
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
new file mode 100644
index 0000000..a6408ec
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.RadioButtonBorder-1.png
Binary files differ
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
new file mode 100644
index 0000000..db283c2
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.SplitPaneBorder-1.png
Binary files differ
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
new file mode 100644
index 0000000..65381bd
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.SplitPaneBorder-2.png
Binary files differ
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
new file mode 100644
index 0000000..c22763a
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.SplitPaneDividerBorder-1.png
Binary files differ
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
new file mode 100644
index 0000000..f898bee
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicBorders.ToggleButtonBorder-1.png
Binary files differ
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
new file mode 100644
index 0000000..99f8c6e
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-1.png
Binary files differ
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
new file mode 100644
index 0000000..59d9a61
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-2.png
Binary files differ
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
new file mode 100644
index 0000000..5b0971c
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-3.png
Binary files differ
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
new file mode 100644
index 0000000..ceba0b6e
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-4.png
Binary files differ
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
new file mode 100644
index 0000000..fa3055f
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-5.png
Binary files differ
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
new file mode 100644
index 0000000..c760313
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-6.png
Binary files differ
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
new file mode 100644
index 0000000..6a557a0
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/basic/doc-files/BasicGraphicsUtils-7.png
Binary files differ
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
new file mode 100644
index 0000000..02bfbbe
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/doc-files/ComponentUI-1.dia
Binary files differ
diff --git a/libjava/classpath/javax/swing/plaf/doc-files/ComponentUI-1.png b/libjava/classpath/javax/swing/plaf/doc-files/ComponentUI-1.png
new file mode 100644
index 0000000..def4cbc
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/doc-files/ComponentUI-1.png
Binary files differ
diff --git a/libjava/classpath/javax/swing/plaf/doc-files/TreeUI-1.png b/libjava/classpath/javax/swing/plaf/doc-files/TreeUI-1.png
new file mode 100644
index 0000000..0f01ab0
--- /dev/null
+++ b/libjava/classpath/javax/swing/plaf/doc-files/TreeUI-1.png
Binary files differ
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 &amp; Feel.
+ *
+ * @return a border for Swing buttons in the Metal Look &amp; 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 &amp; Feel.
+ *
+ * @return a border for Toolbar buttons in the Metal Look &amp; 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 &amp; 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 &amp; Feel defaults for Buttons.
+ *
+ * @param button the button for which to install the Look &amp; 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 &amp; 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 &amp; 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 &amp; 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>