diff options
author | Mark Wielaard <mark@gcc.gnu.org> | 2005-11-15 23:20:01 +0000 |
---|---|---|
committer | Mark Wielaard <mark@gcc.gnu.org> | 2005-11-15 23:20:01 +0000 |
commit | 8f523f3a1047919d3563daf1ef47ba87336ebe89 (patch) | |
tree | a5eb7cf42a51869cc8aa1fad7ad6a90cca47fdd8 /libjava/classpath/javax/swing/plaf | |
parent | 02e549bfaaec38f68307e7f34e46ea57ea1809af (diff) | |
download | gcc-8f523f3a1047919d3563daf1ef47ba87336ebe89.zip gcc-8f523f3a1047919d3563daf1ef47ba87336ebe89.tar.gz gcc-8f523f3a1047919d3563daf1ef47ba87336ebe89.tar.bz2 |
Imported GNU Classpath 0.19 + gcj-import-20051115.
* sources.am: Regenerated.
* Makefile.in: Likewise.
* scripts/makemake.tcl: Use glob -nocomplain.
From-SVN: r107049
Diffstat (limited to 'libjava/classpath/javax/swing/plaf')
129 files changed, 13097 insertions, 5184 deletions
diff --git a/libjava/classpath/javax/swing/plaf/ActionMapUIResource.java b/libjava/classpath/javax/swing/plaf/ActionMapUIResource.java index f6af088..07292fe 100644 --- a/libjava/classpath/javax/swing/plaf/ActionMapUIResource.java +++ b/libjava/classpath/javax/swing/plaf/ActionMapUIResource.java @@ -50,9 +50,7 @@ import javax.swing.ActionMap; * @author Andrew Selkirk * @author Sascha Brawer (brawer@dandelis.ch) */ -public class ActionMapUIResource - extends ActionMap - implements UIResource +public class ActionMapUIResource extends ActionMap implements UIResource { /** * Constructs a new ActionMapUIResource. diff --git a/libjava/classpath/javax/swing/plaf/BorderUIResource.java b/libjava/classpath/javax/swing/plaf/BorderUIResource.java index 4402bbb..317cb09 100644 --- a/libjava/classpath/javax/swing/plaf/BorderUIResource.java +++ b/libjava/classpath/javax/swing/plaf/BorderUIResource.java @@ -71,9 +71,7 @@ import javax.swing.border.TitledBorder; * @author Brian Jones (cbj@gnu.org) * @author Sascha Brawer (brawer@dandelis.ch) */ -public class BorderUIResource - extends Object - implements Border, UIResource, Serializable +public class BorderUIResource implements Border, UIResource, Serializable { /** * Verified using the <code>serialver</code> tool diff --git a/libjava/classpath/javax/swing/plaf/ButtonUI.java b/libjava/classpath/javax/swing/plaf/ButtonUI.java index 197299e..6910e42 100644 --- a/libjava/classpath/javax/swing/plaf/ButtonUI.java +++ b/libjava/classpath/javax/swing/plaf/ButtonUI.java @@ -46,7 +46,7 @@ package javax.swing.plaf; * * @author Sascha Brawer (brawer@dandelis.ch) */ -public abstract class ButtonUI - extends ComponentUI +public abstract class ButtonUI extends ComponentUI { + // This abstract class does not define any methods of its own. } diff --git a/libjava/classpath/javax/swing/plaf/ColorChooserUI.java b/libjava/classpath/javax/swing/plaf/ColorChooserUI.java index 68ffd91..1609141 100644 --- a/libjava/classpath/javax/swing/plaf/ColorChooserUI.java +++ b/libjava/classpath/javax/swing/plaf/ColorChooserUI.java @@ -46,8 +46,7 @@ package javax.swing.plaf; * @author Andrew Selkirk * @author Sascha Brawer (brawer@dandelis.ch) */ -public abstract class ColorChooserUI - extends ComponentUI +public abstract class ColorChooserUI extends ComponentUI { /** * Constructs a ColorChooserUI. diff --git a/libjava/classpath/javax/swing/plaf/ColorUIResource.java b/libjava/classpath/javax/swing/plaf/ColorUIResource.java index 33b1676..36e10f2 100644 --- a/libjava/classpath/javax/swing/plaf/ColorUIResource.java +++ b/libjava/classpath/javax/swing/plaf/ColorUIResource.java @@ -50,9 +50,7 @@ import java.awt.Color; * * @author Sascha Brawer (brawer@dandelis.ch) */ -public class ColorUIResource - extends Color - implements UIResource +public class ColorUIResource extends Color implements UIResource { /** * Constructs a <code>ColorUIResource</code> using the specified diff --git a/libjava/classpath/javax/swing/plaf/ComboBoxUI.java b/libjava/classpath/javax/swing/plaf/ComboBoxUI.java index 9498a48..3e81ed7 100644 --- a/libjava/classpath/javax/swing/plaf/ComboBoxUI.java +++ b/libjava/classpath/javax/swing/plaf/ComboBoxUI.java @@ -48,14 +48,14 @@ import javax.swing.JComboBox; * @author Andrew Selkirk * @author Sascha Brawer (brawer@dandelis.ch) */ -public abstract class ComboBoxUI - extends ComponentUI +public abstract class ComboBoxUI extends ComponentUI { /** * Constructs a new <code>ComboBoxUI</code>. */ public ComboBoxUI() { + // Nothing to do here. } diff --git a/libjava/classpath/javax/swing/plaf/ComponentInputMapUIResource.java b/libjava/classpath/javax/swing/plaf/ComponentInputMapUIResource.java index e141871..cfc43e4 100644 --- a/libjava/classpath/javax/swing/plaf/ComponentInputMapUIResource.java +++ b/libjava/classpath/javax/swing/plaf/ComponentInputMapUIResource.java @@ -52,8 +52,7 @@ import javax.swing.JComponent; * @author Andrew Selkirk * @author Sascha Brawer (brawer@dandelis.ch) */ -public class ComponentInputMapUIResource - extends ComponentInputMap +public class ComponentInputMapUIResource extends ComponentInputMap implements UIResource { /** diff --git a/libjava/classpath/javax/swing/plaf/ComponentUI.java b/libjava/classpath/javax/swing/plaf/ComponentUI.java index 0e76805..6a736f2 100644 --- a/libjava/classpath/javax/swing/plaf/ComponentUI.java +++ b/libjava/classpath/javax/swing/plaf/ComponentUI.java @@ -38,8 +38,10 @@ exception statement from your version. */ package javax.swing.plaf; +import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; +import java.awt.Rectangle; import javax.accessibility.Accessible; import javax.swing.JComponent; @@ -86,6 +88,7 @@ public abstract class ComponentUI */ public ComponentUI() { + // Nothing to do here. } @@ -157,6 +160,8 @@ public abstract class ComponentUI */ public void paint(Graphics g, JComponent c) { + // Nothing is done here. This method is meant to be overridden by + // subclasses. } @@ -181,13 +186,14 @@ public abstract class ComponentUI { if (c.isOpaque()) { + Color oldColor = g.getColor(); g.setColor(c.getBackground()); g.fillRect(0, 0, c.getWidth(), c.getHeight()); + g.setColor(oldColor); } paint(g, c); } - - + /** * Determines the preferred size of a component. The default * implementation returns <code>null</code>, which means that diff --git a/libjava/classpath/javax/swing/plaf/DesktopIconUI.java b/libjava/classpath/javax/swing/plaf/DesktopIconUI.java index 2e44088..676233e 100644 --- a/libjava/classpath/javax/swing/plaf/DesktopIconUI.java +++ b/libjava/classpath/javax/swing/plaf/DesktopIconUI.java @@ -44,13 +44,13 @@ package javax.swing.plaf; * @author Andrew Selkirk (aselkirk@sympatico.ca) * @author Sascha Brawer (brawer@dandelis.ch) */ -public abstract class DesktopIconUI - extends ComponentUI +public abstract class DesktopIconUI extends ComponentUI { /** * Constructs a new <code>DesktopIconUI</code>. */ public DesktopIconUI() { + // Nothing to do here. } } diff --git a/libjava/classpath/javax/swing/plaf/DesktopPaneUI.java b/libjava/classpath/javax/swing/plaf/DesktopPaneUI.java index de553ea..3d4cfc8 100644 --- a/libjava/classpath/javax/swing/plaf/DesktopPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/DesktopPaneUI.java @@ -46,14 +46,13 @@ package javax.swing.plaf; * @author Andrew Selkirk (aselkirk@sympatico.ca) * @author Sascha Brawer (brawer@dandelis.ch) */ -public abstract class DesktopPaneUI - extends ComponentUI +public abstract class DesktopPaneUI extends ComponentUI { /** * Constructs a new <code>DesktopPaneUI</code>. */ public DesktopPaneUI() { + // Nothing to do here. } } - diff --git a/libjava/classpath/javax/swing/plaf/DimensionUIResource.java b/libjava/classpath/javax/swing/plaf/DimensionUIResource.java index 63c6838..618c220 100644 --- a/libjava/classpath/javax/swing/plaf/DimensionUIResource.java +++ b/libjava/classpath/javax/swing/plaf/DimensionUIResource.java @@ -51,9 +51,7 @@ import java.awt.Dimension; * @author Andrew Selkirk (aselkirk@sympatico.ca) * @author Sascha Brawer (brawer@dandelis.ch) */ -public class DimensionUIResource - extends Dimension - implements UIResource +public class DimensionUIResource extends Dimension implements UIResource { /** * Constructs a new DimensionUIResource, given its width and height. diff --git a/libjava/classpath/javax/swing/plaf/FileChooserUI.java b/libjava/classpath/javax/swing/plaf/FileChooserUI.java index 8b661e3..e9be8f2 100644 --- a/libjava/classpath/javax/swing/plaf/FileChooserUI.java +++ b/libjava/classpath/javax/swing/plaf/FileChooserUI.java @@ -53,14 +53,14 @@ import javax.swing.filechooser.FileView; * @author Andrew Selkirk (aselkirk@sympatico.ca) * @author Sascha Brawer (brawer@dandelis.ch) */ -public abstract class FileChooserUI - extends ComponentUI +public abstract class FileChooserUI extends ComponentUI { /** * Constructs a new <code>FileChooserUI</code>. */ public FileChooserUI() { + // Nothing to do here. } diff --git a/libjava/classpath/javax/swing/plaf/FontUIResource.java b/libjava/classpath/javax/swing/plaf/FontUIResource.java index 1c17310..c54f987 100644 --- a/libjava/classpath/javax/swing/plaf/FontUIResource.java +++ b/libjava/classpath/javax/swing/plaf/FontUIResource.java @@ -50,9 +50,7 @@ import java.awt.Font; * @author Andrew Selkirk (aselkirk@sympatico.ca) * @author Sascha Brawer (brawer@dandelis.ch) */ -public class FontUIResource - extends Font - implements UIResource +public class FontUIResource extends Font implements UIResource { /** * Constructs a new <code>FontUIResource</code> given diff --git a/libjava/classpath/javax/swing/plaf/IconUIResource.java b/libjava/classpath/javax/swing/plaf/IconUIResource.java index 1b09ed3..659c8e7 100644 --- a/libjava/classpath/javax/swing/plaf/IconUIResource.java +++ b/libjava/classpath/javax/swing/plaf/IconUIResource.java @@ -53,8 +53,7 @@ import javax.swing.Icon; * @author Andrew Selkirk (aselkirk@sympatico.ca) * @author Sascha Brawer (brawer@dandelis.ch) */ -public class IconUIResource - implements Icon, UIResource, Serializable +public class IconUIResource implements Icon, UIResource, Serializable { /** * Verified using the <code>serialver</code> tool of Sun JDK 1.4.1_01 diff --git a/libjava/classpath/javax/swing/plaf/InputMapUIResource.java b/libjava/classpath/javax/swing/plaf/InputMapUIResource.java index ae032e5..0c5f6f9 100644 --- a/libjava/classpath/javax/swing/plaf/InputMapUIResource.java +++ b/libjava/classpath/javax/swing/plaf/InputMapUIResource.java @@ -49,15 +49,13 @@ import javax.swing.InputMap; * @author Andrew Selkirk (aselkirk@sympatico.ca) * @author Sascha Brawer (brawer@dandelis.ch) */ -public class InputMapUIResource - extends InputMap - implements UIResource +public class InputMapUIResource extends InputMap implements UIResource { /** * Constructs a new <code>InputMapUIResource</code>. */ public InputMapUIResource() { + // Nothing to do here. } } - diff --git a/libjava/classpath/javax/swing/plaf/InsetsUIResource.java b/libjava/classpath/javax/swing/plaf/InsetsUIResource.java index 755d8ad..d64feb4 100644 --- a/libjava/classpath/javax/swing/plaf/InsetsUIResource.java +++ b/libjava/classpath/javax/swing/plaf/InsetsUIResource.java @@ -50,8 +50,7 @@ import java.io.Serializable; * @author Andrew Selkirk (aselkirk@sympatico.ca) * @author Sascha Brawer (brawer@dandelis.ch) */ -public class InsetsUIResource - extends Insets +public class InsetsUIResource extends Insets implements Cloneable, UIResource, Serializable { /** diff --git a/libjava/classpath/javax/swing/plaf/InternalFrameUI.java b/libjava/classpath/javax/swing/plaf/InternalFrameUI.java index fd1e337..0b2f77c 100644 --- a/libjava/classpath/javax/swing/plaf/InternalFrameUI.java +++ b/libjava/classpath/javax/swing/plaf/InternalFrameUI.java @@ -47,13 +47,13 @@ package javax.swing.plaf; * @author Andrew Selkirk (aselkirk@sympatico.ca) * @author Sascha Brawer (brawer@dandelis.ch) */ -public abstract class InternalFrameUI - extends ComponentUI +public abstract class InternalFrameUI extends ComponentUI { /** * Constructs a new <code>InternalFrameUI</code>. */ public InternalFrameUI() { + // Nothing to do here. } } diff --git a/libjava/classpath/javax/swing/plaf/LabelUI.java b/libjava/classpath/javax/swing/plaf/LabelUI.java index 8fc1d71..f4b74d5 100644 --- a/libjava/classpath/javax/swing/plaf/LabelUI.java +++ b/libjava/classpath/javax/swing/plaf/LabelUI.java @@ -47,13 +47,13 @@ package javax.swing.plaf; * @author Andrew Selkirk (aselkirk@sympatico.ca) * @author Sascha Brawer (brawer@dandelis.ch) */ -public abstract class LabelUI - extends ComponentUI +public abstract class LabelUI extends ComponentUI { /** * Constructs a new <code>LabelUI</code>. */ public LabelUI() { + // Nothing to do here. } } diff --git a/libjava/classpath/javax/swing/plaf/ListUI.java b/libjava/classpath/javax/swing/plaf/ListUI.java index 66d5cf5..bdfe4b3 100644 --- a/libjava/classpath/javax/swing/plaf/ListUI.java +++ b/libjava/classpath/javax/swing/plaf/ListUI.java @@ -49,14 +49,14 @@ import javax.swing.JList; * * @author Sascha Brawer (brawer@dandelis.ch) */ -public abstract class ListUI - extends ComponentUI +public abstract class ListUI extends ComponentUI { /** * Constructs a new <code>ListUI</code>. */ public ListUI() { + // Nothing to do here. } diff --git a/libjava/classpath/javax/swing/plaf/MenuBarUI.java b/libjava/classpath/javax/swing/plaf/MenuBarUI.java index 8835571..2c82adf 100644 --- a/libjava/classpath/javax/swing/plaf/MenuBarUI.java +++ b/libjava/classpath/javax/swing/plaf/MenuBarUI.java @@ -47,13 +47,13 @@ package javax.swing.plaf; * @author Andrew Selkirk (aselkirk@sympatico.ca) * @author Sascha Brawer (brawer@dandelis.ch) */ -public abstract class MenuBarUI - extends ComponentUI +public abstract class MenuBarUI extends ComponentUI { /** * Constructs a new <code>MenuBarUI</code>. */ public MenuBarUI() { + // Nothing to do here. } } diff --git a/libjava/classpath/javax/swing/plaf/MenuItemUI.java b/libjava/classpath/javax/swing/plaf/MenuItemUI.java index 31d7319..83ad52f 100644 --- a/libjava/classpath/javax/swing/plaf/MenuItemUI.java +++ b/libjava/classpath/javax/swing/plaf/MenuItemUI.java @@ -47,13 +47,13 @@ package javax.swing.plaf; * @author Andrew Selkirk (aselkirk@sympatico.ca) * @author Sascha Brawer (brawer@dandelis.ch) */ -public abstract class MenuItemUI - extends ButtonUI +public abstract class MenuItemUI extends ButtonUI { /** * Constructs a new <code>MenuItemUI</code>. */ public MenuItemUI() { + // Nothing to do here. } } diff --git a/libjava/classpath/javax/swing/plaf/PanelUI.java b/libjava/classpath/javax/swing/plaf/PanelUI.java index b1171b8..12a6f52 100644 --- a/libjava/classpath/javax/swing/plaf/PanelUI.java +++ b/libjava/classpath/javax/swing/plaf/PanelUI.java @@ -46,13 +46,13 @@ package javax.swing.plaf; * * @author Sascha Brawer (brawer@dandelis.ch) */ -public abstract class PanelUI - extends ComponentUI +public abstract class PanelUI extends ComponentUI { /** * Constructs a new <code>PanelUI</code>. */ public PanelUI() { + // Nothing to do here. } } diff --git a/libjava/classpath/javax/swing/plaf/PopupMenuUI.java b/libjava/classpath/javax/swing/plaf/PopupMenuUI.java index c70ad2a..de351f2 100644 --- a/libjava/classpath/javax/swing/plaf/PopupMenuUI.java +++ b/libjava/classpath/javax/swing/plaf/PopupMenuUI.java @@ -53,14 +53,14 @@ import javax.swing.PopupFactory; * @author Andrew Selkirk (aselkirk@sympatico.ca) * @author Sascha Brawer (brawer@dandelis.ch) */ -public abstract class PopupMenuUI - extends ComponentUI +public abstract class PopupMenuUI extends ComponentUI { /** * Constructs a new <code>PopupMenuUI</code>. */ public PopupMenuUI() { + // Nothing to do here. } diff --git a/libjava/classpath/javax/swing/plaf/ProgressBarUI.java b/libjava/classpath/javax/swing/plaf/ProgressBarUI.java index 79c1b95..013b8c5 100644 --- a/libjava/classpath/javax/swing/plaf/ProgressBarUI.java +++ b/libjava/classpath/javax/swing/plaf/ProgressBarUI.java @@ -47,13 +47,13 @@ package javax.swing.plaf; * @author Andrew Selkirk (aselkirk@sympatico.ca) * @author Sascha Brawer (brawer@dandelis.ch) */ -public abstract class ProgressBarUI - extends ComponentUI +public abstract class ProgressBarUI extends ComponentUI { /** * Constructs a new <code>ProgressBarUI</code>. */ public ProgressBarUI() { + // Nothing to do here. } } diff --git a/libjava/classpath/javax/swing/plaf/RootPaneUI.java b/libjava/classpath/javax/swing/plaf/RootPaneUI.java index ff7d0a6..9637c9c 100644 --- a/libjava/classpath/javax/swing/plaf/RootPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/RootPaneUI.java @@ -46,13 +46,13 @@ package javax.swing.plaf; * @author Andrew Selkirk (aselkirk@sympatico.ca) * @author Sascha Brawer (brawer@dandelis.ch) */ -public abstract class RootPaneUI - extends ComponentUI +public abstract class RootPaneUI extends ComponentUI { /** * Constructs a new <code>RootPaneUI</code>. */ public RootPaneUI() { + // Nothing to do here. } } diff --git a/libjava/classpath/javax/swing/plaf/ScrollBarUI.java b/libjava/classpath/javax/swing/plaf/ScrollBarUI.java index 3cad393..51b4bf2 100644 --- a/libjava/classpath/javax/swing/plaf/ScrollBarUI.java +++ b/libjava/classpath/javax/swing/plaf/ScrollBarUI.java @@ -46,13 +46,13 @@ package javax.swing.plaf; * @author Andrew Selkirk (aselkirk@sympatico.ca) * @author Sascha Brawer (brawer@dandelis.ch) */ -public abstract class ScrollBarUI - extends ComponentUI +public abstract class ScrollBarUI extends ComponentUI { /** * Constructs a new <code>ScrollBarUI</code>. */ public ScrollBarUI() { + // Nothing to do here. } } diff --git a/libjava/classpath/javax/swing/plaf/ScrollPaneUI.java b/libjava/classpath/javax/swing/plaf/ScrollPaneUI.java index 14d2ac6..8b37fed 100644 --- a/libjava/classpath/javax/swing/plaf/ScrollPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/ScrollPaneUI.java @@ -47,13 +47,13 @@ package javax.swing.plaf; * @author Andrew Selkirk (aselkirk@sympatico.ca) * @author Sascha Brawer (brawer@dandelis.ch) */ -public abstract class ScrollPaneUI - extends ComponentUI +public abstract class ScrollPaneUI extends ComponentUI { /** * Constructs a new <code>ScrollPaneUI</code>. */ public ScrollPaneUI() { + // Nothing to do here. } } diff --git a/libjava/classpath/javax/swing/plaf/SeparatorUI.java b/libjava/classpath/javax/swing/plaf/SeparatorUI.java index 6855bd0..8a9f8cf 100644 --- a/libjava/classpath/javax/swing/plaf/SeparatorUI.java +++ b/libjava/classpath/javax/swing/plaf/SeparatorUI.java @@ -54,5 +54,6 @@ public abstract class SeparatorUI */ public SeparatorUI() { + // Nothing to do here. } } diff --git a/libjava/classpath/javax/swing/plaf/SliderUI.java b/libjava/classpath/javax/swing/plaf/SliderUI.java index 775f196..570e962 100644 --- a/libjava/classpath/javax/swing/plaf/SliderUI.java +++ b/libjava/classpath/javax/swing/plaf/SliderUI.java @@ -47,13 +47,13 @@ package javax.swing.plaf; * @author Andrew Selkirk (aselkirk@sympatico.ca) * @author Sascha Brawer (brawer@dandelis.ch) */ -public abstract class SliderUI - extends ComponentUI +public abstract class SliderUI extends ComponentUI { /** * Constructs a new <code>SliderUI</code>. */ public SliderUI() { + // Nothing to do here. } } diff --git a/libjava/classpath/javax/swing/plaf/SpinnerUI.java b/libjava/classpath/javax/swing/plaf/SpinnerUI.java index fb4a3b1..ca29ddb 100644 --- a/libjava/classpath/javax/swing/plaf/SpinnerUI.java +++ b/libjava/classpath/javax/swing/plaf/SpinnerUI.java @@ -47,13 +47,13 @@ package javax.swing.plaf; * * @author Sascha Brawer (brawer@dandelis.ch) */ -public abstract class SpinnerUI - extends ComponentUI +public abstract class SpinnerUI extends ComponentUI { /** * Constructs a new <code>SpinnerUI</code>. */ public SpinnerUI() { + // Nothing to do here. } } diff --git a/libjava/classpath/javax/swing/plaf/SplitPaneUI.java b/libjava/classpath/javax/swing/plaf/SplitPaneUI.java index ea9af2b..59ededf 100644 --- a/libjava/classpath/javax/swing/plaf/SplitPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/SplitPaneUI.java @@ -51,14 +51,14 @@ import javax.swing.JSplitPane; * @author Andrew Selkirk (aselkirk@sympatico.ca) * @author Sascha Brawer (brawer@dandelis.ch) */ -public abstract class SplitPaneUI - extends ComponentUI +public abstract class SplitPaneUI extends ComponentUI { /** * Constructs a new <code>SplitPaneUI</code>. */ public SplitPaneUI() { + // Nothing to do here. } diff --git a/libjava/classpath/javax/swing/plaf/TabbedPaneUI.java b/libjava/classpath/javax/swing/plaf/TabbedPaneUI.java index 6ab823b..01a7720 100644 --- a/libjava/classpath/javax/swing/plaf/TabbedPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/TabbedPaneUI.java @@ -51,14 +51,14 @@ import javax.swing.JTabbedPane; * @author Andrew Selkirk (aselkirk@sympatico.ca) * @author Sascha Brawer (brawer@dandelis.ch) */ -public abstract class TabbedPaneUI - extends ComponentUI +public abstract class TabbedPaneUI extends ComponentUI { /** * Constructs a new <code>TabbedPaneUI</code>. */ public TabbedPaneUI() { + // Nothing to do here. } diff --git a/libjava/classpath/javax/swing/plaf/TableHeaderUI.java b/libjava/classpath/javax/swing/plaf/TableHeaderUI.java index f23ca74..34ac0e0 100644 --- a/libjava/classpath/javax/swing/plaf/TableHeaderUI.java +++ b/libjava/classpath/javax/swing/plaf/TableHeaderUI.java @@ -47,13 +47,13 @@ package javax.swing.plaf; * @author Andrew Selkirk (aselkirk@sympatico.ca) * @author Sascha Brawer (brawer@dandelis.ch) */ -public abstract class TableHeaderUI - extends ComponentUI +public abstract class TableHeaderUI extends ComponentUI { /** * Constructs a new <code>TableHeaderUI</code>. */ public TableHeaderUI() { + // Nothing to do here. } } diff --git a/libjava/classpath/javax/swing/plaf/TableUI.java b/libjava/classpath/javax/swing/plaf/TableUI.java index e56bcd1..a8c6bf9 100644 --- a/libjava/classpath/javax/swing/plaf/TableUI.java +++ b/libjava/classpath/javax/swing/plaf/TableUI.java @@ -47,13 +47,13 @@ package javax.swing.plaf; * @author Andrew Selkirk (aselkirk@sympatico.ca) * @author Sascha Brawer (brawer@dandelis.ch) */ -public abstract class TableUI - extends ComponentUI +public abstract class TableUI extends ComponentUI { /** * Constructs a new <code>TableUI</code>. */ public TableUI() { + // Nothing to do here. } } diff --git a/libjava/classpath/javax/swing/plaf/TextUI.java b/libjava/classpath/javax/swing/plaf/TextUI.java index dcabdfc..9f2737c 100644 --- a/libjava/classpath/javax/swing/plaf/TextUI.java +++ b/libjava/classpath/javax/swing/plaf/TextUI.java @@ -57,14 +57,14 @@ import javax.swing.text.View; * @author Ronald Veldema (rveldema@cs.vu.nl) * @author Sascha Brawer (brawer@dandelis.ch) */ -public abstract class TextUI - extends ComponentUI +public abstract class TextUI extends ComponentUI { /** * Constructs a new <code>TextUI</code>. */ public TextUI() { + // Nothing to do here. } diff --git a/libjava/classpath/javax/swing/plaf/ToolBarUI.java b/libjava/classpath/javax/swing/plaf/ToolBarUI.java index 730cf488..9a26e7b 100644 --- a/libjava/classpath/javax/swing/plaf/ToolBarUI.java +++ b/libjava/classpath/javax/swing/plaf/ToolBarUI.java @@ -47,13 +47,13 @@ package javax.swing.plaf; * @author Andrew Selkirk (aselkirk@sympatico.ca) * @author Sascha Brawer (brawer@dandelis.ch) */ -public abstract class ToolBarUI - extends ComponentUI +public abstract class ToolBarUI extends ComponentUI { /** * Constructs a new <code>ToolBarUI</code>. */ public ToolBarUI() { + // Nothing to do here. } } diff --git a/libjava/classpath/javax/swing/plaf/ToolTipUI.java b/libjava/classpath/javax/swing/plaf/ToolTipUI.java index 4383d0e..ae2d465 100644 --- a/libjava/classpath/javax/swing/plaf/ToolTipUI.java +++ b/libjava/classpath/javax/swing/plaf/ToolTipUI.java @@ -47,13 +47,13 @@ package javax.swing.plaf; * @author Andrew Selkirk (aselkirk@sympatico.ca) * @author Sascha Brawer (brawer@dandelis.ch) */ -public abstract class ToolTipUI - extends ComponentUI +public abstract class ToolTipUI extends ComponentUI { /** * Constructs a new <code>ToolTipUI</code>. */ public ToolTipUI() { + // Nothing to do here. } } diff --git a/libjava/classpath/javax/swing/plaf/TreeUI.java b/libjava/classpath/javax/swing/plaf/TreeUI.java index e32952d..308ec63 100644 --- a/libjava/classpath/javax/swing/plaf/TreeUI.java +++ b/libjava/classpath/javax/swing/plaf/TreeUI.java @@ -51,14 +51,14 @@ import javax.swing.tree.TreePath; * * @author Sascha Brawer (brawer@dandelis.ch) */ -public abstract class TreeUI - extends ComponentUI +public abstract class TreeUI extends ComponentUI { /** * Constructs a new <code>TreeUI</code>. */ public TreeUI() { + // Nothing to do here. } diff --git a/libjava/classpath/javax/swing/plaf/UIResource.java b/libjava/classpath/javax/swing/plaf/UIResource.java index 59edf56..fe398fe 100644 --- a/libjava/classpath/javax/swing/plaf/UIResource.java +++ b/libjava/classpath/javax/swing/plaf/UIResource.java @@ -50,6 +50,10 @@ package javax.swing.plaf; * they are initialized or set to <code>null</code>. * * @author Brian Jones + * * @see ComponentUI */ -public interface UIResource { } +public interface UIResource +{ + // This is a marker interface and declares no methods. +} diff --git a/libjava/classpath/javax/swing/plaf/ViewportUI.java b/libjava/classpath/javax/swing/plaf/ViewportUI.java index 087938f..db514de 100644 --- a/libjava/classpath/javax/swing/plaf/ViewportUI.java +++ b/libjava/classpath/javax/swing/plaf/ViewportUI.java @@ -48,13 +48,13 @@ package javax.swing.plaf; * @author Andrew Selkirk (aselkirk@sympatico.ca) * @author Sascha Brawer (brawer@dandelis.ch) */ -public abstract class ViewportUI - extends ComponentUI +public abstract class ViewportUI extends ComponentUI { /** * Constructs a new <code>ViewportUI</code>. */ public ViewportUI() { + // Nothing to do here. } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicArrowButton.java b/libjava/classpath/javax/swing/plaf/basic/BasicArrowButton.java index 836ef22..69d4415 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicArrowButton.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicArrowButton.java @@ -39,42 +39,30 @@ 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.ButtonModel; 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. + * A button that displays an arrow (triangle) that points {@link #NORTH}, + * {@link #SOUTH}, {@link #EAST} or {@link #WEST}. This button is used by + * the {@link BasicComboBoxUI} class. + * + * @see BasicComboBoxUI#createArrowButton */ public class BasicArrowButton extends JButton implements SwingConstants { - /** The default size of the Arrow buttons. */ - private static int defaultSize = 12; - /** 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. */ + /** + * The direction that the arrow points. + * + * @see #getDirection() + */ protected int direction; /** @@ -89,7 +77,7 @@ public class BasicArrowButton extends JButton implements SwingConstants * edges of the button. * This is package-private to avoid an accessor method. */ - transient Color darkShadow = Color.DARK_GRAY; + transient Color darkShadow = new Color(102, 102, 102); /** * The top and left edges of the button. @@ -97,51 +85,15 @@ public class BasicArrowButton extends JButton implements SwingConstants */ 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. + * Creates a new <code>BasicArrowButton</code> object. * - * @param direction The direction the arrow points in. + * @param direction The direction the arrow points in (one of: + * {@link #NORTH}, {@link #SOUTH}, {@link #EAST} and {@link #WEST}). */ public BasicArrowButton(int direction) { super(); - setBorder(buttonBorder); setDirection(direction); } @@ -149,7 +101,8 @@ public class BasicArrowButton extends JButton implements SwingConstants * Creates a new BasicArrowButton object with the given colors and * direction. * - * @param direction The direction to point in. + * @param direction The direction to point in (one of: + * {@link #NORTH}, {@link #SOUTH}, {@link #EAST} and {@link #WEST}). * @param background The background color. * @param shadow The shadow color. * @param darkShadow The dark shadow color. @@ -166,9 +119,10 @@ public class BasicArrowButton extends JButton implements SwingConstants } /** - * This method returns whether the focus can traverse to this component. + * Returns whether the focus can traverse to this component. This method + * always returns <code>false</code>. * - * @return Whether the focus can traverse to this component. + * @return <code>false</code>. */ public boolean isFocusTraversable() { @@ -176,7 +130,8 @@ public class BasicArrowButton extends JButton implements SwingConstants } /** - * This method returns the direction of the arrow. + * Returns the direction of the arrow (one of: {@link #NORTH}, + * {@link #SOUTH}, {@link #EAST} and {@link #WEST}). * * @return The direction of the arrow. */ @@ -186,9 +141,10 @@ public class BasicArrowButton extends JButton implements SwingConstants } /** - * This method changes the direction of the arrow. + * Sets the direction of the arrow. * - * @param dir The new direction of the arrow. + * @param dir The new direction of the arrow (one of: {@link #NORTH}, + * {@link #SOUTH}, {@link #EAST} and {@link #WEST}). */ public void setDirection(int dir) { @@ -196,7 +152,7 @@ public class BasicArrowButton extends JButton implements SwingConstants } /** - * This method paints the arrow button. The painting is delegated to the + * Paints the arrow button. The painting is delegated to the * paintTriangle method. * * @param g The Graphics object to paint with. @@ -204,147 +160,257 @@ public class BasicArrowButton extends JButton implements SwingConstants 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()); + int size = bounds.height / 4; + int x = (bounds.width - size) / 2; + int y = (bounds.height - size) / 2; + ButtonModel m = getModel(); + if (m.isArmed()) + { + x++; + y++; + } + paintTriangle(g, x, y, size, direction, isEnabled()); } + /** The preferred size for the button. */ + private static final Dimension PREFERRED_SIZE = new Dimension(16, 16); + + /** The minimum size for the button. */ + private static final Dimension MINIMUM_SIZE = new Dimension(5, 5); + + /** The maximum size for the button. */ + private static final Dimension MAXIMUM_SIZE + = new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); + /** - * This method returns the preferred size of the arrow button. + * Returns the preferred size of the arrow button. * - * @return The preferred size. + * @return The preferred size (always 16 x 16). */ 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); + return PREFERRED_SIZE; } /** - * This method returns the minimum size of the arrow button. + * Returns the minimum size of the arrow button. * - * @return The minimum size. + * @return The minimum size (always 5 x 5). */ public Dimension getMinimumSize() { - return getPreferredSize(); + return MINIMUM_SIZE; } /** - * This method returns the maximum size of the arrow button. + * Returns the maximum size of the arrow button. * * @return The maximum size. */ public Dimension getMaximumSize() { - return getPreferredSize(); + return MAXIMUM_SIZE; } /** - * The method paints a triangle with the given size and direction at the - * given x and y coordinates. + * Paints a triangle with the given size, location and direction. It is + * difficult to explain the rationale behind the positioning of the triangle + * relative to the given (x, y) position - by trial and error we seem to + * match the behaviour of the reference implementation (which is missing a + * specification for this method). * - * @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. + * @param g the graphics device. + * @param x the x-coordinate for the triangle's location. + * @param y the y-coordinate for the triangle's location. + * @param size the arrow size (depth). + * @param direction the direction of the arrow (one of: {@link #NORTH}, + * {@link #SOUTH}, {@link #EAST} and {@link #WEST}). + * @param isEnabled if <code>true</code> the arrow is drawn in the enabled + * state, otherwise it is drawn in the disabled state. */ 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); - + Color savedColor = g.getColor(); switch (direction) { case NORTH: - x1 = xPoints[0] + 2; - y1 = yPoints[0]; - y2 = y1; - x2 = xPoints[2] - 1; - break; + paintTriangleNorth(g, x, y, size, isEnabled); + break; case SOUTH: - x1 = xPoints[1]; - y1 = yPoints[1] + 1; - x2 = xPoints[2] - 1; - y2 = yPoints[2]; - break; + paintTriangleSouth(g, x, y, size, isEnabled); + break; case LEFT: case WEST: - x1 = xPoints[0] + 1; - y1 = yPoints[0] + 1; - x2 = x1; - y2 = yPoints[2] + 1; - break; + paintTriangleWest(g, x, y, size, isEnabled); + break; case RIGHT: case EAST: - x1 = xPoints[2]; - y1 = yPoints[2] + 1; - x2 = xPoints[1] - 1; - y2 = yPoints[1] + 1; - break; + paintTriangleEast(g, x, y, size, isEnabled); + break; } - Color saved = g.getColor(); - + g.setColor(savedColor); + } + + /** + * Paints an upward-pointing triangle. This method is called by the + * {@link #paintTriangle(Graphics, int, int, int, int, boolean)} method. + * + * @param g the graphics device. + * @param x the x-coordinate for the anchor point. + * @param y the y-coordinate for the anchor point. + * @param size the arrow size (depth). + * @param isEnabled if <code>true</code> the arrow is drawn in the enabled + * state, otherwise it is drawn in the disabled state. + */ + private void paintTriangleNorth(Graphics g, int x, int y, int size, + boolean isEnabled) + { + int tipX = x + (size - 2) / 2; + int tipY = y; + int baseX1 = tipX - (size - 1); + int baseX2 = tipX + (size - 1); + int baseY = y + (size - 1); + Polygon triangle = new Polygon(); + triangle.addPoint(tipX, tipY); + triangle.addPoint(baseX1, baseY); + triangle.addPoint(baseX2, baseY); if (isEnabled) - { - g.setColor(Color.DARK_GRAY); - - if (arrow != null) - g.fillPolygon(xPoints, yPoints, 3); - } + { + g.setColor(Color.DARK_GRAY); + g.fillPolygon(triangle); + g.drawPolygon(triangle); + } 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); + { + g.setColor(Color.GRAY); + g.fillPolygon(triangle); + g.drawPolygon(triangle); + g.setColor(Color.WHITE); + g.drawLine(baseX1 + 1, baseY + 1, baseX2 + 1, baseY + 1); + } + } + + /** + * Paints an downward-pointing triangle. This method is called by the + * {@link #paintTriangle(Graphics, int, int, int, int, boolean)} method. + * + * @param g the graphics device. + * @param x the x-coordinate for the anchor point. + * @param y the y-coordinate for the anchor point. + * @param size the arrow size (depth). + * @param isEnabled if <code>true</code> the arrow is drawn in the enabled + * state, otherwise it is drawn in the disabled state. + */ + private void paintTriangleSouth(Graphics g, int x, int y, int size, + boolean isEnabled) + { + int tipX = x + (size - 2) / 2; + int tipY = y + (size - 1); + int baseX1 = tipX - (size - 1); + int baseX2 = tipX + (size - 1); + int baseY = y; + Polygon triangle = new Polygon(); + triangle.addPoint(tipX, tipY); + triangle.addPoint(baseX1, baseY); + triangle.addPoint(baseX2, baseY); + if (isEnabled) + { + g.setColor(Color.DARK_GRAY); + g.fillPolygon(triangle); + g.drawPolygon(triangle); + } + else + { + g.setColor(Color.GRAY); + g.fillPolygon(triangle); + g.drawPolygon(triangle); + g.setColor(Color.WHITE); + g.drawLine(tipX + 1, tipY, baseX2, baseY + 1); + g.drawLine(tipX + 1, tipY + 1, baseX2 + 1, baseY + 1); + } + } + + /** + * Paints a right-pointing triangle. This method is called by the + * {@link #paintTriangle(Graphics, int, int, int, int, boolean)} method. + * + * @param g the graphics device. + * @param x the x-coordinate for the anchor point. + * @param y the y-coordinate for the anchor point. + * @param size the arrow size (depth). + * @param isEnabled if <code>true</code> the arrow is drawn in the enabled + * state, otherwise it is drawn in the disabled state. + */ + private void paintTriangleEast(Graphics g, int x, int y, int size, + boolean isEnabled) + { + int tipX = x + (size - 1); + int tipY = y + (size - 2) / 2; + int baseX = x; + int baseY1 = tipY - (size - 1); + int baseY2 = tipY + (size - 1); + + Polygon triangle = new Polygon(); + triangle.addPoint(tipX, tipY); + triangle.addPoint(baseX, baseY1); + triangle.addPoint(baseX, baseY2); + if (isEnabled) + { + g.setColor(Color.DARK_GRAY); + g.fillPolygon(triangle); + g.drawPolygon(triangle); + } + else + { + g.setColor(Color.GRAY); + g.fillPolygon(triangle); + g.drawPolygon(triangle); + g.setColor(Color.WHITE); + g.drawLine(baseX + 1, baseY2, tipX, tipY + 1); + g.drawLine(baseX + 1, baseY2 + 1, tipX + 1, tipY + 1); + } + } + + /** + * Paints a left-pointing triangle. This method is called by the + * {@link #paintTriangle(Graphics, int, int, int, int, boolean)} method. + * + * @param g the graphics device. + * @param x the x-coordinate for the anchor point. + * @param y the y-coordinate for the anchor point. + * @param size the arrow size (depth). + * @param isEnabled if <code>true</code> the arrow is drawn in the enabled + * state, otherwise it is drawn in the disabled state. + */ + private void paintTriangleWest(Graphics g, int x, int y, int size, + boolean isEnabled) + { + int tipX = x; + int tipY = y + (size - 2) / 2; + int baseX = x + (size - 1); + int baseY1 = tipY - (size - 1); + int baseY2 = tipY + (size - 1); + + Polygon triangle = new Polygon(); + triangle.addPoint(tipX, tipY); + triangle.addPoint(baseX, baseY1); + triangle.addPoint(baseX, baseY2); + if (isEnabled) + { + g.setColor(Color.DARK_GRAY); + g.fillPolygon(triangle); + g.drawPolygon(triangle); + } + else + { + g.setColor(Color.GRAY); + g.fillPolygon(triangle); + g.drawPolygon(triangle); + g.setColor(Color.WHITE); + g.drawLine(baseX + 1, baseY1 + 1, baseX + 1, baseY2 + 1); + } } + } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicBorders.java b/libjava/classpath/javax/swing/plaf/basic/BasicBorders.java index e7d6e43..cec7bec 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicBorders.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicBorders.java @@ -806,9 +806,9 @@ public class BasicBorders */ public MarginBorder() { + // Nothing to do here. } - /** * Measures the width of this border. * @@ -1313,33 +1313,32 @@ public class BasicBorders * * @author Sascha Brawer (brawer@dandelis.ch) */ - public static class SplitPaneBorder - implements Border, UIResource + 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)}. + * by {@link #paintRect}. */ 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)}. + * by {@link #paintRect}. */ 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)}. + * by {@link #paintRect}. */ 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)}. + * by {@link #paintRect}. */ private static final int SUPPRESS_RIGHT = 8; diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicButtonListener.java b/libjava/classpath/javax/swing/plaf/basic/BasicButtonListener.java index 5349f52..1fca694 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicButtonListener.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicButtonListener.java @@ -55,9 +55,8 @@ import javax.swing.JComponent; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; -public class BasicButtonListener - implements MouseListener, MouseMotionListener, FocusListener, - ChangeListener, PropertyChangeListener +public class BasicButtonListener implements MouseListener, MouseMotionListener, + FocusListener, ChangeListener, PropertyChangeListener { public BasicButtonListener(AbstractButton b) { @@ -66,10 +65,12 @@ public class BasicButtonListener public void propertyChange(PropertyChangeEvent e) { + // TODO: What should be done here, if anything? } protected void checkOpacity(AbstractButton b) { + // TODO: What should be done here? } public void focusGained(FocusEvent e) @@ -129,18 +130,22 @@ public class BasicButtonListener public void stateChanged(ChangeEvent e) { + // TODO: What should be done here, if anything? } public void mouseMoved(MouseEvent e) { + // TODO: What should be done here, if anything? } public void mouseDragged(MouseEvent e) { + // TODO: What should be done here, if anything? } public void mouseClicked(MouseEvent e) { + // TODO: What should be done here, if anything? } /** diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicButtonUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicButtonUI.java index 6c80f14..2d3dbd3 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicButtonUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicButtonUI.java @@ -38,7 +38,6 @@ 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; @@ -49,13 +48,19 @@ import javax.swing.AbstractButton; import javax.swing.ButtonModel; import javax.swing.Icon; import javax.swing.InputMap; +import javax.swing.JButton; import javax.swing.JComponent; +import javax.swing.LookAndFeel; import javax.swing.SwingUtilities; import javax.swing.UIDefaults; import javax.swing.UIManager; import javax.swing.plaf.ButtonUI; import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.UIResource; +/** + * A UI delegate for the {@link JButton} component. + */ public class BasicButtonUI extends ButtonUI { /** @@ -72,13 +77,11 @@ public class BasicButtonUI extends ButtonUI 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 + * @param c The component. * * @return A new UI capable of drawing the component */ @@ -87,21 +90,46 @@ public class BasicButtonUI extends ButtonUI return new BasicButtonUI(); } + /** + * Returns the default gap between the button's text and icon (in pixels). + * + * @param b the button (ignored). + * + * @return The gap. + */ public int getDefaultTextIconGap(AbstractButton b) { return defaultTextIconGap; } + /** + * Sets the text shift offset to zero. + * + * @see #setTextShiftOffset() + */ protected void clearTextShiftOffset() { textShiftOffset = 0; } + /** + * Returns the text shift offset. + * + * @return The text shift offset. + * + * @see #clearTextShiftOffset() + * @see #setTextShiftOffset() + */ protected int getTextShiftOffset() { return textShiftOffset; } + /** + * Sets the text shift offset to the value in {@link #defaultTextShiftOffset}. + * + * @see #clearTextShiftOffset() + */ protected void setTextShiftOffset() { textShiftOffset = defaultTextShiftOffset; @@ -118,23 +146,33 @@ public class BasicButtonUI extends ButtonUI return "Button."; } + /** + * Installs the default settings. + * + * @param b the button (<code>null</code> not permitted). + */ 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")); + LookAndFeel.installColorsAndFont(b, prefix + "background", + prefix + "foreground", prefix + "font"); + LookAndFeel.installBorder(b, prefix + "border"); + b.setMargin(UIManager.getInsets(prefix + "margin")); + b.setIconTextGap(UIManager.getInt(prefix + "textIconGap")); b.setInputMap(JComponent.WHEN_FOCUSED, - (InputMap) defaults.get(prefix + "focusInputMap")); - b.setOpaque(true); + (InputMap) UIManager.get(prefix + "focusInputMap")); + b.setRolloverEnabled(UIManager.getBoolean(prefix + "rollover")); } + /** + * Removes the defaults added by {@link #installDefaults(AbstractButton)}. + * + * @param b the button (<code>null</code> not permitted). + */ protected void uninstallDefaults(AbstractButton b) { + if (b.getFont() instanceof UIResource) + b.setFont(null); b.setForeground(null); b.setBackground(null); b.setBorder(null); @@ -144,11 +182,25 @@ public class BasicButtonUI extends ButtonUI protected BasicButtonListener listener; + /** + * Creates and returns a new instance of {@link BasicButtonListener}. This + * method provides a hook to make it easy for subclasses to install a + * different listener. + * + * @param b the button. + * + * @return A new listener. + */ protected BasicButtonListener createButtonListener(AbstractButton b) { return new BasicButtonListener(b); } + /** + * Installs listeners for the button. + * + * @param b the button (<code>null</code> not permitted). + */ protected void installListeners(AbstractButton b) { listener = createButtonListener(b); @@ -159,6 +211,11 @@ public class BasicButtonUI extends ButtonUI b.addMouseMotionListener(listener); } + /** + * Uninstalls listeners for the button. + * + * @param b the button (<code>null</code> not permitted). + */ protected void uninstallListeners(AbstractButton b) { b.removeChangeListener(listener); @@ -215,12 +272,12 @@ public class BasicButtonUI extends ButtonUI return d; } - private static Icon currentIcon(AbstractButton b) + static Icon currentIcon(AbstractButton b) { Icon i = b.getIcon(); ButtonModel model = b.getModel(); - if (model.isPressed() && b.getPressedIcon() != null) + if (model.isPressed() && b.getPressedIcon() != null && b.isEnabled()) i = b.getPressedIcon(); else if (model.isRollover()) @@ -231,7 +288,7 @@ public class BasicButtonUI extends ButtonUI i = b.getRolloverIcon(); } - else if (b.isSelected()) + else if (b.isSelected() && b.isEnabled()) { if (b.isEnabled() && b.getSelectedIcon() != null) i = b.getSelectedIcon(); @@ -264,7 +321,10 @@ public class BasicButtonUI extends ButtonUI g.setFont(f); - SwingUtilities.calculateInnerArea(b, vr); + if (b.isBorderPainted()) + SwingUtilities.calculateInnerArea(b, vr); + else + vr = SwingUtilities.getLocalBounds(b); String text = SwingUtilities.layoutCompoundLabel(c, g.getFontMetrics(f), b.getText(), currentIcon(b), @@ -279,13 +339,11 @@ public class BasicButtonUI extends ButtonUI 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); - if (b.isFocusOwner()) + if (b.isFocusOwner() && b.isFocusPainted()) paintFocus(g, b, vr, tr, ir); } @@ -331,44 +389,25 @@ public class BasicButtonUI extends ButtonUI /** * Paints the background area of an {@link AbstractButton} in the pressed - * state. This means filling the supplied area with the {@link - * pressedBackgroundColor}. + * state. This means filling the supplied area with a darker than normal + * background. * * @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()) + if (b.isContentAreaFilled() && b.isOpaque()) { - g.setColor(b.getBackground()); + Rectangle area = new Rectangle(); + SwingUtilities.calculateInnerArea(b, area); + g.setColor(UIManager.getColor(getPropertyPrefix() + "shadow")); g.fillRect(area.x, area.y, area.width, area.height); } } /** - * Paints the "text" property of an {@link AbstractButton}, using the - * {@link textColor} color. + * Paints the "text" property of an {@link AbstractButton}. * * @param g The graphics context to paint with * @param c The component to paint the state of @@ -382,8 +421,7 @@ public class BasicButtonUI extends ButtonUI } /** - * Paints the "text" property of an {@link AbstractButton}, using the - * {@link textColor} color. + * Paints the "text" property of an {@link AbstractButton}. * * @param g The graphics context to paint with * @param b The button to paint the state of @@ -401,15 +439,15 @@ public class BasicButtonUI extends ButtonUI if (b.isEnabled()) { - g.setColor(b.getForeground()); - g.drawString(text, textRect.x, textRect.y + fm.getAscent()); + 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); + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + String prefix = getPropertyPrefix(); + g.setColor(defaults.getColor(prefix + "disabledText")); + g.drawString(text, textRect.x, textRect.y + fm.getAscent()); } } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxMenuItemUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxMenuItemUI.java index 945aea5..95e0dc9 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxMenuItemUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicCheckBoxMenuItemUI.java @@ -53,6 +53,15 @@ import javax.swing.plaf.ComponentUI; */ public class BasicCheckBoxMenuItemUI extends BasicMenuItemUI { + + /** + * Creates a new BasicCheckBoxMenuItemUI object. + */ + public BasicCheckBoxMenuItemUI() + { + super(); + } + /** * Factory method to create a BasicCheckBoxMenuItemUI for the given {@link * JComponent}, which should be a JCheckBoxMenuItem @@ -77,18 +86,6 @@ public class BasicCheckBoxMenuItemUI extends BasicMenuItemUI } /** - * 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! @@ -100,5 +97,7 @@ public class BasicCheckBoxMenuItemUI extends BasicMenuItemUI MenuElement[] path, MenuSelectionManager manager) { + // TODO: May not be implemented properly. + item.processMouseEvent(e, path, manager); } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicColorChooserUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicColorChooserUI.java index 4e6d381..5a872ae 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicColorChooserUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicColorChooserUI.java @@ -47,8 +47,7 @@ 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.LookAndFeel; import javax.swing.colorchooser.AbstractColorChooserPanel; import javax.swing.colorchooser.ColorChooserComponentFactory; import javax.swing.event.ChangeEvent; @@ -243,12 +242,21 @@ public class BasicColorChooserUI extends ColorChooserUI { uninstallListeners(); uninstallDefaults(); + uninstallDefaultChoosers(); pane = null; chooser = null; } /** + * Uninstalls the default color choosers that have been installed by this UI. + */ + protected void uninstallDefaultChoosers() + { + defaultChoosers = null; + } + + /** * This method installs the preview panel for the JColorChooser. */ protected void installPreviewPanel() @@ -281,11 +289,9 @@ public class BasicColorChooserUI extends ColorChooserUI */ 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")); + LookAndFeel.installColorsAndFont(chooser, "ColorChooser.background", + "ColorChooser.foreground", + "ColorChooser.font"); } /** diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxEditor.java b/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxEditor.java index dd867f0..831dde8 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxEditor.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxEditor.java @@ -45,35 +45,34 @@ 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. + * An editor used by the {@link BasicComboBoxUI} class. This editor uses a + * {@link JTextField} as the editor component. * * @author Olga Rodimina */ public class BasicComboBoxEditor extends Object implements ComboBoxEditor, FocusListener { + /** The editor component. */ protected JTextField editor; /** - * Creates a new BasicComboBoxEditor object. + * Creates a new <code>BasicComboBoxEditor</code> instance. */ public BasicComboBoxEditor() { editor = new JTextField(); - editor.setBorder(new EmptyBorder(1, 1, 1, 1)); + editor.setBorder(null); + editor.setColumns(9); } /** - * This method returns textfield that will be used by the combo box to - * display/edit currently selected item in the combo box. + * Returns the component that will be used by the combo box to display and + * edit the currently selected item in the combo box. * - * @return textfield that will be used by the combo box to display/edit - * currently selected item + * @return The editor component, which is a {@link JTextField} in this case. */ public Component getEditorComponent() { @@ -98,15 +97,18 @@ public class BasicComboBoxEditor extends Object implements ComboBoxEditor, } /** - * This method returns item that is currently editable. + * Returns the text from the editor component. * - * @return item in the combo box that is currently editable + * @return The text from the editor component. */ public Object getItem() { return editor.getText(); } + /** + * Selects all the text in the editor component. + */ public void selectAll() { editor.selectAll(); @@ -136,8 +138,8 @@ public class BasicComboBoxEditor extends Object implements ComboBoxEditor, } /** - * This method adds actionListener to the editor. If the user will edit - * currently selected item in the textfield and pressEnter, then action + * Adds an {@link ActionListener} to the editor component. 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. @@ -147,27 +149,32 @@ public class BasicComboBoxEditor extends Object implements ComboBoxEditor, */ public void addActionListener(ActionListener l) { - // FIXME: Need to implement + editor.addActionListener(l); } /** - * This method removes actionListener from the textfield. + * Removes the {@link ActionListener} from the editor component. * - * @param l the ActionListener to remove from the textfield. + * @param l the listener to remove. */ public void removeActionListener(ActionListener l) { - // FIXME: Need to implement + editor.removeActionListener(l); } + /** + * A subclass of {@link BasicComboBoxEditor} that implements the + * {@link UIResource} interface. + */ public static class UIResource extends BasicComboBoxEditor implements javax.swing.plaf.UIResource { /** - * Creates a new UIResource object. + * Creates a new <code>BasicComboBoxEditor.UIResource</code> instance. */ public UIResource() { + // Nothing to do here. } } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxRenderer.java b/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxRenderer.java index e4fbb83..8115605 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxRenderer.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxRenderer.java @@ -1,5 +1,5 @@ /* BasicComboBoxRenderer.java -- - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -40,36 +40,39 @@ package javax.swing.plaf.basic; import java.awt.Component; import java.awt.Dimension; +import java.awt.FontMetrics; import java.io.Serializable; +import javax.swing.JComboBox; 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.SwingUtilities; import javax.swing.border.Border; import javax.swing.border.EmptyBorder; /** - * This class is renderer for the combo box. + * A renderer for a {@link JComboBox}. * * @author Olga Rodimina */ -public class BasicComboBoxRenderer extends JLabel implements ListCellRenderer, - Serializable +public class BasicComboBoxRenderer + extends JLabel + implements ListCellRenderer, Serializable { /** - * This border is used whenever renderer doesn't have a focus. + * A shared border instance for all renderers. */ protected static Border noFocusBorder = new EmptyBorder(0, 0, 0, 0); /** - * Creates a new BasicComboBoxRenderer object. + * Creates a new <code>BasicComboBoxRenderer</code> object. */ public BasicComboBoxRenderer() { setHorizontalAlignment(SwingConstants.LEFT); + setBorder(noFocusBorder); } /** @@ -83,7 +86,8 @@ public class BasicComboBoxRenderer extends JLabel implements ListCellRenderer, } /** - * getListCellRendererComponent + * Returns a component that has been configured to display the given + * <code>value</code>. * * @param list List of items for which to the background and foreground * colors @@ -100,43 +104,59 @@ public class BasicComboBoxRenderer extends JLabel implements ListCellRenderer, boolean cellHasFocus) { String s = value.toString(); - setText(s); + + // String maybe larger than comboBox. + FontMetrics fm = getToolkit().getFontMetrics(list.getFont()); + int strWidth = SwingUtilities.computeStringWidth(fm, s); + int cbWidth = getSize().width; + if (cbWidth != 0 && strWidth > cbWidth) + { + char[] str = s.toCharArray(); + int currWidth = 0; + int i = 0; + String postStr = "... "; + cbWidth -= SwingUtilities.computeStringWidth(fm, postStr); + while (i < str.length && currWidth < cbWidth) + { + ++i; + currWidth = SwingUtilities.computeStringWidth(fm, new String(str, 0, i)); + } + setText(new String(str, 0, i) + postStr); + } + else + setText(s); + setOpaque(true); - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - - if (isSelected) + if (isSelected || cellHasFocus) { - setBackground(list.getSelectionBackground()); - setForeground(list.getSelectionForeground()); + setBackground(list.getSelectionBackground()); + setForeground(list.getSelectionForeground()); } else { - setBackground(list.getBackground()); - setForeground(list.getForeground()); + 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; } + /** + * A subclass of {@link BasicComboBoxRenderer} that implements the + * {@link javax.swing.plaf.UIResource} interface. + */ public static class UIResource extends BasicComboBoxRenderer implements javax.swing.plaf.UIResource { /** - * Creates a new UIResource object. + * Creates a new <code>UIResource</code> object. */ public UIResource() { + // Nothing to do here. } } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxUI.java index 68e18a6..464c8dd 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicComboBoxUI.java @@ -42,6 +42,8 @@ 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; @@ -69,15 +71,17 @@ import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JList; import javax.swing.ListCellRenderer; -import javax.swing.UIDefaults; +import javax.swing.LookAndFeel; +import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.event.ListDataEvent; import javax.swing.event.ListDataListener; import javax.swing.plaf.ComboBoxUI; import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.UIResource; /** - * UI Delegate for JComboBox + * A UI delegate for the {@link JComboBox} component. * * @author Olga Rodimina * @author Robert Schuster @@ -85,52 +89,54 @@ import javax.swing.plaf.ComponentUI; 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 + * The arrow button that is displayed in the right 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 + * The combo box represented by this UI delegate. */ 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 + * The component that is responsible for displaying/editing the selected + * item of the combo box. + * + * @see BasicComboBoxEditor#getEditorComponent() */ protected Component editor; /** - * Listener listening to focus events occuring in the JComboBox + * A listener listening to focus events occurring in the {@link JComboBox}. */ protected FocusListener focusListener; /** - * tells whether JComboBox currently has focus + * A flag indicating whether JComboBox currently has the focus. */ protected boolean hasFocus; /** - * Listener listening to item events fired by the JComboBox + * A listener listening to item events fired by the {@link JComboBox}. */ protected ItemListener itemListener; /** - * KeyListener listening to key events that occur while JComboBox has focus + * A listener listening to key events that occur while {@link JComboBox} has + * the focus. */ protected KeyListener keyListener; /** - * MouseListener listening to mouse events occuring in the combo box + * A listener listening to mouse events occuring in the {@link JComboBox}. */ 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 + * and foreground colors for combo box renderer are configured from this + * list. */ protected JList listBox; @@ -140,11 +146,14 @@ public class BasicComboBoxUI extends ComboBoxUI protected ListDataListener listDataListener; /** - * Popup list containing combo box's menu items + * Popup list containing the combo box's menu items. */ protected ComboPopup popup; + protected KeyListener popupKeyListener; + protected MouseListener popupMouseListener; + protected MouseMotionListener popupMouseMotionListener; /** @@ -152,30 +161,34 @@ public class BasicComboBoxUI extends ComboBoxUI */ protected PropertyChangeListener propertyChangeListener; + /** + * The button background. + * @see #installDefaults() + */ + private Color buttonBackground; + + /** + * The button shadow. + * @see #installDefaults() + */ + private Color buttonShadow; + /** - * Colors that are used to render selected item in the combo box. + * The button dark shadow. + * @see #installDefaults() */ - private Color shadow; - private Color darkShadow; - private Color highlight; - private Color lightHighlight; + private Color buttonDarkShadow; + + /** + * The button highlight. + * @see #installDefaults() + */ + private Color buttonHighlight; /* 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; + Dimension displaySize; // FIXME: This fields aren't used anywhere at this moment. protected Dimension cachedMinimumSize; @@ -183,19 +196,20 @@ public class BasicComboBoxUI extends ComboBoxUI protected boolean isMinimumSizeDirty; /** - * Creates a new BasicComboBoxUI object. + * Creates a new <code>BasicComboBoxUI</code> object. */ public BasicComboBoxUI() { + // Nothing to do here. } /** - * Factory method to create a BasicComboBoxUI for the given {@link - * JComponent}, which should be a {@link JComboBox}. + * A factory method to create a UI delegate 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}. + * @return A UI delegate for the {@link JComponent}. */ public static ComponentUI createUI(JComponent c) { @@ -203,9 +217,11 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method installs the UI for the given JComponent. + * Installs the UI for the given {@link JComponent}. * - * @param c The JComponent to install a UI for. + * @param c the JComponent to install a UI for. + * + * @see #uninstallUI(JComponent) */ public void installUI(JComponent c) { @@ -213,20 +229,22 @@ public class BasicComboBoxUI extends ComboBoxUI if (c instanceof JComboBox) { - comboBox = (JComboBox) c; - comboBox.setOpaque(true); - comboBox.setLayout(createLayoutManager()); - installDefaults(); - installComponents(); - installListeners(); - installKeyboardActions(); + comboBox = (JComboBox) c; + comboBox.setOpaque(true); + comboBox.setLayout(createLayoutManager()); + installDefaults(); + installComponents(); + installListeners(); + installKeyboardActions(); } } /** - * This method uninstalls the UI. + * Uninstalls the UI for the given {@link JComponent}. * * @param c The JComponent that is having this UI removed. + * + * @see #installUI(JComponent) */ public void uninstallUI(JComponent c) { @@ -238,27 +256,27 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method installs the defaults that are defined in the Basic look and - * feel for this {@link JComboBox}. + * Installs the defaults that are defined in the {@link BasicLookAndFeel} + * for this {@link JComboBox}. + * + * @see #uninstallDefaults() */ 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"); + LookAndFeel.installColorsAndFont(comboBox, "ComboBox.background", + "ComboBox.foreground", "ComboBox.font"); + + // fetch the button color scheme + buttonBackground = UIManager.getColor("ComboBox.buttonBackground"); + buttonShadow = UIManager.getColor("ComboBox.buttonShadow"); + buttonDarkShadow = UIManager.getColor("ComboBox.buttonDarkShadow"); + buttonHighlight = UIManager.getColor("ComboBox.buttonHighlight"); } /** - * This method creates and installs the listeners for this UI. + * Creates and installs the listeners for this UI. + * + * @see #uninstallListeners() */ protected void installListeners() { @@ -268,6 +286,7 @@ public class BasicComboBoxUI extends ComboBoxUI focusListener = createFocusListener(); comboBox.addFocusListener(focusListener); + listBox.addFocusListener(focusListener); itemListener = createItemListener(); comboBox.addItemListener(itemListener); @@ -276,35 +295,40 @@ public class BasicComboBoxUI extends ComboBoxUI comboBox.addKeyListener(keyListener); mouseListener = createMouseListener(); - comboBox.addMouseListener(mouseListener); + arrowButton.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 + * Uninstalls the defaults and sets any objects created during + * install to <code>null</code>. + * + * @see #installDefaults() */ protected void uninstallDefaults() { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - - comboBox.setBackground(null); - comboBox.setFont(null); - comboBox.setForeground(null); - - shadow = null; - darkShadow = null; - lightHighlight = null; - highlight = null; + if (comboBox.getFont() instanceof UIResource) + comboBox.setFont(null); + + if (comboBox.getForeground() instanceof UIResource) + comboBox.setForeground(null); + + if (comboBox.getBackground() instanceof UIResource) + comboBox.setBackground(null); + + buttonBackground = null; + buttonShadow = null; + buttonDarkShadow = null; + buttonHighlight = null; } /** * Detaches all the listeners we attached in {@link #installListeners}. + * + * @see #installListeners() */ protected void uninstallListeners() { @@ -312,6 +336,7 @@ public class BasicComboBoxUI extends ComboBoxUI propertyChangeListener = null; comboBox.removeFocusListener(focusListener); + listBox.removeFocusListener(focusListener); focusListener = null; comboBox.removeItemListener(itemListener); @@ -320,17 +345,15 @@ public class BasicComboBoxUI extends ComboBoxUI comboBox.removeKeyListener(keyListener); keyListener = null; - comboBox.removeMouseListener(mouseListener); + arrowButton.removeMouseListener(mouseListener); mouseListener = null; comboBox.getModel().removeListDataListener(listDataListener); listDataListener = null; - - unconfigureArrowButton(); } /** - * This method creates popup that will contain list of combo box's items + * Creates the popup that will contain list of combo box's items. * * @return popup containing list of combo box's items */ @@ -340,7 +363,7 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * Creates KeyListener to listen to key events. + * Creates a {@link KeyListener} to listen to key events. * * @return KeyListener that listens to key events. */ @@ -350,8 +373,8 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method create MouseListener that will listen to mouse event occuring - * in combo box. + * Creates a {@link MouseListener} that will listen to mouse events occurring + * in the combo box. * * @return the MouseListener */ @@ -361,10 +384,10 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method create FocusListener that will listen to changes in this + * Creates the {@link FocusListener} that will listen to changes in this * JComboBox's focus. * - * @return theFocusListener + * @return the FocusListener. */ protected FocusListener createFocusListener() { @@ -372,9 +395,9 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method create ListDataListener to listen to ComboBox's data model + * Creates a {@link ListDataListener} to listen to the combo box's data model. * - * @return ListDataListener + * @return The new listener. */ protected ListDataListener createListDataListener() { @@ -382,10 +405,10 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method creates ItemListener that will listen to to the changes in + * Creates an {@link ItemListener} that will listen to the changes in * the JComboBox's selection. * - * @return the ItemListener + * @return The ItemListener */ protected ItemListener createItemListener() { @@ -393,10 +416,10 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method creates PropertyChangeListener to listen to the changes in + * Creates a {@link PropertyChangeListener} to listen to the changes in * the JComboBox's bound properties. * - * @return the PropertyChangeListener + * @return The PropertyChangeListener */ protected PropertyChangeListener createPropertyChangeListener() { @@ -404,9 +427,10 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method returns layout manager for the combo box. + * Creates and returns a layout manager for the combo box. Subclasses can + * override this method to provide a different layout. * - * @return layout manager for the combo box + * @return a layout manager for the combo box. */ protected LayoutManager createLayoutManager() { @@ -414,10 +438,10 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method creates component that will be responsible for rendering the + * Creates a component that will be responsible for rendering the * selected component in the combo box. * - * @return render for the combo box + * @return A renderer for the combo box. */ protected ListCellRenderer createRenderer() { @@ -425,58 +449,54 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * 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. + * Creates the component that will be responsible for displaying/editing + * the 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. + * @return A new component that will be responsible for displaying/editing + * the selected item in the combo box. */ protected ComboBoxEditor createEditor() { - return new BasicComboBoxEditor(); + return new BasicComboBoxEditor.UIResource(); } /** - * This method installs components for this JComboBox. ArrowButton, main - * part of combo box (upper part) and popup list of items are created and + * Installs the 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); + // create drop down list of items + popup = createPopup(); + listBox = popup.getList(); // 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 and install arrow button + arrowButton = createArrowButton(); + configureArrowButton(); + comboBox.add(arrowButton); - // create drop down list of items - popup = createPopup(); + ComboBoxEditor currentEditor = comboBox.getEditor(); + if (currentEditor == null || currentEditor instanceof UIResource) + { + currentEditor = createEditor(); + comboBox.setEditor(currentEditor); + } + editor = currentEditor.getEditorComponent(); comboBox.revalidate(); } /** - * This method uninstalls components from this JComboBox + * Uninstalls components from this {@link JComboBox}. + * + * @see #installComponents() */ protected void uninstallComponents() { @@ -490,12 +510,18 @@ public class BasicComboBoxUI extends ComboBoxUI comboBox.setRenderer(null); - comboBox.setEditor(null); - editor = null; + // if the editor is not an instanceof UIResource, it was not set by the + // UI delegate, so don't clear it... + ComboBoxEditor currentEditor = comboBox.getEditor(); + if (currentEditor instanceof UIResource) + { + comboBox.setEditor(null); + editor = null; + } } /** - * This method adds editor to the combo box + * Adds the current editor to the combo box. */ public void addEditor() { @@ -503,7 +529,7 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method removes editor from the combo box + * Removes the current editor from the combo box. */ public void removeEditor() { @@ -511,15 +537,17 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method configures editor for this combo box. + * Configures the editor for this combo box. */ protected void configureEditor() { + editor.setFont(comboBox.getFont()); + comboBox.getEditor().setItem(comboBox.getSelectedItem()); // FIXME: Need to implement. Set font and add listeners. } /** - * This method removes all the listeners for the editor. + * Unconfigures the editor for this combo nox. This method is not implemented. */ protected void unconfigureEditor() { @@ -527,42 +555,50 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method adds listeners to the arrow button part of the combo box. + * Configures the arrow button. + * + * @see #configureArrowButton() */ public void configureArrowButton() { - arrowButton.addMouseListener(mouseListener); + arrowButton.setEnabled(comboBox.isEnabled()); + arrowButton.setFont(comboBox.getFont()); } /** - * This method removes listeners from the arrow button part of the combo - * box. + * Unconfigures the arrow button. + * + * @see #configureArrowButton() + * + * @specnote The specification says this method is implementation specific + * and should not be used or overridden. */ public void unconfigureArrowButton() { - arrowButton.removeMouseListener(mouseListener); + // Nothing to do here yet. } /** - * This method create arrow button for this JComboBox. Arrow button is - * responsible for displaying / hiding drop down list of items when it is - * clicked. + * Creates an arrow button for this {@link JComboBox}. The arrow button is + * displayed at the right end of the combo box and is used to display/hide + * the drop down list of items. * - * @return JButton arrow button for this JComboBox. + * @return A new button. */ protected JButton createArrowButton() { - return new BasicArrowButton(BasicArrowButton.SOUTH); + return new BasicArrowButton(BasicArrowButton.SOUTH, buttonBackground, + buttonShadow, buttonDarkShadow, buttonHighlight); } /** - * This method checks if popup part of the combo box is visible on the - * screen + * Returns <code>true</code> if the popup is visible, and <code>false</code> + * otherwise. * * @param c The JComboBox to check * - * @return true if popup part of the JComboBox is visible and false - * otherwise. + * @return <code>true</code> if popup part of the JComboBox is visible and + * <code>false</code> otherwise. */ public boolean isPopupVisible(JComboBox c) { @@ -570,7 +606,7 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * Displays/Hides JComboBox's list of items on the screen. + * Displays/hides the {@link JComboBox}'s list of items on the screen. * * @param c The combo box, for which list of items should be * displayed/hidden @@ -579,7 +615,10 @@ public class BasicComboBoxUI extends ComboBoxUI public void setPopupVisible(JComboBox c, boolean v) { if (v) - popup.show(); + { + popup.show(); + popup.getList().requestFocus(); + } else popup.hide(); } @@ -593,7 +632,7 @@ public class BasicComboBoxUI extends ComboBoxUI */ public boolean isFocusTraversable(JComboBox c) { - if (comboBox.isEditable()) + if (!comboBox.isEditable()) return true; return false; @@ -607,56 +646,28 @@ public class BasicComboBoxUI extends ComboBoxUI */ 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); + Rectangle rect = rectangleForCurrentValue(); + paintCurrentValueBackground(g, rect, hasFocus); + paintCurrentValue(g, rect, hasFocus); } /** - * Returns preferred size for the given menu item. + * Returns preferred size for the combo box. * * @param c comboBox for which to get preferred size * - * @return $Dimension$ preferred size for the given combo box + * @return The 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; + // note: overriding getMinimumSize() (for example in the MetalComboBoxUI + // class) affects the getPreferredSize() result, so it seems logical that + // this method is implemented by delegating to the getMinimumSize() method + return getMinimumSize(c); } /** - * This method returns the minimum size for this {@link JComboBox} for this + * Returns the minimum size for this {@link JComboBox} for this * look and feel. * * @param c The {@link JComponent} to find the minimum size for. @@ -665,20 +676,26 @@ public class BasicComboBoxUI extends ComboBoxUI */ public Dimension getMinimumSize(JComponent c) { - return null; + Dimension d = getDisplaySize(); + int arrowButtonWidth = d.height; + Dimension result = new Dimension(d.width + arrowButtonWidth, d.height); + return result; } + /** The value returned by the getMaximumSize() method. */ + private static final Dimension MAXIMUM_SIZE = new Dimension(32767, 32767); + /** - * This method returns the maximum size for this {@link JComboBox} for this + * 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. + * @return The maximum size (<code>Dimension(32767, 32767)</code>). */ public Dimension getMaximumSize(JComponent c) { - return null; + return MAXIMUM_SIZE; } public int getAccessibleChildrenCount(JComponent c) @@ -707,7 +724,7 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method selects next possible item relative to the current selection + * Selects next possible item relative to the current selection * to be next selected item in the combo box. */ protected void selectNextPossibleValue() @@ -718,7 +735,7 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method selects previous item relative to current selection to be + * Selects previous item relative to current selection to be * next selected item. */ protected void selectPreviousPossibleValue() @@ -729,8 +746,8 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method displays combo box popup if the popup is not currently shown - * on the screen and hides it if it is currently shown + * 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() { @@ -738,34 +755,23 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method returns bounds in which comboBox's selected Item will be - * displayed + * Returns the 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); - + Rectangle cbBounds = SwingUtilities.getLocalBounds(comboBox); + Rectangle abBounds = arrowButton.getBounds(); + Rectangle rectForCurrentValue = new Rectangle(cbBounds.x, cbBounds.y, + cbBounds.width - abBounds.width, cbBounds.height); return rectForCurrentValue; } /** - * This method returns insets of the current border. + * Returns the insets of the current border. * * @return Insets representing space between combo box and its border */ @@ -775,7 +781,7 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method paints currently selected value in the main part of the combo + * Paints currently selected value in the main part of the combo * box (part without popup). * * @param g graphics context @@ -794,28 +800,29 @@ public class BasicComboBoxUI extends ComboBoxUI * 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(); + Component comp = comboBox.getRenderer().getListCellRendererComponent( + listBox, (currentValue != null ? currentValue : ""), -1, + isPressed, hasFocus); + if (! comboBox.isEnabled()) + { + comp.setBackground(UIManager.getLookAndFeelDefaults().getColor( + "ComboBox.disabledBackground")); + comp.setForeground(UIManager.getLookAndFeelDefaults().getColor( + "ComboBox.disabledForeground")); + comp.setEnabled(false); + } + comp.setBounds(0, 0, bounds.width, bounds.height); + comp.setFont(comboBox.getFont()); + comp.paint(g); + + comboBox.revalidate(); } else comboBox.getEditor().setItem(comboBox.getSelectedItem()); } /** - * This method paints background of part of the combo box, where currently + * Paints the 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. * @@ -832,58 +839,102 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * Returns default size for the combo box that doesn't contain any elements - * in it + * Returns the default size for the display area of a combo box that does + * not contain any elements. This method returns the width and height of + * a single space in the current font, plus a margin of 1 pixel. * - * @return Default size of the combo box with no elements in it. + * @return The default display size. + * + * @see #getDisplaySize() */ protected Dimension getDefaultSize() { - return new Dimension(6, 17); + // There is nothing in the spec to say how this method should be + // implemented...so I've done some guessing, written some Mauve tests, + // and written something that gives dimensions that are close to the + // reference implementation. + FontMetrics fm = comboBox.getFontMetrics(comboBox.getFont()); + int w = fm.charWidth(' ') + 2; + int h = fm.getHeight() + 2; + return new Dimension(w, h); } /** - * Returns size of the largest item in the combo box. This size will be the - * size of the combo box, not including the arrowButton. + * Returns the size of the display area for 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. + * @return The size of the display area for the combo box. */ - protected Dimension getLargestItemSize() + protected Dimension getDisplaySize() { - 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) + if (!comboBox.isEditable()) { - largestItemSize = getDefaultSize(); - return largestItemSize; + Object prototype = comboBox.getPrototypeDisplayValue(); + if (prototype != null) + { + // calculate result based on prototype + ListCellRenderer renderer = comboBox.getRenderer(); + Component comp = renderer.getListCellRendererComponent(listBox, + prototype, -1, false, false); + Dimension compSize = comp.getPreferredSize(); + compSize.width += 2; // add 1 pixel margin around area + compSize.height += 2; + return compSize; + } + else + { + 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) + { + displaySize = getDefaultSize(); + return displaySize; + } + + 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); + Component comp = renderer.getListCellRendererComponent(listBox, + item, -1, false, false); + + Dimension compSize = comp.getPreferredSize(); + if (compSize.width + 2 > size.width) + size.width = compSize.width + 2; + if (compSize.height + 2 > size.height) + size.height = compSize.height + 2; + } + displaySize = size; + return displaySize; + } } - - 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++) + else // an editable combo, { - 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(); + Component comp = comboBox.getEditor().getEditorComponent(); + Dimension prefSize = comp.getPreferredSize(); + int width = prefSize.width; + int height = prefSize.height + 2; + Object prototype = comboBox.getPrototypeDisplayValue(); + if (prototype != null) + { + FontMetrics fm = comboBox.getFontMetrics(comboBox.getFont()); + width = Math.max(width, fm.stringWidth(prototype.toString()) + 2); + } + displaySize = new Dimension(width, height); + return displaySize; } - - largestItemSize = size; - return largestItemSize; } /** - * This method installs the keyboard actions for the JComboBox as specified + * Installs the keyboard actions for the {@link JComboBox} as specified * by the look and feel. */ protected void installKeyboardActions() @@ -892,7 +943,7 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method uninstalls the keyboard actions for the JComboBox there were + * Uninstalls the keyboard actions for the {@link JComboBox} there were * installed by in {@link #installListeners}. */ protected void uninstallKeyboardActions() @@ -901,22 +952,39 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This class is Layout Manager for this combo box. + * A {@link LayoutManager} used to position the sub-components of the + * {@link JComboBox}. + * + * @see BasicComboBoxUI#createLayoutManager() */ - public class ComboBoxLayoutManager extends Object implements LayoutManager + public class ComboBoxLayoutManager implements LayoutManager { /** * Creates a new ComboBoxLayoutManager object. */ public ComboBoxLayoutManager() { + // Nothing to do here. } + /** + * Adds a component to the layout. This method does nothing, since the + * layout manager doesn't need to track the components. + * + * @param name the name to associate the component with (ignored). + * @param comp the component (ignored). + */ public void addLayoutComponent(String name, Component comp) { // Do nothing } + /** + * Removes a component from the layout. This method does nothing, since + * the layout manager doesn't need to track the components. + * + * @param comp the component. + */ public void removeLayoutComponent(Component comp) { // Do nothing @@ -925,43 +993,30 @@ public class BasicComboBoxUI extends ComboBoxUI /** * Returns preferred layout size of the JComboBox. * - * @param parent Container for which preferred size should be calculated + * @param parent the Container for which the preferred size should be + * calculated. * - * @return preferred size for the given container + * @return The 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; + return getPreferredSize((JComponent) parent); } + /** + * Returns the minimum layout size. + * + * @param parent the container. + * + * @return The minimum size. + */ public Dimension minimumLayoutSize(Container parent) { return preferredLayoutSize(parent); } /** - * This method layouts out the components in the container. It puts arrow + * Arranges 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. @@ -972,21 +1027,19 @@ public class BasicComboBoxUI extends ComboBoxUI { // Position editor component to the left of arrow button if combo box is // editable - int editorWidth = comboBox.getBounds().width - arrowButtonWidth - 2; + int arrowSize = comboBox.getHeight(); + int editorWidth = comboBox.getBounds().width - arrowSize; 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); + editor.setBounds(0, 0, editorWidth, comboBox.getBounds().height); + + arrowButton.setBounds(editorWidth, 0, arrowSize, arrowSize); comboBox.revalidate(); } } /** - * This class handles focus changes occuring in the combo box. This class is + * 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. @@ -998,11 +1051,12 @@ public class BasicComboBoxUI extends ComboBoxUI */ public FocusHandler() { + // Nothing to do here. } /** - * This mehtod is invoked when combo box gains focus. It repaints main - * part of combo box accordingally. + * Invoked when combo box gains focus. It repaints main + * part of combo box accordingly. * * @param e the FocusEvent */ @@ -1013,22 +1067,22 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method is invoked when combo box loses focus It repaint main part - * of combo box accordingally and hides popup list of items. + * Invoked when the combo box loses focus. It repaints the main part + * of the combo box accordingly and hides the popup list of items. * * @param e the FocusEvent */ public void focusLost(FocusEvent e) { hasFocus = false; + setPopupVisible(comboBox, false); comboBox.repaint(); - popup.hide(); } } /** - * This class handles ItemEvent fired by the JComboBox when its selected - * item changes. + * Handles {@link ItemEvent}s fired by the {@link JComboBox} when its + * selected item changes. */ public class ItemHandler extends Object implements ItemListener { @@ -1037,16 +1091,19 @@ public class BasicComboBoxUI extends ComboBoxUI */ public ItemHandler() { + // Nothing to do here. } /** - * This method is invoked when selected item becomes deselected or when + * 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) { + if (e.getStateChange() == ItemEvent.SELECTED && comboBox.isEditable()) + comboBox.getEditor().setItem(e.getItem()); comboBox.repaint(); } } @@ -1058,11 +1115,11 @@ public class BasicComboBoxUI extends ComboBoxUI { public KeyHandler() { + // Nothing to do here. } - /* - * This method is invoked whenever key is pressed while JComboBox is in - * focus. + /** + * Invoked whenever key is pressed while JComboBox is in focus. */ public void keyPressed(KeyEvent e) { @@ -1072,7 +1129,7 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This class handles to the changes occuring in the JComboBox's data model + * Handles the changes occurring in the JComboBox's data model. */ public class ListDataHandler extends Object implements ListDataListener { @@ -1081,10 +1138,11 @@ public class BasicComboBoxUI extends ComboBoxUI */ public ListDataHandler() { + // Nothing to do here. } /** - * This method is invoked content's of JComboBox's data model are changed + * Invoked if the content's of JComboBox's data model are changed. * * @param e ListDataEvent describing the change. */ @@ -1094,36 +1152,27 @@ public class BasicComboBoxUI extends ComboBoxUI } /** - * This method is invoked when items were added to the JComboBox's data - * model. + * Invoked when items are 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); + if (displaySize == null) + displaySize = getDisplaySize(); + if (displaySize.width < getDefaultSize().width) + displaySize.width = getDefaultSize().width; + if (displaySize.height < getDefaultSize().height) + displaySize.height = getDefaultSize().height; - 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(); - } + comboBox.repaint(); } /** - * This method is invoked when items were removed from the JComboBox's + * Invoked when items are removed from the JComboBox's * data model. * * @param e ListDataEvent describing the change. @@ -1131,23 +1180,29 @@ public class BasicComboBoxUI extends ComboBoxUI public void intervalRemoved(ListDataEvent e) { // recalculate display size of the JComboBox. - largestItemSize = getLargestItemSize(); + displaySize = getDisplaySize(); comboBox.repaint(); } } /** - * This class handles PropertyChangeEvents fired by JComboBox. + * Handles {@link PropertyChangeEvent}s fired by the {@link JComboBox}. */ public class PropertyChangeHandler extends Object implements PropertyChangeListener { + /** + * Creates a new instance. + */ public PropertyChangeHandler() { + // Nothing to do here. } /** - * This method is invoked whenever bound property of JComboBox changes. + * Invoked whenever bound property of JComboBox changes. + * + * @param e the event. */ public void propertyChange(PropertyChangeEvent e) { @@ -1185,59 +1240,36 @@ public class BasicComboBoxUI extends ComboBoxUI if ((ComboBoxModel) e.getNewValue() != null) comboBox.getModel().addListDataListener(listDataListener); } + else if (e.getPropertyName().equals("font")) + { + Font font = (Font) e.getNewValue(); + editor.setFont(font); + listBox.setFont(font); + arrowButton.setFont(font); + comboBox.revalidate(); + comboBox.repaint(); + } // 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. + * A handler for mouse events occurring in the combo box. An instance of + * this class is returned by the <code>createMouseListener()</code> method. */ private class MouseHandler extends MouseAdapter { /** - * This method is invoked when mouse is pressed over the combo box. It - * repaints the combo box accordinglly + * Invoked when mouse is pressed over the combo box. It toggles the + * visibility of the popup list. * - * @param e the MouseEvent + * @param e the event */ 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(); - } + toggleOpenClose(); } } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicComboPopup.java b/libjava/classpath/javax/swing/plaf/basic/BasicComboPopup.java index 73aac8d..73979bb 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicComboPopup.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicComboPopup.java @@ -38,6 +38,7 @@ 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.Point; @@ -55,6 +56,7 @@ import java.awt.event.MouseMotionListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import javax.swing.BorderFactory; import javax.swing.ComboBoxModel; import javax.swing.JComboBox; import javax.swing.JLabel; @@ -178,8 +180,8 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup // 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); + scroller.setPreferredSize(new Dimension(cbBounds.width, popupHeight)); + pack(); // Highlight selected item in the combo box's drop down list if (comboBox.getSelectedIndex() != -1) @@ -478,6 +480,7 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup */ protected void configureScroller() { + scroller.setBorder(null); scroller.getViewport().setView(list); scroller.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); } @@ -488,6 +491,7 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup */ protected void configurePopup() { + setBorder(BorderFactory.createLineBorder(Color.BLACK)); // initialize list that will be used to display combo box's items this.list = createList(); ((JLabel) list.getCellRenderer()).setHorizontalAlignment(SwingConstants.LEFT); @@ -714,7 +718,11 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup protected void updateListBoxSelectionForEvent(MouseEvent anEvent, boolean shouldScroll) { - // FIXME: Need to implement + // TODO: We need to handle the shouldScroll parameter somehow. + int index = list.locationToIndex(anEvent.getPoint()); + // Check for valid index. + if (index >= 0) + list.setSelectedIndex(index); } /** @@ -732,6 +740,7 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup */ protected InvocationMouseHandler() { + // Nothing to do here. } /** @@ -744,7 +753,7 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup public void mousePressed(MouseEvent e) { if (comboBox.isEnabled()) - togglePopup(); + togglePopup(); } /** @@ -768,15 +777,15 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup // 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(); + // 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(); } } } @@ -792,6 +801,7 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup */ protected InvocationMouseMotionHandler() { + // Nothing to do here. } /** @@ -868,6 +878,7 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup */ protected ItemHandler() { + // Nothing to do here. } /** @@ -877,6 +888,7 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup */ public void itemStateChanged(ItemEvent e) { + // TODO: What should be done here? } } @@ -890,16 +902,20 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup { protected ListMouseHandler() { + // Nothing to do here. } public void mousePressed(MouseEvent e) { + // TODO: What should be do here? } public void mouseReleased(MouseEvent anEvent) { int index = list.locationToIndex(anEvent.getPoint()); - comboBox.setSelectedIndex(index); + // Check for valid index. + if (index >= 0) + comboBox.setSelectedIndex(index); hide(); } } @@ -913,15 +929,12 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup { protected ListMouseMotionHandler() { + // Nothing to do here. } 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(); + updateListBoxSelectionForEvent(anEvent, false); } } @@ -934,6 +947,7 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup { protected PropertyChangeHandler() { + // Nothing to do here. } public void propertyChange(PropertyChangeEvent e) @@ -1009,18 +1023,22 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup { public ListDataHandler() { + // Nothing to do here. } public void contentsChanged(ListDataEvent e) { + // Nothing to do here. } public void intervalAdded(ListDataEvent e) { + // Nothing to do here. } public void intervalRemoved(ListDataEvent e) { + // Nothing to do here. } } @@ -1032,10 +1050,12 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup { protected ListSelectionHandler() { + // Nothing to do here. } public void valueChanged(ListSelectionEvent e) { + // Nothing to do here. } } @@ -1046,10 +1066,12 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup { public InvocationKeyHandler() { + // Nothing to do here. } public void keyReleased(KeyEvent e) { + // Nothing to do here. } } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicDesktopIconUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicDesktopIconUI.java index 561b497..3f87302 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicDesktopIconUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicDesktopIconUI.java @@ -365,6 +365,7 @@ public class BasicDesktopIconUI extends DesktopIconUI */ public BasicDesktopIconUI() { + // Nothing to do here. } /** @@ -585,6 +586,7 @@ public class BasicDesktopIconUI extends DesktopIconUI } catch (PropertyVetoException pve) { + // We do nothing if the attempt has been vetoed. } } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicDesktopPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicDesktopPaneUI.java index b59261b..4116858 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicDesktopPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicDesktopPaneUI.java @@ -38,6 +38,7 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import java.awt.Color; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.beans.PropertyVetoException; @@ -49,10 +50,10 @@ 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; +import javax.swing.plaf.UIResource; /** * This class is the UI delegate for JDesktopPane for the Basic look and feel. @@ -74,13 +75,14 @@ public class BasicDesktopPaneUI extends DesktopPaneUI { if (desktop.getSelectedFrame() != null) { - try - { - desktop.getSelectedFrame().setClosed(true); - } - catch (PropertyVetoException pve) - { - } + try + { + desktop.getSelectedFrame().setClosed(true); + } + catch (PropertyVetoException pve) + { + // We do nothing if the attempts has been vetoed. + } } } @@ -112,13 +114,14 @@ public class BasicDesktopPaneUI extends DesktopPaneUI { if (desktop.getSelectedFrame() != null) { - try - { - desktop.getSelectedFrame().setMaximum(true); - } - catch (PropertyVetoException pve) - { - } + try + { + desktop.getSelectedFrame().setMaximum(true); + } + catch (PropertyVetoException pve) + { + // We do nothing if the attempts has been vetoed. + } } } @@ -150,13 +153,14 @@ public class BasicDesktopPaneUI extends DesktopPaneUI { if (desktop.getSelectedFrame() != null) { - try - { - desktop.getSelectedFrame().setIcon(true); - } - catch (PropertyVetoException pve) - { - } + try + { + desktop.getSelectedFrame().setIcon(true); + } + catch (PropertyVetoException pve) + { + // We do nothing if the attempt has been vetoed. + } } } @@ -236,16 +240,17 @@ public class BasicDesktopPaneUI extends DesktopPaneUI JInternalFrame frame = desktop.getSelectedFrame(); if (frame != null) { - try - { - if (frame.isIcon()) - frame.setIcon(false); - else if (frame.isMaximum()) - frame.setMaximum(false); - } - catch (PropertyVetoException pve) - { - } + try + { + if (frame.isIcon()) + frame.setIcon(false); + else if (frame.isMaximum()) + frame.setMaximum(false); + } + catch (PropertyVetoException pve) + { + // We do nothing if the attempt has been vetoed. + } } } @@ -304,6 +309,7 @@ public class BasicDesktopPaneUI extends DesktopPaneUI */ public BasicDesktopPaneUI() { + // Nothing to do here. } /** @@ -361,9 +367,9 @@ public class BasicDesktopPaneUI extends DesktopPaneUI */ protected void installDefaults() { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - - desktop.setBackground(defaults.getColor("desktop")); + Color bg = desktop.getBackground(); + if (bg == null || bg instanceof UIResource) + desktop.setBackground(UIManager.getColor("desktop")); } /** @@ -381,7 +387,7 @@ public class BasicDesktopPaneUI extends DesktopPaneUI protected void installKeyboardActions() { // FIXME: create actions and keystrokes. - registerKeyboardAction(); + registerKeyboardActions(); } /** @@ -405,7 +411,7 @@ public class BasicDesktopPaneUI extends DesktopPaneUI * This method registers the actions to the appropriate Action and Input * maps. */ - protected void registerKeyboardAction() + protected void registerKeyboardActions() { // FIXME: Do the binding. // XXX: the gtk windows tend to intercept a lot of the diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicFileChooserUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicFileChooserUI.java index f74e922..9c63965 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicFileChooserUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicFileChooserUI.java @@ -48,7 +48,6 @@ 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; @@ -60,9 +59,9 @@ 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; @@ -92,25 +91,31 @@ import javax.swing.plaf.FileChooserUI; /** - * DOCUMENT ME! + * A UI delegate for the {@link JFileChooser} component under the + * {@link BasicLookAndFeel}. */ public class BasicFileChooserUI extends FileChooserUI { /** - * DOCUMENT ME! + * A file filter that accepts all files. */ protected class AcceptAllFileFilter extends FileFilter { + /** + * Creates a new instance. + */ public AcceptAllFileFilter() { + // Nothing to do here. } /** - * DOCUMENT ME! + * Returns <code>true</code> always, as all files are accepted by this + * filter. * - * @param f DOCUMENT ME! + * @param f the file. * - * @return DOCUMENT ME! + * @return Always <code>true</code>. */ public boolean accept(File f) { @@ -118,9 +123,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns a description for this filter. * - * @return DOCUMENT ME! + * @return A description for the file filter. */ public String getDescription() { @@ -129,7 +134,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Handles a user action to approve the dialog selection. + * + * @see BasicFileChooserUI#getApproveSelectionAction() */ protected class ApproveSelectionAction extends AbstractAction { @@ -138,50 +145,55 @@ public class BasicFileChooserUI extends FileChooserUI */ protected ApproveSelectionAction() { + // Nothing to do here. } /** - * DOCUMENT ME! - * - * @param e DOCUMENT ME! + * Sets the current selection and closes the dialog. + * + * @param e the action event. */ public void actionPerformed(ActionEvent e) { - Object obj = filelist.getSelectedValue(); + Object obj = new String(parentPath + entry.getText()); if (obj != null) { - File f = filechooser.getFileSystemView().createFileObject(obj - .toString()); - if (filechooser.isTraversable(f) && - filechooser.getFileSelectionMode() == JFileChooser.FILES_ONLY) + File f = filechooser.getFileSystemView().createFileObject( + obj.toString()); + if (filechooser.isTraversable(f) + && filechooser.isDirectorySelectionEnabled()) filechooser.setCurrentDirectory(f); - else - { - filechooser.setSelectedFile(f); - filechooser.approveSelection(); - closeDialog(); - } + else + { + filechooser.setSelectedFile(f); + filechooser.approveSelection(); + closeDialog(); + } } } } /** - * DOCUMENT ME! + * Provides presentation information about files and directories. */ protected class BasicFileView extends FileView { - /** DOCUMENT ME! */ + /** Storage for cached icons. */ protected Hashtable iconCache = new Hashtable(); + /** + * Creates a new instance. + */ public BasicFileView() { + // Nothing to do here. } /** - * DOCUMENT ME! + * Adds an icon to the cache, associating it with the given file/directory. * - * @param f DOCUMENT ME! - * @param i DOCUMENT ME! + * @param f the file/directory. + * @param i the icon. */ public void cacheIcon(File f, Icon i) { @@ -189,7 +201,7 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Clears the icon cache. */ public void clearIconCache() { @@ -197,11 +209,12 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Retrieves the icon associated with the specified file/directory, if + * there is one. * - * @param f DOCUMENT ME! + * @param f the file/directory. * - * @return DOCUMENT ME! + * @return The cached icon (or <code>null</code>). */ public Icon getCachedIcon(File f) { @@ -209,11 +222,13 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns a description of the given file/directory. In this + * implementation, the description is the same as the name returned by + * {@link #getName(File)}. * - * @param f DOCUMENT ME! + * @param f the file/directory. * - * @return DOCUMENT ME! + * @return A description of the given file/directory. */ public String getDescription(File f) { @@ -221,11 +236,11 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns an icon appropriate for the given file or directory. * - * @param f DOCUMENT ME! + * @param f the file/directory. * - * @return DOCUMENT ME! + * @return An icon. */ public Icon getIcon(File f) { @@ -241,11 +256,11 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns the name for the given file/directory. * - * @param f DOCUMENT ME! + * @param f the file/directory. * - * @return DOCUMENT ME! + * @return The name of the file/directory. */ public String getName(File f) { @@ -253,11 +268,11 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns a localised description for the type of file/directory. * - * @param f DOCUMENT ME! + * @param f the file/directory. * - * @return DOCUMENT ME! + * @return A type description for the given file/directory. */ public String getTypeDescription(File f) { @@ -268,34 +283,38 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns {@link Boolean#TRUE} if the given file/directory is hidden, + * and {@link Boolean#FALSE} otherwise. * - * @param f DOCUMENT ME! + * @param f the file/directory. * - * @return DOCUMENT ME! + * @return {@link Boolean#TRUE} or {@link Boolean#FALSE}. */ public Boolean isHidden(File f) { - return new Boolean(filechooser.getFileSystemView().isHiddenFile(f)); + return Boolean.valueOf(filechooser.getFileSystemView().isHiddenFile(f)); } } /** - * DOCUMENT ME! + * Handles an action to cancel the file chooser. + * + * @see BasicFileChooserUI#getCancelSelectionAction() */ protected class CancelSelectionAction extends AbstractAction { /** - * Creates a new CancelSelectionAction object. + * Creates a new <code>CancelSelectionAction</code> object. */ protected CancelSelectionAction() { + // Nothing to do here. } /** - * DOCUMENT ME! + * Cancels the selection and closes the dialog. * - * @param e DOCUMENT ME! + * @param e the action event (ignored). */ public void actionPerformed(ActionEvent e) { @@ -305,21 +324,25 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * An action to handle changes to the parent directory (for example, via + * a click on the "up folder" button). + * + * @see BasicFileChooserUI#getChangeToParentDirectoryAction() */ protected class ChangeToParentDirectoryAction extends AbstractAction { /** - * Creates a new ChangeToParentDirectoryAction object. + * Creates a new <code>ChangeToParentDirectoryAction</code> object. */ protected ChangeToParentDirectoryAction() { + // Nothing to do here. } /** - * DOCUMENT ME! + * Handles the action event. * - * @param e DOCUMENT ME! + * @param e the action event. */ public void actionPerformed(ActionEvent e) { @@ -330,11 +353,13 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * A mouse listener that handles double-click events. + * + * @see BasicFileChooserUI#createDoubleClickListener(JFileChooser, JList) */ protected class DoubleClickListener extends MouseAdapter { - /** DOCUMENT ME! */ + /** A timer. */ private Timer timer = null; /** DOCUMENT ME! */ @@ -358,54 +383,57 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! - * - * @param e DOCUMENT ME! + * Handles a mouse click event. + * + * @param e the event. */ public void mouseClicked(MouseEvent e) { if (list.getSelectedValue() == null) - return; + 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(); - } + 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(); + String path = list.getSelectedValue().toString(); + File f = fsv.createFileObject(path); + if (filechooser.isTraversable(f)) + { + setDirectorySelected(true); + setDirectory(f); + } + else + { + setDirectorySelected(false); + setDirectory(null); + } + lastSelected = path; + parentPath = path.substring(0, path.lastIndexOf("/") + 1); + entry.setText(path.substring(path.lastIndexOf("/") + 1)); + timer.restart(); } } /** - * DOCUMENT ME! - * - * @param e DOCUMENT ME! + * Handles a mouse entered event (NOT IMPLEMENTED). + * + * @param e the mouse event. */ public void mouseEntered(MouseEvent e) { @@ -414,21 +442,26 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * An action that changes the file chooser to display the user's home + * directory. + * + * @see BasicFileChooserUI#getGoHomeAction() */ protected class GoHomeAction extends AbstractAction { /** - * Creates a new GoHomeAction object. + * Creates a new <code>GoHomeAction</code> object. */ protected GoHomeAction() { + // Nothing to do here. } /** - * DOCUMENT ME! + * Sets the directory to the user's home directory, and repaints the + * file chooser component. * - * @param e DOCUMENT ME! + * @param e the action event (ignored). */ public void actionPerformed(ActionEvent e) { @@ -440,21 +473,24 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * An action that handles the creation of a new folder/directory. + * + * @see BasicFileChooserUI#getNewFolderAction() */ protected class NewFolderAction extends AbstractAction { /** - * Creates a new NewFolderAction object. + * Creates a new <code>NewFolderAction</code> object. */ protected NewFolderAction() { + // Nothing to do here. } /** - * DOCUMENT ME! + * Handles the event by creating a new folder. * - * @param e DOCUMENT ME! + * @param e the action event (ignored). */ public void actionPerformed(ActionEvent e) { @@ -473,15 +509,18 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * A listener for selection events in the file list. + * + * @see BasicFileChooserUI#createListSelectionListener(JFileChooser) */ protected class SelectionListener implements ListSelectionListener { /** - * Creates a new SelectionListener object. + * Creates a new <code>SelectionListener</code> object. */ protected SelectionListener() { + // Nothing to do here. } /** @@ -504,6 +543,8 @@ public class BasicFileChooserUI extends FileChooserUI /** * DOCUMENT ME! + * + * @see BasicFileChooserUI#getUpdateAction() */ protected class UpdateAction extends AbstractAction { @@ -512,28 +553,30 @@ public class BasicFileChooserUI extends FileChooserUI */ protected UpdateAction() { + // Nothing to do here. } /** - * DOCUMENT ME! + * NOT YET IMPLEMENTED. * - * @param e DOCUMENT ME! + * @param e the action event. */ public void actionPerformed(ActionEvent e) { + // FIXME: implement this } } - /** DOCUMENT ME! */ + /** The localised mnemonic for the cancel button. */ protected int cancelButtonMnemonic; - /** DOCUMENT ME! */ + /** The localised text for the cancel button. */ protected String cancelButtonText; - /** DOCUMENT ME! */ + /** The localised tool tip text for the cancel button. */ protected String cancelButtonToolTipText; - /** DOCUMENT ME! */ + /** An icon representing a computer. */ protected Icon computerIcon = new Icon() { public int getIconHeight() @@ -548,10 +591,11 @@ public class BasicFileChooserUI extends FileChooserUI public void paintIcon(Component c, Graphics g, int x, int y) { + // FIXME: is this not implemented, or is the icon intentionally blank? } }; - /** DOCUMENT ME! */ + /** An icon for the "details view" button. */ protected Icon detailsViewIcon = new Icon() { public int getIconHeight() @@ -580,7 +624,7 @@ public class BasicFileChooserUI extends FileChooserUI } }; - /** DOCUMENT ME! */ + /** An icon representing a directory. */ protected Icon directoryIcon = new Icon() { public int getIconHeight() @@ -619,16 +663,16 @@ public class BasicFileChooserUI extends FileChooserUI } }; - /** DOCUMENT ME! */ + /** The localised Mnemonic for the open button. */ protected int directoryOpenButtonMnemonic; - /** DOCUMENT ME! */ + /** The localised text for the open button. */ protected String directoryOpenButtonText; - /** DOCUMENT ME! */ + /** The localised tool tip text for the open button. */ protected String directoryOpenButtonToolTipText; - /** DOCUMENT ME! */ + /** An icon representing a file. */ protected Icon fileIcon = new Icon() { public int getIconHeight() @@ -668,7 +712,7 @@ public class BasicFileChooserUI extends FileChooserUI } }; - /** DOCUMENT ME! */ + /** An icon representing a floppy drive. */ protected Icon floppyDriveIcon = new Icon() { public int getIconHeight() @@ -683,10 +727,11 @@ public class BasicFileChooserUI extends FileChooserUI public void paintIcon(Component c, Graphics g, int x, int y) { + // FIXME: is this not implemented, or is the icon intentionally blank? } }; - /** DOCUMENT ME! */ + /** An icon representing a hard drive. */ protected Icon hardDriveIcon = new Icon() { public int getIconHeight() @@ -701,19 +746,20 @@ public class BasicFileChooserUI extends FileChooserUI public void paintIcon(Component c, Graphics g, int x, int y) { + // FIXME: is this not implemented, or is the icon intentionally blank? } }; - /** DOCUMENT ME! */ + /** The localised mnemonic for the "help" button. */ protected int helpButtonMnemonic; - /** DOCUMENT ME! */ + /** The localised text for the "help" button. */ protected String helpButtonText; - /** DOCUMENT ME! */ + /** The localised tool tip text for the help button. */ protected String helpButtonToolTipText; - /** DOCUMENT ME! */ + /** An icon representing the user's home folder. */ protected Icon homeFolderIcon = new Icon() { public int getIconHeight() @@ -753,7 +799,7 @@ public class BasicFileChooserUI extends FileChooserUI } }; - /** DOCUMENT ME! */ + /** An icon for the "list view" button. */ protected Icon listViewIcon = new Icon() { public int getIconHeight() @@ -795,37 +841,37 @@ public class BasicFileChooserUI extends FileChooserUI } }; - /** DOCUMENT ME! */ + /** An icon for the "new folder" button. */ protected Icon newFolderIcon = directoryIcon; - /** DOCUMENT ME! */ + /** The localised mnemonic for the "open" button. */ protected int openButtonMnemonic; - /** DOCUMENT ME! */ + /** The localised text for the "open" button. */ protected String openButtonText; - /** DOCUMENT ME! */ + /** The localised tool tip text for the "open" button. */ protected String openButtonToolTipText; - /** DOCUMENT ME! */ + /** The localised mnemonic for the "save" button. */ protected int saveButtonMnemonic; - /** DOCUMENT ME! */ + /** The localised text for the "save" button. */ protected String saveButtonText; - /** DOCUMENT ME! */ + /** The localised tool tip text for the save button. */ protected String saveButtonToolTipText; - /** DOCUMENT ME! */ + /** The localised mnemonic for the "update" button. */ protected int updateButtonMnemonic; - /** DOCUMENT ME! */ + /** The localised text for the "update" button. */ protected String updateButtonText; - /** DOCUMENT ME! */ + /** The localised tool tip text for the "update" button. */ protected String updateButtonToolTipText; - /** DOCUMENT ME! */ + /** An icon for the "up folder" button. */ protected Icon upFolderIcon = new Icon() { public int getIconHeight() @@ -876,77 +922,84 @@ public class BasicFileChooserUI extends FileChooserUI // -- begin private, but package local since used in inner classes -- + /** The file chooser component represented by this UI delegate. */ JFileChooser filechooser; - /** DOCUMENT ME! */ + /** The file list. */ JList filelist; - /** DOCUMENT ME! */ + /** The combo box used to display/select file filters. */ JComboBox filters; - /** DOCUMENT ME! */ + /** The model for the directory list. */ BasicDirectoryModel model; - /** DOCUMENT ME! */ + /** The file filter for all files. */ FileFilter acceptAll = new AcceptAllFileFilter(); - /** DOCUMENT ME! */ + /** The default file view. */ FileView fv = new BasicFileView(); - /** DOCUMENT ME! */ + /** The icon size. */ static final int ICON_SIZE = 24; - /** DOCUMENT ME! */ + /** A combo box for display/selection of parent directories. */ JComboBox parents; - /** DOCUMENT ME! */ + /** The current file name. */ String filename; - /** DOCUMENT ME! */ + /** The accept (open/save) button. */ JButton accept; - /** DOCUMENT ME! */ + /** The cancel button. */ JButton cancel; - /** DOCUMENT ME! */ + /** The button to move up to the parent directory. */ JButton upFolderButton; - /** DOCUMENT ME! */ + /** The button to create a new directory. */ JButton newFolderButton; - /** DOCUMENT ME! */ + /** The button to move to the user's home directory. */ JButton homeFolderButton; - /** DOCUMENT ME! */ + /** An optional accessory panel. */ JPanel accessoryPanel; - /** DOCUMENT ME! */ + /** A property change listener. */ PropertyChangeListener propertyChangeListener; - /** DOCUMENT ME! */ + /** The text describing the filter for "all files". */ String acceptAllFileFilterText; - /** DOCUMENT ME! */ + /** The text describing a directory type. */ String dirDescText; - /** DOCUMENT ME! */ + /** The text describing a file type. */ String fileDescText; - /** DOCUMENT ME! */ + /** Is a directory selected? */ boolean dirSelected = false; - /** DOCUMENT ME! */ + /** The current directory. */ File currDir = null; + // FIXME: describe what is contained in the bottom panel + /** The bottom panel. */ JPanel bottomPanel; - - /** DOCUMENT ME! */ + + /** The close panel. */ JPanel closePanel; + /** Text box that displays file name */ + JTextField entry; + + /** Current parent path */ + String parentPath; + // -- end private -- - private class ListLabelRenderer - extends JLabel - implements ListCellRenderer + private class ListLabelRenderer extends JLabel implements ListCellRenderer { /** DOCUMENT ME! */ final Color selected = new Color(153, 204, 255); @@ -988,45 +1041,8 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Closes the dialog. */ - 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); @@ -1035,9 +1051,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * Creates a new BasicFileChooserUI object. + * Creates a new <code>BasicFileChooserUI</code> object. * - * @param b DOCUMENT ME! + * @param b the file chooser component. */ public BasicFileChooserUI(JFileChooser b) { @@ -1045,11 +1061,11 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns a UI delegate for the given component. * - * @param c DOCUMENT ME! + * @param c the component (should be a {@link JFileChooser}). * - * @return DOCUMENT ME! + * @return A new UI delegate. */ public static ComponentUI createUI(JComponent c) { @@ -1057,28 +1073,32 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! - * - * @param c DOCUMENT ME! + * Installs the UI for the specified component. + * + * @param c the component (should be a {@link JFileChooser}). */ public void installUI(JComponent c) { if (c instanceof JFileChooser) { - JFileChooser fc = (JFileChooser) c; - fc.resetChoosableFileFilters(); - createModel(); - clearIconCache(); - installDefaults(fc); - installComponents(fc); - installListeners(fc); + JFileChooser fc = (JFileChooser) c; + fc.resetChoosableFileFilters(); + createModel(); + clearIconCache(); + installDefaults(fc); + installComponents(fc); + installListeners(fc); + + Object path = filechooser.getCurrentDirectory(); + if (path != null) + parentPath = path.toString().substring(path.toString().lastIndexOf("/")); } } /** - * DOCUMENT ME! - * - * @param c DOCUMENT ME! + * Uninstalls this UI from the given component. + * + * @param c the component (should be a {@link JFileChooser}). */ public void uninstallUI(JComponent c) { @@ -1185,16 +1205,16 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Creates and install the subcomponents for the file chooser. * - * @param fc DOCUMENT ME! + * @param fc the file chooser. */ public void installComponents(JFileChooser fc) { JLabel look = new JLabel("Look In:"); parents = new JComboBox(); - parents.setRenderer(new CBLabelRenderer()); + parents.setRenderer(new BasicComboBoxRenderer()); boxEntries(); look.setLabelFor(parents); JPanel parentsPanel = new JPanel(); @@ -1226,9 +1246,9 @@ public class BasicFileChooserUI extends FileChooserUI buttonPanel.add(detailsViewButton); JPanel topPanel = new JPanel(); - topPanel.setLayout(new java.awt.FlowLayout()); + parentsPanel.add(buttonPanel); + topPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT, 0, 0)); topPanel.add(parentsPanel); - topPanel.add(buttonPanel); accessoryPanel = new JPanel(); if (filechooser.getAccessory() != null) @@ -1260,7 +1280,7 @@ public class BasicFileChooserUI extends FileChooserUI JLabel fileNameLabel = new JLabel("File Name:"); JLabel fileTypesLabel = new JLabel("Files of Type:"); - JTextField entry = new JTextField(); + entry = new JTextField(); filters = new JComboBox(); filterEntries(); @@ -1309,9 +1329,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Uninstalls the components from the file chooser. * - * @param fc DOCUMENT ME! + * @param fc the file chooser. */ public void uninstallComponents(JFileChooser fc) { @@ -1327,9 +1347,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Installs the listeners required by this UI delegate. * - * @param fc DOCUMENT ME! + * @param fc the file chooser. */ protected void installListeners(JFileChooser fc) { @@ -1349,9 +1369,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Uninstalls the listeners previously installed by this UI delegate. * - * @param fc DOCUMENT ME! + * @param fc the file chooser. */ protected void uninstallListeners(JFileChooser fc) { @@ -1360,9 +1380,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Installs the defaults for this UI delegate. * - * @param fc DOCUMENT ME! + * @param fc the file chooser. */ protected void installDefaults(JFileChooser fc) { @@ -1371,9 +1391,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Uninstalls the defaults previously added by this UI delegate. * - * @param fc DOCUMENT ME! + * @param fc the file chooser. */ protected void uninstallDefaults(JFileChooser fc) { @@ -1382,9 +1402,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Installs the icons for this UI delegate (NOT YET IMPLEMENTED). * - * @param fc DOCUMENT ME! + * @param fc the file chooser. */ protected void installIcons(JFileChooser fc) { @@ -1392,9 +1412,10 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Uninstalls the icons previously added by this UI delegate (NOT YET + * IMPLEMENTED). * - * @param fc DOCUMENT ME! + * @param fc the file chooser. */ protected void uninstallIcons(JFileChooser fc) { @@ -1402,9 +1423,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Installs the strings used by this UI delegate. * - * @param fc DOCUMENT ME! + * @param fc the file chooser. */ protected void installStrings(JFileChooser fc) { @@ -1432,9 +1453,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Uninstalls the strings previously added by this UI delegate. * - * @param fc DOCUMENT ME! + * @param fc the file chooser. */ protected void uninstallStrings(JFileChooser fc) { @@ -1460,7 +1481,7 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Creates a new directory model. */ protected void createModel() { @@ -1468,9 +1489,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns the directory model. * - * @return DOCUMENT ME! + * @return The directory model. */ public BasicDirectoryModel getModel() { @@ -1478,115 +1499,131 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! - * - * @param fc DOCUMENT ME! - * - * @return DOCUMENT ME! + * Creates a listener to handle changes to the properties of the given + * file chooser component. + * + * @param fc the file chooser component. + * + * @return A new listener. */ public PropertyChangeListener createPropertyChangeListener(JFileChooser fc) { return new PropertyChangeListener() + { + public void propertyChange(PropertyChangeEvent e) { - 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)) - { - filelist.clearSelection(); - filelist.revalidate(); - filelist.repaint(); - setDirectorySelected(false); - setDirectory(filechooser.getCurrentDirectory()); - boxEntries(); - } - 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(); - } - }; + // 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)) + { + filelist.clearSelection(); + filelist.revalidate(); + filelist.repaint(); + setDirectorySelected(false); + setDirectory(filechooser.getCurrentDirectory()); + boxEntries(); + } + 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! + * Returns the current file name. + * + * @return The current file name. */ public String getFileName() { @@ -1594,9 +1631,11 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns the current directory name. * - * @return DOCUMENT ME! + * @return The directory name. + * + * @see #setDirectoryName(String) */ public String getDirectoryName() { @@ -1605,9 +1644,11 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Sets the file name. * - * @param filename DOCUMENT ME! + * @param filename the file name. + * + * @see #getFileName() */ public void setFileName(String filename) { @@ -1615,9 +1656,11 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Sets the directory name (NOT IMPLEMENTED). * - * @param dirname DOCUMENT ME! + * @param dirname the directory name. + * + * @see #getDirectoryName() */ public void setDirectoryName(String dirname) { @@ -1625,9 +1668,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Rescans the current directory. * - * @param fc DOCUMENT ME! + * @param fc the file chooser. */ public void rescanCurrentDirectory(JFileChooser fc) { @@ -1636,10 +1679,10 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * NOT YET IMPLEMENTED. * - * @param fc DOCUMENT ME! - * @param f DOCUMENT ME! + * @param fc the file chooser. + * @param f the file. */ public void ensureFileIsVisible(JFileChooser fc, File f) { @@ -1647,9 +1690,10 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns the {@link JFileChooser} component that this UI delegate + * represents. * - * @return DOCUMENT ME! + * @return The component represented by this UI delegate. */ public JFileChooser getFileChooser() { @@ -1657,9 +1701,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns the optional accessory panel. * - * @return DOCUMENT ME! + * @return The optional accessory panel. */ public JPanel getAccessoryPanel() { @@ -1667,11 +1711,11 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Creates and returns an approve (open or save) button for the dialog. * - * @param fc DOCUMENT ME! + * @param fc the file chooser. * - * @return DOCUMENT ME! + * @return The button. */ public JButton getApproveButton(JFileChooser fc) { @@ -1682,11 +1726,14 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns the tool tip text for the approve (open/save) button. This first + * checks the file chooser to see if a value has been explicitly set - if + * not, a default value appropriate for the type of file chooser is + * returned. * - * @param fc DOCUMENT ME! + * @param fc the file chooser. * - * @return DOCUMENT ME! + * @return The tool tip text. */ public String getApproveButtonToolTipText(JFileChooser fc) { @@ -1699,7 +1746,7 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Clears the icon cache. */ public void clearIconCache() { @@ -1708,11 +1755,11 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Creates a new listener to handle selections in the file list. * - * @param fc DOCUMENT ME! + * @param fc the file chooser component. * - * @return DOCUMENT ME! + * @return A new instance of {@link SelectionListener}. */ public ListSelectionListener createListSelectionListener(JFileChooser fc) { @@ -1720,12 +1767,12 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Creates a new listener to handle double-click events. * - * @param fc DOCUMENT ME! - * @param list DOCUMENT ME! + * @param fc the file chooser component. + * @param list the list. * - * @return DOCUMENT ME! + * @return A new instance of {@link DoubleClickListener}. */ protected MouseListener createDoubleClickListener(JFileChooser fc, JList list) { @@ -1733,9 +1780,10 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns <code>true</code> if a directory is selected, and + * <code>false</code> otherwise. * - * @return DOCUMENT ME! + * @return A boolean. */ protected boolean isDirectorySelected() { @@ -1743,9 +1791,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Sets the flag that indicates whether the current directory is selected. * - * @param selected DOCUMENT ME! + * @param selected the new flag value. */ protected void setDirectorySelected(boolean selected) { @@ -1753,9 +1801,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns the current directory. * - * @return DOCUMENT ME! + * @return The current directory. */ protected File getDirectory() { @@ -1763,9 +1811,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Sets the current directory. * - * @param f DOCUMENT ME! + * @param f the directory. */ protected void setDirectory(File f) { @@ -1773,11 +1821,11 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns the "accept all" file filter. * - * @param fc DOCUMENT ME! + * @param fc the file chooser component. * - * @return DOCUMENT ME! + * @return The "accept all" file filter. */ public FileFilter getAcceptAllFileFilter(JFileChooser fc) { @@ -1785,25 +1833,29 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns the file view for the file chooser. This returns either the + * file view that has been explicitly set for the {@link JFileChooser}, or + * a default file view. * - * @param fc DOCUMENT ME! + * @param fc the file chooser component. * - * @return DOCUMENT ME! + * @return The file view. + * + * @see JFileChooser#getFileView() */ public FileView getFileView(JFileChooser fc) { - if (fc.getFileView() != null) - return fc.getFileView(); return fv; } /** - * DOCUMENT ME! + * Returns the dialog title. * - * @param fc DOCUMENT ME! + * @param fc the file chooser (<code>null</code> not permitted). * - * @return DOCUMENT ME! + * @return The dialog title. + * + * @see JFileChooser#getDialogTitle() */ public String getDialogTitle(JFileChooser fc) { @@ -1828,11 +1880,13 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns the approve button mnemonic. * - * @param fc DOCUMENT ME! + * @param fc the file chooser (<code>null</code> not permitted). * - * @return DOCUMENT ME! + * @return The approve button mnemonic. + * + * @see JFileChooser#getApproveButtonMnemonic() */ public int getApproveButtonMnemonic(JFileChooser fc) { @@ -1845,11 +1899,13 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Returns the approve button text. * - * @param fc DOCUMENT ME! + * @param fc the file chooser (<code>null</code> not permitted). * - * @return DOCUMENT ME! + * @return The approve button text. + * + * @see JFileChooser#getApproveButtonText() */ public String getApproveButtonText(JFileChooser fc) { @@ -1862,9 +1918,10 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Creates and returns a new action that will be used with the "new folder" + * button. * - * @return DOCUMENT ME! + * @return A new instance of {@link GoHomeAction}. */ public Action getNewFolderAction() { @@ -1872,9 +1929,10 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Creates and returns a new action that will be used with the "home folder" + * button. * - * @return DOCUMENT ME! + * @return A new instance of {@link GoHomeAction}. */ public Action getGoHomeAction() { @@ -1882,9 +1940,10 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Creates and returns a new action that will be used with the "up folder" + * button. * - * @return DOCUMENT ME! + * @return A new instance of {@link ChangeToParentDirectoryAction}. */ public Action getChangeToParentDirectoryAction() { @@ -1892,9 +1951,10 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Creates and returns a new action that will be used with the "approve" + * button. * - * @return DOCUMENT ME! + * @return A new instance of {@link ApproveSelectionAction}. */ public Action getApproveSelectionAction() { @@ -1902,9 +1962,10 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Creates and returns a new action that will be used with the "cancel" + * button. * - * @return DOCUMENT ME! + * @return A new instance of {@link CancelSelectionAction}. */ public Action getCancelSelectionAction() { @@ -1912,9 +1973,9 @@ public class BasicFileChooserUI extends FileChooserUI } /** - * DOCUMENT ME! + * Creates and returns a new instance of {@link UpdateAction}. * - * @return DOCUMENT ME! + * @return An action. */ public Action getUpdateAction() { diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicFormattedTextFieldUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicFormattedTextFieldUI.java index 3abd76f..9c7f1c4 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicFormattedTextFieldUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicFormattedTextFieldUI.java @@ -1,5 +1,5 @@ /* BasicFormattedTextFieldUI.java - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -39,6 +39,7 @@ exception statement from your version. */ package javax.swing.plaf.basic; import javax.swing.JComponent; +import javax.swing.UIDefaults; import javax.swing.plaf.ComponentUI; /** @@ -48,6 +49,7 @@ public class BasicFormattedTextFieldUI extends BasicTextFieldUI { public BasicFormattedTextFieldUI() { + // Nothing to do here. } public static ComponentUI createUI(JComponent c) @@ -55,6 +57,11 @@ public class BasicFormattedTextFieldUI extends BasicTextFieldUI return new BasicFormattedTextFieldUI(); } + /** + * Returns the prefix for entries in the {@link UIDefaults} table. + * + * @return "FormattedTextField" + */ protected String getPropertyPrefix() { return "FormattedTextField"; diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicGraphicsUtils.java b/libjava/classpath/javax/swing/plaf/basic/BasicGraphicsUtils.java index 757ac47..068de34 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicGraphicsUtils.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicGraphicsUtils.java @@ -71,6 +71,7 @@ public class BasicGraphicsUtils */ public BasicGraphicsUtils() { + // Nothing to do here. } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicIconFactory.java b/libjava/classpath/javax/swing/plaf/basic/BasicIconFactory.java index 56a67b0..6debd64 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicIconFactory.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicIconFactory.java @@ -41,7 +41,6 @@ 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.Icon; @@ -241,34 +240,33 @@ public class BasicIconFactory implements Serializable { return new DummyIcon(); } + + /** + * Returns a new instance of a 4 x 8 icon showing a small black triangle that + * points to the right. This is displayed in menu items that have a + * sub menu. + * + * @return The icon. + */ public static Icon getMenuArrowIcon() { return new Icon() { public int getIconHeight() { - return 12; + return 8; } - public int getIconWidth() { - return 12; + return 4; } - 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)); - + for (int i = 0; i < 4; i++) + g.drawLine(x + i, y + i, x + i, y + 7 - i); g.setColor(saved); - g.translate(-x, -y); } }; } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameTitlePane.java b/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameTitlePane.java index cc26294..73d3e61 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameTitlePane.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameTitlePane.java @@ -84,6 +84,14 @@ public class BasicInternalFrameTitlePane extends JComponent public class CloseAction extends AbstractAction { /** + * Creates a new action. + */ + public CloseAction() + { + super("Close"); + } + + /** * This method is called when something closes the JInternalFrame. * * @param e The ActionEvent. @@ -92,13 +100,14 @@ public class BasicInternalFrameTitlePane extends JComponent { if (frame.isClosable()) { - try - { - frame.setClosed(true); - } - catch (PropertyVetoException pve) - { - } + try + { + frame.setClosed(true); + } + catch (PropertyVetoException pve) + { + // We do nothing if the attempt has been vetoed. + } } } } @@ -113,6 +122,14 @@ public class BasicInternalFrameTitlePane extends JComponent public class IconifyAction extends AbstractAction { /** + * Creates a new action. + */ + public IconifyAction() + { + super("Minimize"); + } + + /** * This method is called when the user wants to iconify the * JInternalFrame. * @@ -122,13 +139,14 @@ public class BasicInternalFrameTitlePane extends JComponent { if (frame.isIconifiable() && ! frame.isIcon()) { - try - { - frame.setIcon(true); - } - catch (PropertyVetoException pve) - { - } + try + { + frame.setIcon(true); + } + catch (PropertyVetoException pve) + { + // We do nothing if the attempt has been vetoed. + } } } } @@ -143,6 +161,13 @@ public class BasicInternalFrameTitlePane extends JComponent public class MaximizeAction extends AbstractAction { /** + * Creates a new action. + */ + public MaximizeAction() + { + super("Maximize"); + } + /** * This method is called when the user wants to maximize the * JInternalFrame. * @@ -152,13 +177,14 @@ public class BasicInternalFrameTitlePane extends JComponent { try { - if (frame.isMaximizable() && ! frame.isMaximum()) - frame.setMaximum(true); - else if (frame.isMaximum()) - frame.setMaximum(false); + if (frame.isMaximizable() && ! frame.isMaximum()) + frame.setMaximum(true); + else if (frame.isMaximum()) + frame.setMaximum(false); } catch (PropertyVetoException pve) { + // We do nothing if the attempt has been vetoed. } } } @@ -173,6 +199,13 @@ public class BasicInternalFrameTitlePane extends JComponent public class MoveAction extends AbstractAction { /** + * Creates a new action. + */ + public MoveAction() + { + super("Move"); + } + /** * This method is called when the user wants to drag the JInternalFrame. * * @param e The ActionEvent. @@ -194,6 +227,13 @@ public class BasicInternalFrameTitlePane extends JComponent public class RestoreAction extends AbstractAction { /** + * Creates a new action. + */ + public RestoreAction() + { + super("Restore"); + } + /** * This method is called when the user wants to restore the * JInternalFrame. * @@ -203,13 +243,14 @@ public class BasicInternalFrameTitlePane extends JComponent { if (frame.isMaximum()) { - try - { - frame.setMaximum(false); - } - catch (PropertyVetoException pve) - { - } + try + { + frame.setMaximum(false); + } + catch (PropertyVetoException pve) + { + // We do nothing if the attempt has been vetoed. + } } } } @@ -224,6 +265,13 @@ public class BasicInternalFrameTitlePane extends JComponent public class SizeAction extends AbstractAction { /** + * Creates a new action. + */ + public SizeAction() + { + super("Size"); + } + /** * This method is called when the user wants to resize the JInternalFrame. * * @param e The ActionEvent. @@ -377,24 +425,26 @@ public class BasicInternalFrameTitlePane extends JComponent 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); + int buttonWidth = closeIcon.getIconWidth(); + loc -= buttonWidth + 2; + closeButton.setBounds(loc, top, buttonWidth, buttonHeight); } if (maxButton.isVisible()) { - loc -= buttonWidth + 2; - maxButton.setBounds(loc, top, buttonWidth, buttonHeight); + int buttonWidth = maxIcon.getIconWidth(); + loc -= buttonWidth + 2; + maxButton.setBounds(loc, top, buttonWidth, buttonHeight); } if (iconButton.isVisible()) { - loc -= buttonWidth + 2; - iconButton.setBounds(loc, top, buttonWidth, buttonHeight); + int buttonWidth = iconIcon.getIconWidth(); + loc -= buttonWidth + 2; + iconButton.setBounds(loc, top, buttonWidth, buttonHeight); } if (title != null) @@ -435,6 +485,7 @@ public class BasicInternalFrameTitlePane extends JComponent */ public void removeLayoutComponent(Component c) { + // Nothing to do here. } } @@ -466,6 +517,7 @@ public class BasicInternalFrameTitlePane extends JComponent // These buttons cannot be given focus. return false; } + } /** The action command for the Close action. */ @@ -522,6 +574,9 @@ public class BasicInternalFrameTitlePane extends JComponent /** The icon displayed in the iconify button. */ protected Icon iconIcon = BasicIconFactory.createEmptyFrameIcon(); + /** The icon displayed in the close button. */ + protected Icon closeIcon; + /** The JInternalFrame that this TitlePane is used in. */ protected JInternalFrame frame; @@ -645,7 +700,7 @@ public class BasicInternalFrameTitlePane extends JComponent */ protected void installListeners() { - propertyChangeListener = new PropertyChangeHandler(); + propertyChangeListener = createPropertyChangeListener(); frame.addPropertyChangeListener(propertyChangeListener); } @@ -663,14 +718,17 @@ public class BasicInternalFrameTitlePane extends JComponent */ protected void installDefaults() { - // FIXME: move icons to defaults. UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - setFont(defaults.getFont("InternalFrame.titleFont")); + title.setFont(defaults.getFont("InternalFrame.titleFont")); selectedTextColor = defaults.getColor("InternalFrame.activeTitleForeground"); selectedTitleColor = defaults.getColor("InternalFrame.activeTitleBackground"); notSelectedTextColor = defaults.getColor("InternalFrame.inactiveTitleForeground"); notSelectedTitleColor = defaults.getColor("InternalFrame.inactiveTitleBackground"); + + closeIcon = UIManager.getIcon("InternalFrame.closeIcon"); + iconIcon = UIManager.getIcon("InternalFrame.iconifyIcon"); + maxIcon = UIManager.getIcon("InternalFrame.maximizeIcon"); } /** @@ -683,6 +741,10 @@ public class BasicInternalFrameTitlePane extends JComponent selectedTitleColor = null; notSelectedTextColor = null; notSelectedTitleColor = null; + + closeIcon = null; + iconIcon = null; + maxIcon = null; } /** @@ -691,12 +753,15 @@ public class BasicInternalFrameTitlePane extends JComponent protected void createButtons() { closeButton = new PaneButton(closeAction); + closeButton.setText(null); if (!frame.isClosable()) closeButton.setVisible(false); iconButton = new PaneButton(iconifyAction); + iconButton.setText(null); if (!frame.isIconifiable()) iconButton.setVisible(false); maxButton = new PaneButton(maximizeAction); + maxButton.setText(null); if (!frame.isMaximizable()) maxButton.setVisible(false); } @@ -706,15 +771,12 @@ public class BasicInternalFrameTitlePane extends JComponent */ protected void setButtonIcons() { - Icon icon = UIManager.getIcon("InternalFrame.closeIcon"); - if (icon != null) - closeButton.setIcon(icon); - icon = UIManager.getIcon("InternalFrame.iconifyIcon"); - if (icon != null) - iconButton.setIcon(icon); - icon = UIManager.getIcon("InternalFrame.maximizeIcon"); - if (icon != null) - maxButton.setIcon(icon); + if (closeIcon != null && closeButton != null) + closeButton.setIcon(closeIcon); + if (iconIcon != null && iconButton != null) + iconButton.setIcon(iconIcon); + if (maxIcon != null && maxButton != null) + maxButton.setIcon(maxIcon); } /** @@ -816,11 +878,12 @@ public class BasicInternalFrameTitlePane extends JComponent 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(); + Font f = title.getFont(); + g.setFont(f); + FontMetrics fm = g.getFontMetrics(f); if (frame.isSelected()) g.setColor(selectedTextColor); else diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameUI.java index 8f76ea0..d9dadda 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicInternalFrameUI.java @@ -56,20 +56,17 @@ 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.LookAndFeel; 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; @@ -202,67 +199,66 @@ public class BasicInternalFrameUI extends InternalFrameUI */ public void mouseDragged(MouseEvent e) { - // If the frame is maximized, there is nothing that + // If the frame is maximized, there is nothing that // can be dragged around. if (frame.isMaximum()) - return; + return; DesktopManager dm = getDesktopManager(); Rectangle b = frame.getBounds(); Dimension min = frame.getMinimumSize(); if (min == null) - min = new Dimension(0, 0); + 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)); + 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(); + Rectangle fBounds = frame.getBounds(); - dm.dragFrame(frame, e.getX() - xOffset + b.x, - e.getY() - yOffset + b.y); + dm.dragFrame(frame, e.getX() - xOffset + b.x, e.getY() - yOffset + + b.y); } } @@ -304,17 +300,17 @@ public class BasicInternalFrameUI extends InternalFrameUI if (e.getSource() == frame && frame.isResizable()) { - direction = sectionOfClick(x, y); - dm.beginResizingFrame(frame, direction); + direction = sectionOfClick(x, y); + dm.beginResizingFrame(frame, direction); } else if (e.getSource() == titlePane) { - Rectangle tBounds = titlePane.getBounds(); + Rectangle tBounds = titlePane.getBounds(); - xOffset = e.getX() - tBounds.x + insets.left; - yOffset = e.getY() - tBounds.y + insets.top; + xOffset = e.getX() - tBounds.x + insets.left; + yOffset = e.getY() - tBounds.y + insets.top; - dm.beginDraggingFrame(frame); + dm.beginDraggingFrame(frame); } } @@ -329,9 +325,9 @@ public class BasicInternalFrameUI extends InternalFrameUI xOffset = 0; yOffset = 0; if (e.getSource() == frame && frame.isResizable()) - dm.endResizingFrame(frame); + dm.endResizingFrame(frame); else if (e.getSource() == titlePane) - dm.endDraggingFrame(frame); + dm.endDraggingFrame(frame); } /** @@ -348,21 +344,21 @@ public class BasicInternalFrameUI extends InternalFrameUI Insets insets = frame.getInsets(); Rectangle b = frame.getBounds(); if (x < insets.left && y < insets.top) - return NORTH_WEST; + return NORTH_WEST; else if (x > b.width - insets.right && y < insets.top) - return NORTH_EAST; + return NORTH_EAST; else if (x > b.width - insets.right && y > b.height - insets.bottom) - return SOUTH_EAST; + return SOUTH_EAST; else if (x < insets.left && y > b.height - insets.bottom) - return SOUTH_WEST; + return SOUTH_WEST; else if (y < insets.top) - return NORTH; + return NORTH; else if (x < insets.left) - return WEST; + return WEST; else if (y > b.height - insets.bottom) - return SOUTH; + return SOUTH; else if (x > b.width - insets.right) - return EAST; + return EAST; return -1; } @@ -377,8 +373,9 @@ public class BasicInternalFrameUI extends InternalFrameUI { /** * This method is called when the JDesktopPane is hidden. - * - * @param e The ComponentEvent fired. + * + * @param e + * The ComponentEvent fired. */ public void componentHidden(ComponentEvent e) { @@ -387,8 +384,9 @@ public class BasicInternalFrameUI extends InternalFrameUI /** * This method is called when the JDesktopPane is moved. - * - * @param e The ComponentEvent fired. + * + * @param e + * The ComponentEvent fired. */ public void componentMoved(ComponentEvent e) { @@ -397,22 +395,23 @@ public class BasicInternalFrameUI extends InternalFrameUI /** * This method is called when the JDesktopPane is resized. - * - * @param e The ComponentEvent fired. + * + * @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(); + 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. @@ -420,8 +419,9 @@ public class BasicInternalFrameUI extends InternalFrameUI /** * This method is called when the JDesktopPane is shown. - * - * @param e The ComponentEvent fired. + * + * @param e + * The ComponentEvent fired. */ public void componentShown(ComponentEvent e) { @@ -435,21 +435,25 @@ public class BasicInternalFrameUI extends InternalFrameUI public class InternalFrameLayout implements LayoutManager { /** - * This method is called when the given Component is added to the + * 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. + * + * @param name + * The name of the Component. + * @param c + * The Component added. */ public void addLayoutComponent(String name, Component c) { + // Nothing to do here. } /** * This method is used to set the bounds of the children of the * JInternalFrame. - * - * @param c The Container to lay out. + * + * @param c + * The Container to lay out. */ public void layoutContainer(Container c) { @@ -468,38 +472,38 @@ public class BasicInternalFrameUI extends InternalFrameUI if (northPane != null) { - Dimension nDims = northPane.getPreferredSize(); - nh = Math.min(nDims.height, dims.height); + Dimension nDims = northPane.getPreferredSize(); + nh = Math.min(nDims.height, dims.height); - northPane.setBounds(insets.left, insets.top, dims.width, nh); + northPane.setBounds(insets.left, insets.top, dims.width, nh); } if (southPane != null) { - Dimension sDims = southPane.getPreferredSize(); - sh = Math.min(sDims.height, dims.height - nh); + Dimension sDims = southPane.getPreferredSize(); + sh = Math.min(sDims.height, dims.height - nh); - southPane.setBounds(insets.left, insets.top + dims.height - sh, - dims.width, sh); + 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); + Dimension wDims = westPane.getPreferredSize(); + ww = Math.min(dims.width, wDims.width); - westPane.setBounds(insets.left, insets.top + nh, ww, remHeight); + westPane.setBounds(insets.left, insets.top + nh, ww, remHeight); } if (eastPane != null) { - Dimension eDims = eastPane.getPreferredSize(); - ew = Math.min(eDims.width, dims.width - ww); + Dimension eDims = eastPane.getPreferredSize(); + ew = Math.min(eDims.width, dims.width - ww); - eastPane.setBounds(insets.left + dims.width - ew, insets.top + nh, - ew, remHeight); + eastPane.setBounds(insets.left + dims.width - ew, insets.top + nh, + ew, remHeight); } int remWidth = dims.width - ww - ew; @@ -510,9 +514,9 @@ public class BasicInternalFrameUI extends InternalFrameUI /** * This method returns the minimum layout size. - * - * @param c The Container to find a minimum layout size for. - * + * + * @param c + * The Container to find a minimum layout size for. * @return The minimum dimensions for the JInternalFrame. */ public Dimension minimumLayoutSize(Container c) @@ -522,9 +526,9 @@ public class BasicInternalFrameUI extends InternalFrameUI /** * This method returns the maximum layout size. - * - * @param c The Container to find a maximum layout size for. - * + * + * @param c + * The Container to find a maximum layout size for. * @return The maximum dimensions for the JInternalFrame. */ public Dimension maximumLayoutSize(Container c) @@ -534,9 +538,9 @@ public class BasicInternalFrameUI extends InternalFrameUI /** * Th8is method returns the preferred layout size. - * - * @param c The Container to find a preferred layout size for. - * + * + * @param c + * The Container to find a preferred layout size for. * @return The preferred dimensions for the JInternalFrame. */ public Dimension preferredLayoutSize(Container c) @@ -546,10 +550,11 @@ public class BasicInternalFrameUI extends InternalFrameUI /** * DOCUMENT ME! - * - * @param c DOCUMENT ME! - * @param min DOCUMENT ME! - * + * + * @param c + * DOCUMENT ME! + * @param min + * DOCUMENT ME! * @return DOCUMENT ME! */ private Dimension getSize(Container c, boolean min) @@ -558,7 +563,7 @@ public class BasicInternalFrameUI extends InternalFrameUI Dimension contentDims = frame.getContentPane().getPreferredSize(); if (min) - contentDims.width = contentDims.height = 0; + contentDims.width = contentDims.height = 0; int nWidth = 0; int nHeight = 0; int sWidth = 0; @@ -571,42 +576,42 @@ public class BasicInternalFrameUI extends InternalFrameUI if (northPane != null) { - dims = northPane.getPreferredSize(); - if (dims != null) - { - nWidth = dims.width; - nHeight = dims.height; - } + 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; - } + 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; - } + 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; - } + dims = westPane.getPreferredSize(); + if (dims != null) + { + wWidth = dims.width; + wHeight = dims.height; + } } int width = Math.max(sWidth, nWidth); @@ -630,6 +635,7 @@ public class BasicInternalFrameUI extends InternalFrameUI */ public void removeLayoutComponent(Component c) { + // Nothing to do here. } } @@ -657,8 +663,9 @@ public class BasicInternalFrameUI extends InternalFrameUI /** * This method is called when the mouse enters the glass pane. - * - * @param e The MouseEvent. + * + * @param e + * The MouseEvent. */ public void mouseEntered(MouseEvent e) { @@ -667,8 +674,9 @@ public class BasicInternalFrameUI extends InternalFrameUI /** * This method is called when the mouse is clicked on the glass pane. - * - * @param e The MouseEvent. + * + * @param e + * The MouseEvent. */ public void mouseClicked(MouseEvent e) { @@ -677,8 +685,9 @@ public class BasicInternalFrameUI extends InternalFrameUI /** * This method is called when the mouse is dragged in the glass pane. - * - * @param e The MouseEvent. + * + * @param e + * The MouseEvent. */ public void mouseDragged(MouseEvent e) { @@ -687,8 +696,9 @@ public class BasicInternalFrameUI extends InternalFrameUI /** * This method is called when the mouse exits the glass pane. - * - * @param e The MouseEvent. + * + * @param e + * The MouseEvent. */ public void mouseExited(MouseEvent e) { @@ -697,8 +707,9 @@ public class BasicInternalFrameUI extends InternalFrameUI /** * This method is called when the mouse is moved in the glass pane. - * - * @param e The MouseEvent. + * + * @param e + * The MouseEvent. */ public void mouseMoved(MouseEvent e) { @@ -706,9 +717,10 @@ public class BasicInternalFrameUI extends InternalFrameUI } /** - * This method is called when the mouse is pressed in the glass pane. - * - * @param e The MouseEvent. + * This method is called when the mouse is pressed in the glass pane. + * + * @param e + * The MouseEvent. */ public void mousePressed(MouseEvent e) { @@ -717,9 +729,10 @@ public class BasicInternalFrameUI extends InternalFrameUI } /** - * This method is called when the mouse is released in the glass pane. - * - * @param e The MouseEvent. + * This method is called when the mouse is released in the glass pane. + * + * @param e + * The MouseEvent. */ public void mouseReleased(MouseEvent e) { @@ -727,10 +740,10 @@ public class BasicInternalFrameUI extends InternalFrameUI } /** - * This method acquires a candidate component to dispatch the MouseEvent - * to. - * - * @param me The MouseEvent to acquire a component for. + * 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) { @@ -738,134 +751,137 @@ public class BasicInternalFrameUI extends InternalFrameUI int y = me.getY(); // Find the candidate which should receive this event. - Component parent = frame.getContentPane(); + Component parent = frame.getLayeredPane(); if (parent == null) - return; + 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(); - } + 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 + // don't dispatch any event at all. We only care about the lightweight // children here. if (candidate == frame.getContentPane()) - candidate = null; + 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()); + 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); + 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); - } + 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; + // 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; + // 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. + * 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; - } - } + MouseEvent me = (MouseEvent) e; + acquireComponentForMouseEvent(me); + + //If there is no target, return + if (mouseEventTarget == null) + return; + + //Avoid re-dispatching to ourselves and causing an infinite loop + if (mouseEventTarget.equals(frame.getGlassPane())) + return; + + // Avoid dispatching ENTERED and EXITED events twice. + if (mouseEventTarget.isShowing() + && e.getID() != MouseEvent.MOUSE_ENTERED + && e.getID() != MouseEvent.MOUSE_EXITED) + { + MouseEvent newEvt = SwingUtilities.convertMouseEvent( + frame.getGlassPane(), + 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; + } + } } } } @@ -874,17 +890,18 @@ public class BasicInternalFrameUI extends InternalFrameUI * This helper class listens for PropertyChangeEvents from the * JInternalFrame. */ - public class InternalFramePropertyChangeListener - implements PropertyChangeListener, VetoableChangeListener + 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. + * 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 + public void vetoableChange(PropertyChangeEvent e) + throws PropertyVetoException { if (e.getPropertyName().equals(JInternalFrame.IS_CLOSED_PROPERTY)) { @@ -892,75 +909,78 @@ public class BasicInternalFrameUI extends InternalFrameUI { frame.setVisible(false); frame.getDesktopPane().repaint(); - throw new PropertyVetoException ("close operation is HIDE_ON_CLOSE\n", e); + 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); + 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. + * 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); + 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); + 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); + if (frame.isSelected()) + activateFrame(frame); + else + deactivateFrame(frame); } else if (evt.getPropertyName().equals(JInternalFrame.ROOT_PANE_PROPERTY) - || evt.getPropertyName().equals(JInternalFrame.GLASS_PANE_PROPERTY)) + || evt.getPropertyName().equals( + JInternalFrame.GLASS_PANE_PROPERTY)) { - Component old = (Component) evt.getOldValue(); - old.removeMouseListener(glassPaneDispatcher); - old.removeMouseMotionListener(glassPaneDispatcher); + Component old = (Component) evt.getOldValue(); + old.removeMouseListener(glassPaneDispatcher); + old.removeMouseMotionListener(glassPaneDispatcher); - Component newPane = (Component) evt.getNewValue(); - newPane.addMouseListener(glassPaneDispatcher); - newPane.addMouseMotionListener(glassPaneDispatcher); + Component newPane = (Component) evt.getNewValue(); + newPane.addMouseListener(glassPaneDispatcher); + newPane.addMouseMotionListener(glassPaneDispatcher); - frame.revalidate(); + 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); - } - */ + /* + * 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 + private class InternalFrameBorder extends AbstractBorder implements + UIResource { /** The width of the border. */ private static final int bSize = 5; @@ -970,7 +990,7 @@ public class BasicInternalFrameUI extends InternalFrameUI /** * This method returns whether the border is opaque. - * + * * @return Whether the border is opaque. */ public boolean isBorderOpaque() @@ -980,9 +1000,9 @@ public class BasicInternalFrameUI extends InternalFrameUI /** * This method returns the insets of the border. - * - * @param c The Component to find border insets for. - * + * + * @param c + * The Component to find border insets for. * @return The border insets. */ public Insets getBorderInsets(Component c) @@ -992,13 +1012,19 @@ public class BasicInternalFrameUI extends InternalFrameUI /** * 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. + * + * @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) @@ -1111,6 +1137,7 @@ public class BasicInternalFrameUI extends InternalFrameUI */ public BasicInternalFrameUI(JInternalFrame b) { + // Nothing to do here. } /** @@ -1135,21 +1162,21 @@ public class BasicInternalFrameUI extends InternalFrameUI { if (c instanceof JInternalFrame) { - frame = (JInternalFrame) c; + frame = (JInternalFrame) c; - internalFrameLayout = createLayoutManager(); - frame.setLayout(internalFrameLayout); + internalFrameLayout = createLayoutManager(); + frame.setLayout(internalFrameLayout); - ((JComponent) frame.getRootPane().getGlassPane()).setOpaque(false); - frame.getRootPane().getGlassPane().setVisible(true); + ((JComponent) frame.getRootPane().getGlassPane()).setOpaque(false); + frame.getRootPane().getGlassPane().setVisible(true); - installDefaults(); - installListeners(); - installComponents(); - installKeyboardActions(); + installDefaults(); + installListeners(); + installComponents(); + installKeyboardActions(); - frame.setOpaque(true); - frame.invalidate(); + frame.setOpaque(true); + frame.invalidate(); } } @@ -1177,10 +1204,8 @@ public class BasicInternalFrameUI extends InternalFrameUI */ protected void installDefaults() { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - Border border = defaults.getBorder("InternalFrame.border"); - frame.setBorder(border); - frame.setFrameIcon(defaults.getIcon("InternalFrame.icon")); + LookAndFeel.installBorder(frame, "InternalFrame.border"); + frame.setFrameIcon(UIManager.getIcon("InternalFrame.icon")); // InternalFrames are invisible by default. frame.setVisible(false); } @@ -1343,14 +1368,14 @@ public class BasicInternalFrameUI extends InternalFrameUI { if (currentPane != null) { - deinstallMouseHandlers(currentPane); - frame.remove(currentPane); + deinstallMouseHandlers(currentPane); + frame.remove(currentPane); } if (newPane != null) { - installMouseHandlers(newPane); - frame.add(newPane); + installMouseHandlers(newPane); + frame.add(newPane); } } @@ -1678,6 +1703,16 @@ public class BasicInternalFrameUI extends InternalFrameUI } /** + * This is a convenience method that deactivates the JInternalFrame. + * + * @param f the JInternalFrame to deactivate + */ + protected void deactivateFrame(JInternalFrame f) + { + getDesktopManager().deactivateFrame(f); + } + + /** * This method returns a new ComponentListener for the JDesktopPane. * * @return A new ComponentListener. diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicLabelUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicLabelUI.java index bb9ce6c..c8f677f 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicLabelUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicLabelUI.java @@ -50,9 +50,8 @@ import java.beans.PropertyChangeListener; import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.JLabel; +import javax.swing.LookAndFeel; import javax.swing.SwingUtilities; -import javax.swing.UIDefaults; -import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.LabelUI; @@ -60,9 +59,7 @@ 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 +public class BasicLabelUI extends LabelUI implements PropertyChangeListener { /** The labelUI that is shared by all labels. */ protected static BasicLabelUI labelUI; @@ -345,11 +342,8 @@ public class BasicLabelUI */ 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")); + LookAndFeel.installColorsAndFont(c, "Label.background", "Label.foreground", + "Label.font"); //XXX: There are properties we don't use called disabledForeground //and disabledShadow. } @@ -417,8 +411,6 @@ public class BasicLabelUI */ public void propertyChange(PropertyChangeEvent e) { - JLabel c = (JLabel) e.getSource(); - c.revalidate(); - c.repaint(); + // What to do here? } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicListUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicListUI.java index 841bd67..3393299 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicListUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicListUI.java @@ -38,31 +38,35 @@ 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.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.InputEvent; -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.AbstractAction; +import javax.swing.ActionMap; import javax.swing.CellRendererPane; +import javax.swing.DefaultListSelectionModel; +import javax.swing.InputMap; import javax.swing.JComponent; import javax.swing.JList; import javax.swing.JViewport; +import javax.swing.KeyStroke; import javax.swing.ListCellRenderer; import javax.swing.ListModel; import javax.swing.ListSelectionModel; +import javax.swing.LookAndFeel; import javax.swing.UIDefaults; import javax.swing.UIManager; import javax.swing.event.ListDataEvent; @@ -70,7 +74,9 @@ import javax.swing.event.ListDataListener; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import javax.swing.event.MouseInputListener; +import javax.swing.plaf.ActionMapUIResource; import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.InputMapUIResource; import javax.swing.plaf.ListUI; /** @@ -125,8 +131,9 @@ public class BasicListUI extends ListUI * Helper method to repaint the focused cell's * lost or acquired focus state. */ - void repaintCellFocus() + protected void repaintCellFocus() { + // TODO: Implement this properly. } } @@ -183,141 +190,231 @@ public class BasicListUI extends ListUI */ public void valueChanged(ListSelectionEvent e) { + int index1 = e.getFirstIndex(); + int index2 = e.getLastIndex(); + Rectangle damaged = getCellBounds(list, index1, index2); + list.repaint(damaged); } } /** - * A helper class which listens for {@link KeyEvents}s - * from the {@link JList}. + * This class is used to mimmic the behaviour of the JDK when registering + * keyboard actions. It is the same as the private class used in JComponent + * for the same reason. This class receives an action event and dispatches + * it to the true receiver after altering the actionCommand property of the + * event. */ - private class KeyHandler extends KeyAdapter + private static class ActionListenerProxy + extends AbstractAction { - public KeyHandler() + ActionListener target; + String bindingCommandName; + + public ActionListenerProxy(ActionListener li, + String cmd) { + target = li; + bindingCommandName = cmd; } - - public void keyPressed( KeyEvent evt ) + + public void actionPerformed(ActionEvent e) + { + ActionEvent derivedEvent = new ActionEvent(e.getSource(), + e.getID(), + bindingCommandName, + e.getModifiers()); + target.actionPerformed(derivedEvent); + } + } + + class ListAction extends AbstractAction + { + public void actionPerformed (ActionEvent e) { - int lead = BasicListUI.this.list.getLeadSelectionIndex(); - int max = BasicListUI.this.list.getModel().getSize() - 1; + int lead = list.getLeadSelectionIndex(); + int max = list.getModel().getSize() - 1; + DefaultListSelectionModel selModel = (DefaultListSelectionModel)list.getSelectionModel(); + String command = e.getActionCommand(); // 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 (command.equals("selectNextRow")) { - if (evt.getModifiers() == 0) - { - BasicListUI.this.list.clearSelection(); - BasicListUI.this.list.setSelectedIndex(Math.min(lead+1,max)); - } - else if (evt.getModifiers() == InputEvent.SHIFT_MASK) + selectNextIndex(); + } + else if (command.equals("selectPreviousRow")) + { + selectPreviousIndex(); + } + else if (command.equals("clearSelection")) + { + list.clearSelection(); + } + else if (command.equals("selectAll")) + { + list.setSelectionInterval(0, max); + // this next line is to restore the lead selection index to the old + // position, because select-all should not change the lead index + list.addSelectionInterval(lead, lead); + } + else if (command.equals("selectLastRow")) + { + list.setSelectedIndex(list.getModel().getSize() - 1); + } + else if (command.equals("selectLastRowChangeLead")) + { + selModel.moveLeadSelectionIndex(list.getModel().getSize() - 1); + } + else if (command.equals("scrollDownExtendSelection")) + { + int target; + if (lead == list.getLastVisibleIndex()) { - BasicListUI.this.list.getSelectionModel(). - setLeadSelectionIndex(Math.min(lead+1,max)); + target = Math.min + (max, lead + (list.getLastVisibleIndex() - + list.getFirstVisibleIndex() + 1)); } + else + target = list.getLastVisibleIndex(); + selModel.setLeadSelectionIndex(target); } - else if ((evt.getKeyCode() == KeyEvent.VK_UP) - || (evt.getKeyCode() == KeyEvent.VK_KP_UP)) + else if (command.equals("scrollDownChangeLead")) { - if (evt.getModifiers() == 0) + int target; + if (lead == list.getLastVisibleIndex()) { - BasicListUI.this.list.clearSelection(); - BasicListUI.this.list.setSelectedIndex(Math.max(lead-1,0)); + target = Math.min + (max, lead + (list.getLastVisibleIndex() - + list.getFirstVisibleIndex() + 1)); } - else if (evt.getModifiers() == InputEvent.SHIFT_MASK) + else + target = list.getLastVisibleIndex(); + selModel.moveLeadSelectionIndex(target); + } + else if (command.equals("scrollUpExtendSelection")) + { + int target; + if (lead == list.getFirstVisibleIndex()) { - BasicListUI.this.list.getSelectionModel(). - setLeadSelectionIndex(Math.max(lead-1,0)); + target = Math.max + (0, lead - (list.getLastVisibleIndex() - + list.getFirstVisibleIndex() + 1)); } + else + target = list.getFirstVisibleIndex(); + selModel.setLeadSelectionIndex(target); } - else if (evt.getKeyCode() == KeyEvent.VK_PAGE_UP) + else if (command.equals("scrollUpChangeLead")) { int target; - if (lead == BasicListUI.this.list.getFirstVisibleIndex()) + if (lead == list.getFirstVisibleIndex()) { target = Math.max - (0, lead - (BasicListUI.this.list.getLastVisibleIndex() - - BasicListUI.this.list.getFirstVisibleIndex() + 1)); + (0, lead - (list.getLastVisibleIndex() - + list.getFirstVisibleIndex() + 1)); } else + target = list.getFirstVisibleIndex(); + selModel.moveLeadSelectionIndex(target); + } + else if (command.equals("selectNextRowExtendSelection")) + { + selModel.setLeadSelectionIndex(Math.min(lead + 1,max)); + } + else if (command.equals("selectFirstRow")) + { + list.setSelectedIndex(0); + } + else if (command.equals("selectFirstRowChangeLead")) + { + selModel.moveLeadSelectionIndex(0); + } + else if (command.equals("selectFirstRowExtendSelection")) + { + selModel.setLeadSelectionIndex(0); + } + else if (command.equals("selectPreviousRowExtendSelection")) + { + selModel.setLeadSelectionIndex(Math.max(0,lead - 1)); + } + else if (command.equals("scrollUp")) + { + int target; + if (lead == list.getFirstVisibleIndex()) { - target = BasicListUI.this.list.getFirstVisibleIndex(); + target = Math.max + (0, lead - (list.getLastVisibleIndex() - + list.getFirstVisibleIndex() + 1)); } - if (evt.getModifiers() == 0) - BasicListUI.this.list.setSelectedIndex(target); - else if (evt.getModifiers() == InputEvent.SHIFT_MASK) - BasicListUI.this.list.getSelectionModel(). - setLeadSelectionIndex(target); + else + target = list.getFirstVisibleIndex(); + list.setSelectedIndex(target); } - else if (evt.getKeyCode() == KeyEvent.VK_PAGE_DOWN) + else if (command.equals("selectLastRowExtendSelection")) + { + selModel.setLeadSelectionIndex(list.getModel().getSize() - 1); + } + else if (command.equals("scrollDown")) { int target; - if (lead == BasicListUI.this.list.getLastVisibleIndex()) + if (lead == list.getLastVisibleIndex()) { target = Math.min - (max, lead + (BasicListUI.this.list.getLastVisibleIndex() - - BasicListUI.this.list.getFirstVisibleIndex() + 1)); + (max, lead + (list.getLastVisibleIndex() - + list.getFirstVisibleIndex() + 1)); } else + target = list.getLastVisibleIndex(); + list.setSelectedIndex(target); + } + else if (command.equals("selectNextRowChangeLead")) + { + if (selModel.getSelectionMode() != ListSelectionModel.MULTIPLE_INTERVAL_SELECTION) + selectNextIndex(); + else + { + selModel.moveLeadSelectionIndex(Math.min(max, lead + 1)); + } + } + else if (command.equals("selectPreviousRowChangeLead")) + { + if (selModel.getSelectionMode() != ListSelectionModel.MULTIPLE_INTERVAL_SELECTION) + selectPreviousIndex(); + else { - target = BasicListUI.this.list.getLastVisibleIndex(); + selModel.moveLeadSelectionIndex(Math.max(0, lead - 1)); } - if (evt.getModifiers() == 0) - BasicListUI.this.list.setSelectedIndex(target); - else if (evt.getModifiers() == InputEvent.SHIFT_MASK) - BasicListUI.this.list.getSelectionModel(). - setLeadSelectionIndex(target); - } - else if (evt.getKeyCode() == KeyEvent.VK_BACK_SLASH - && (evt.getModifiers() == InputEvent.CTRL_MASK)) + } + else if (command.equals("addToSelection")) { - BasicListUI.this.list.clearSelection(); + list.addSelectionInterval(lead, lead); } - else if ((evt.getKeyCode() == KeyEvent.VK_HOME) - || evt.getKeyCode() == KeyEvent.VK_END) + else if (command.equals("extendTo")) { - if (evt.getModifiers() != 0 && - evt.getModifiers() != InputEvent.SHIFT_MASK) - return; - // 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); + selModel.setSelectionInterval(selModel.getAnchorSelectionIndex(), + lead); } - else if ((evt.getKeyCode() == KeyEvent.VK_A || evt.getKeyCode() - == KeyEvent.VK_SLASH) && (evt.getModifiers() == - InputEvent.CTRL_MASK)) + else if (command.equals("toggleAndAnchor")) { - BasicListUI.this.list.setSelectionInterval(0, max); - // this next line is to restore the lead selection index to the old - // position, because select-all should not change the lead index - BasicListUI.this.list.addSelectionInterval(lead, lead); + if (!list.isSelectedIndex(lead)) + list.addSelectionInterval(lead, lead); + else + list.removeSelectionInterval(lead, lead); + selModel.setAnchorSelectionIndex(lead); } - else if (evt.getKeyCode() == KeyEvent.VK_SPACE && - (evt.getModifiers() == InputEvent.CTRL_MASK)) + else { - BasicListUI.this.list.getSelectionModel(). - setLeadSelectionIndex(Math.min(lead+1,max)); + // DEBUG: uncomment the following line to print out + // key bindings that aren't implemented yet + + // System.out.println ("not implemented: "+e.getActionCommand()); } - - BasicListUI.this.list.ensureIndexIsVisible - (BasicListUI.this.list.getLeadSelectionIndex()); + + list.ensureIndexIsVisible(list.getLeadSelectionIndex()); } } - + /** * A helper class which listens for {@link MouseEvent}s * from the {@link JList}. @@ -333,48 +430,46 @@ public class BasicListUI extends ListUI public void mouseClicked(MouseEvent event) { Point click = event.getPoint(); - int index = BasicListUI.this.locationToIndex(list, click); + int index = locationToIndex(list, click); if (index == -1) return; if (event.isShiftDown()) { - if (BasicListUI.this.list.getSelectionMode() == - ListSelectionModel.SINGLE_SELECTION) - BasicListUI.this.list.setSelectedIndex(index); - else if (BasicListUI.this.list.getSelectionMode() == + if (list.getSelectionMode() == ListSelectionModel.SINGLE_SELECTION) + list.setSelectedIndex(index); + else if (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); + list.setSelectionInterval(list.getAnchorSelectionIndex(), index); else // COMPAT: both Sun and IBM are compatible instead with: - // BasicListUI.this.list.setSelectionInterval - // (BasicListUI.this.list.getLeadSelectionIndex(),index); + // list.setSelectionInterval + // (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); + if (list.isSelectedIndex(list.getAnchorSelectionIndex())) + list.getSelectionModel().setLeadSelectionIndex(index); + else + list.addSelectionInterval(list.getAnchorSelectionIndex(), index); } else 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); + if (list.getSelectionMode() == ListSelectionModel.SINGLE_SELECTION) + list.setSelectedIndex(index); + else if (list.isSelectedIndex(index)) + list.removeSelectionInterval(index,index); else - BasicListUI.this.list.addSelectionInterval(index,index); + list.addSelectionInterval(index,index); } else - BasicListUI.this.list.setSelectedIndex(index); + list.setSelectedIndex(index); - BasicListUI.this.list.ensureIndexIsVisible - (BasicListUI.this.list.getLeadSelectionIndex()); + list.ensureIndexIsVisible(list.getLeadSelectionIndex()); } /** @@ -385,6 +480,7 @@ public class BasicListUI extends ListUI */ public void mousePressed(MouseEvent event) { + // TODO: What should be done here, if anything? } /** @@ -395,6 +491,7 @@ public class BasicListUI extends ListUI */ public void mouseReleased(MouseEvent event) { + // TODO: What should be done here, if anything? } /** @@ -405,6 +502,7 @@ public class BasicListUI extends ListUI */ public void mouseEntered(MouseEvent event) { + // TODO: What should be done here, if anything? } /** @@ -415,6 +513,7 @@ public class BasicListUI extends ListUI */ public void mouseExited(MouseEvent event) { + // TODO: What should be done here, if anything? } /** @@ -425,6 +524,7 @@ public class BasicListUI extends ListUI */ public void mouseDragged(MouseEvent event) { + // TODO: What should be done here, if anything? } /** @@ -435,6 +535,7 @@ public class BasicListUI extends ListUI */ public void mouseMoved(MouseEvent event) { + // TODO: What should be done here, if anything? } } @@ -459,11 +560,61 @@ public class BasicListUI extends ListUI if (e.getNewValue() != null && e.getNewValue() instanceof ListModel) ((ListModel) e.getNewValue()).addListDataListener(BasicListUI.this.listDataListener); } + // Update the updateLayoutStateNeeded flag. + if (e.getPropertyName().equals("model")) + updateLayoutStateNeeded += modelChanged; + else if (e.getPropertyName().equals("selectionModel")) + updateLayoutStateNeeded += selectionModelChanged; + else if (e.getPropertyName().equals("font")) + updateLayoutStateNeeded += fontChanged; + else if (e.getPropertyName().equals("fixedCellWidth")) + updateLayoutStateNeeded += fixedCellWidthChanged; + else if (e.getPropertyName().equals("fixedCellHeight")) + updateLayoutStateNeeded += fixedCellHeightChanged; + else if (e.getPropertyName().equals("prototypeCellValue")) + updateLayoutStateNeeded += prototypeCellValueChanged; + else if (e.getPropertyName().equals("cellRenderer")) + updateLayoutStateNeeded += cellRendererChanged; BasicListUI.this.damageLayout(); } } /** + * A constant to indicate that the model has changed. + */ + protected static final int modelChanged = 1; + + /** + * A constant to indicate that the selection model has changed. + */ + protected static final int selectionModelChanged = 2; + + /** + * A constant to indicate that the font has changed. + */ + protected static final int fontChanged = 4; + + /** + * A constant to indicate that the fixedCellWidth has changed. + */ + protected static final int fixedCellWidthChanged = 8; + + /** + * A constant to indicate that the fixedCellHeight has changed. + */ + protected static final int fixedCellHeightChanged = 16; + + /** + * A constant to indicate that the prototypeCellValue has changed. + */ + protected static final int prototypeCellValueChanged = 32; + + /** + * A constant to indicate that the cellRenderer has changed. + */ + protected static final int cellRendererChanged = 64; + + /** * Creates a new BasicListUI for the component. * * @param c The component to create a UI for @@ -487,9 +638,6 @@ public class BasicListUI extends ListUI /** 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; @@ -501,7 +649,11 @@ public class BasicListUI extends ListUI /** Saved reference to the list this UI was created for. */ protected JList list; - /** The height of a single cell in the list. */ + /** + * The height of a single cell in the list. This field is used when the + * fixedCellHeight property of the list is set. Otherwise this field is + * set to <code>-1</code> and {@link #cellHeights} is used instead. + */ protected int cellHeight; /** The width of a single cell in the list. */ @@ -509,14 +661,25 @@ public class BasicListUI extends ListUI /** * An array of varying heights of cells in the list, in cases where each - * cell might have a different height. + * cell might have a different height. This field is used when the + * <code>fixedCellHeight</code> property of the list is not set. Otherwise + * this field is <code>null</code> and {@link #cellHeight} is used. */ protected int[] cellHeights; /** - * A simple counter. When nonzero, indicates that the UI class is out of + * A bitmask that indicates which properties of the JList have changed. + * 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. + * + * @see #modelChanged + * @see #selectionModelChanged + * @see #fontChanged + * @see #fixedCellWidthChanged + * @see #fixedCellHeightChanged + * @see #prototypeCellValueChanged + * @see #cellRendererChanged */ protected int updateLayoutStateNeeded; @@ -524,6 +687,9 @@ public class BasicListUI extends ListUI * The {@link CellRendererPane} that is used for painting. */ protected CellRendererPane rendererPane; + + /** The action bound to KeyStrokes. */ + ListAction action; /** * Calculate the height of a particular row. If there is a fixed {@link @@ -611,19 +777,51 @@ public class BasicListUI extends ListUI * @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 + * if the list model is empty + * + * @specnote This method is specified to return -1 for an invalid Y + * coordinate. However, some simple tests show that the behaviour + * is to return the index of the last list element for an Y + * coordinate that lies outside of the list bounds (even for + * negative indices). <code>-1</code> + * is only returned if the list model is empty. */ protected int convertYToRow(int y0) { - for (int row = 0; row < cellHeights.length; ++row) - { - int h = getRowHeight(row); + if (list.getModel().getSize() == 0) + return -1; + + // When y0 < 0, then the JDK returns the maximum row index of the list. So + // do we. + if (y0 < 0) + return list.getModel().getSize() - 1; + + // Update the layout if necessary. + maybeUpdateLayoutState(); + + int index = list.getModel().getSize() - 1;; - if (y0 < h) - return row; - y0 -= h; + // If a fixed cell height is set, then we can work more efficient. + if (cellHeight > 0) + { + index = Math.max(y0 / cellHeight, index); + } + // If we have no fixed cell height, we must add up each cell height up + // to y0. + else + { + int h = 0; + for (int row = 0; row < cellHeights.length; ++row) + { + h += cellHeights[row]; + if (y0 < h) + { + index = row; + break; + } + } } - return -1; + return index; } /** @@ -638,29 +836,47 @@ public class BasicListUI extends ListUI cellWidth = -1; if (cellHeights == null || cellHeights.length != nrows) cellHeights = new int[nrows]; - if (list.getFixedCellHeight() == -1 || list.getFixedCellWidth() == -1) + ListCellRenderer rend = list.getCellRenderer(); + // Update the cellHeight(s) fields. + int fixedCellHeight = list.getFixedCellHeight(); + if (fixedCellHeight > 0) + { + cellHeight = fixedCellHeight; + cellHeights = null; + } + else { - ListCellRenderer rend = list.getCellRenderer(); + cellHeight = -1; for (int i = 0; i < nrows; ++i) { - Component flyweight = rend.getListCellRendererComponent(list, - list.getModel() - .getElementAt(i), - 0, false, - false); + Component flyweight = + rend.getListCellRendererComponent(list, + list.getModel().getElementAt(i), + i, list.isSelectedIndex(i), + list.getSelectionModel().getAnchorSelectionIndex() == i); 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); } } + + // Update the cellWidth field. + int fixedCellWidth = list.getFixedCellWidth(); + if (fixedCellWidth > 0) + cellWidth = fixedCellWidth; else { - cellHeight = list.getFixedCellHeight(); - cellWidth = list.getFixedCellWidth(); + for (int i = 0; i < nrows; ++i) + { + Component flyweight = + rend.getListCellRendererComponent(list, + list.getModel().getElementAt(i), + i, list.isSelectedIndex(i), + list.getSelectionModel().getAnchorSelectionIndex() == i); + Dimension dim = flyweight.getPreferredSize(); + cellWidth = Math.max(cellWidth, dim.width); + } + if (list.getLayoutOrientation() == JList.VERTICAL) + cellWidth = Math.max(cellWidth, list.getSize().width); } } @@ -694,13 +910,6 @@ public class BasicListUI extends ListUI */ 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(); } @@ -713,11 +922,10 @@ public class BasicListUI extends ListUI */ 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")); + LookAndFeel.installColorsAndFont(list, "List.background", + "List.foreground", "List.font"); + list.setSelectionForeground(UIManager.getColor("List.selectionForeground")); + list.setSelectionBackground(UIManager.getColor("List.selectionBackground")); list.setOpaque(true); } @@ -727,7 +935,6 @@ public class BasicListUI extends ListUI */ protected void uninstallDefaults() { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); list.setForeground(null); list.setBackground(null); list.setSelectionForeground(null); @@ -742,14 +949,28 @@ public class BasicListUI extends ListUI */ protected void installListeners() { + if (focusListener == null) + focusListener = createFocusListener(); list.addFocusListener(focusListener); + if (listDataListener == null) + listDataListener = createListDataListener(); list.getModel().addListDataListener(listDataListener); + if (listSelectionListener == null) + listSelectionListener = createListSelectionListener(); list.addListSelectionListener(listSelectionListener); + if (mouseInputListener == null) + mouseInputListener = createMouseInputListener(); list.addMouseListener(mouseInputListener); - list.addKeyListener(keyListener); list.addMouseMotionListener(mouseInputListener); + if (propertyChangeListener == null) + propertyChangeListener = createPropertyChangeListener(); list.addPropertyChangeListener(propertyChangeListener); + + // FIXME: Are these two really needed? At least they are not documented. + //keyListener = new KeyHandler(); + componentListener = new ComponentHandler(); list.addComponentListener(componentListener); + //list.addKeyListener(keyListener); } /** @@ -761,16 +982,41 @@ public class BasicListUI extends ListUI list.getModel().removeListDataListener(listDataListener); list.removeListSelectionListener(listSelectionListener); list.removeMouseListener(mouseInputListener); - list.removeKeyListener(keyListener); + //list.removeKeyListener(keyListener); list.removeMouseMotionListener(mouseInputListener); list.removePropertyChangeListener(propertyChangeListener); } - + /** * Installs keyboard actions for this UI in the {@link JList}. */ protected void installKeyboardActions() { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + InputMap focusInputMap = (InputMap)defaults.get("List.focusInputMap"); + InputMapUIResource parentInputMap = new InputMapUIResource(); + // FIXME: The JDK uses a LazyActionMap for parentActionMap + ActionMap parentActionMap = new ActionMapUIResource(); + action = new ListAction(); + Object keys[] = focusInputMap.allKeys(); + // Register key bindings in the UI InputMap-ActionMap pair + for (int i = 0; i < keys.length; i++) + { + KeyStroke stroke = (KeyStroke)keys[i]; + String actionString = (String) focusInputMap.get(stroke); + parentInputMap.put(KeyStroke.getKeyStroke(stroke.getKeyCode(), + stroke.getModifiers()), + actionString); + + parentActionMap.put (actionString, + new ActionListenerProxy(action, actionString)); + } + // Register the new InputMap-ActionMap as the parents of the list's + // InputMap and ActionMap + parentInputMap.setParent(list.getInputMap().getParent()); + parentActionMap.setParent(list.getActionMap().getParent()); + list.getInputMap().setParent(parentInputMap); + list.getActionMap().setParent(parentActionMap); } /** @@ -778,6 +1024,7 @@ public class BasicListUI extends ListUI */ protected void uninstallKeyboardActions() { + // TODO: Implement this properly. } /** @@ -855,22 +1102,6 @@ public class BasicListUI extends ListUI } /** - * 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 @@ -892,14 +1123,12 @@ public class BasicListUI extends ListUI Component comp = rend.getListCellRendererComponent(list, data.getElementAt(row), 0, isSel, hasFocus); - //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. + * Paints the list by 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 @@ -916,9 +1145,12 @@ public class BasicListUI extends ListUI ListSelectionModel sel = list.getSelectionModel(); int lead = sel.getLeadSelectionIndex(); Rectangle clip = g.getClipBounds(); - paintBackground(g, list); - for (int row = 0; row < nrows; ++row) + int startIndex = list.locationToIndex(new Point(clip.x, clip.y)); + int endIndex = list.locationToIndex(new Point(clip.x + clip.width, + clip.y + clip.height)); + + for (int row = startIndex; row <= endIndex; ++row) { Rectangle bounds = getCellBounds(list, row, row); if (bounds.intersects(clip)) @@ -927,13 +1159,15 @@ public class BasicListUI extends ListUI } /** - * Computes the index of a list cell given a point within the list. + * Computes the index of a list cell given a point within the list. If the + * location lies outside the bounds of the list, the greatest index in the + * list model is returned. * * @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 + * coordinates or <code>-1</code> if the list model is empty */ public int locationToIndex(JList list, Point location) { @@ -983,7 +1217,6 @@ public class BasicListUI extends ListUI 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; @@ -1045,4 +1278,82 @@ public class BasicListUI extends ListUI } return loc; } + + /** + * Creates and returns the focus listener for this UI. + * + * @return the focus listener for this UI + */ + protected FocusListener createFocusListener() + { + return new FocusHandler(); + } + + /** + * Creates and returns the list data listener for this UI. + * + * @return the list data listener for this UI + */ + protected ListDataListener createListDataListener() + { + return new ListDataHandler(); + } + + /** + * Creates and returns the list selection listener for this UI. + * + * @return the list selection listener for this UI + */ + protected ListSelectionListener createListSelectionListener() + { + return new ListSelectionHandler(); + } + + /** + * Creates and returns the mouse input listener for this UI. + * + * @return the mouse input listener for this UI + */ + protected MouseInputListener createMouseInputListener() + { + return new MouseInputHandler(); + } + + /** + * Creates and returns the property change listener for this UI. + * + * @return the property change listener for this UI + */ + protected PropertyChangeListener createPropertyChangeListener() + { + return new PropertyChangeHandler(); + } + + /** + * Selects the next list item and force it to be visible. + */ + protected void selectNextIndex() + { + int index = list.getSelectionModel().getLeadSelectionIndex(); + if (index < list.getModel().getSize() - 1) + { + index++; + list.setSelectedIndex(index); + } + list.ensureIndexIsVisible(index); + } + + /** + * Selects the previous list item and force it to be visible. + */ + protected void selectPreviousIndex() + { + int index = list.getSelectionModel().getLeadSelectionIndex(); + if (index > 0) + { + index--; + list.setSelectedIndex(index); + } + list.ensureIndexIsVisible(index); + } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicLookAndFeel.java b/libjava/classpath/javax/swing/plaf/basic/BasicLookAndFeel.java index d35ac9e..8ebe650 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicLookAndFeel.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicLookAndFeel.java @@ -273,7 +273,7 @@ public abstract class BasicLookAndFeel extends LookAndFeel "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.margin", new InsetsUIResource(2, 14, 2, 14), "Button.shadow", new ColorUIResource(Color.GRAY), "Button.textIconGap", new Integer(4), "Button.textShiftOffset", new Integer(0), @@ -362,16 +362,16 @@ public abstract class BasicLookAndFeel extends LookAndFeel "HOME", "homePassThrough", "END", "endPassThrough" }), - "ComboBox.background", new ColorUIResource(light), + "ComboBox.background", new ColorUIResource(Color.white), "ComboBox.buttonBackground", new ColorUIResource(light), - "ComboBox.buttonDarkShadow", new ColorUIResource(shadow), + "ComboBox.buttonDarkShadow", new ColorUIResource(darkShadow), "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.selectionBackground", new ColorUIResource(0, 0, 128), "ComboBox.selectionForeground", new ColorUIResource(Color.white), "Desktop.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { "KP_LEFT", "left", @@ -397,7 +397,7 @@ public abstract class BasicLookAndFeel extends LookAndFeel "DesktopIcon.border", new BorderUIResource.CompoundBorderUIResource(null, null), "EditorPane.background", new ColorUIResource(Color.white), - "EditorPane.border", new BasicBorders.MarginBorder(), + "EditorPane.border", BasicBorders.getMarginBorder(), "EditorPane.caretBlinkRate", new Integer(500), "EditorPane.caretForeground", new ColorUIResource(Color.black), "EditorPane.font", new FontUIResource("Serif", Font.PLAIN, 12), @@ -466,6 +466,8 @@ public abstract class BasicLookAndFeel extends LookAndFeel "FocusManagerClassName", "TODO", "FormattedTextField.background", new ColorUIResource(light), "FormattedTextField.caretForeground", new ColorUIResource(Color.black), + "FormattedTextField.font", + new FontUIResource("SansSerif", Font.PLAIN, 12), "FormattedTextField.foreground", new ColorUIResource(Color.black), "FormattedTextField.inactiveBackground", new ColorUIResource(light), "FormattedTextField.inactiveForeground", new ColorUIResource(Color.gray), @@ -528,30 +530,74 @@ public abstract class BasicLookAndFeel extends LookAndFeel "Label.disabledShadow", new ColorUIResource(shadow), "Label.font", new FontUIResource("Dialog", Font.PLAIN, 12), "Label.foreground", new ColorUIResource(darkShadow), - "List.background", new ColorUIResource(light), + "List.background", new ColorUIResource(Color.white), "List.border", new BasicBorders.MarginBorder(), "List.focusInputMap", new UIDefaults.LazyInputMap(new Object[] { - "PAGE_UP", "scrollUp", - "ctrl \\", "clearSelection", - "PAGE_DOWN", "scrollDown", - "shift PAGE_DOWN","scrollDownExtendSelection", + "ctrl DOWN", "selectNextRowChangeLead", + "shift UP", "selectPreviousRowExtendSelection", + "ctrl RIGHT", "selectNextColumnChangeLead", + "shift ctrl LEFT", "selectPreviousColumnExtendSelection", + "shift KP_UP", "selectPreviousRowChangeLead", + "DOWN", "selectNextRow", + "ctrl UP", "selectPreviousRowChangeLead", + "ctrl LEFT", "selectPreviousColumnChangeLead", + "CUT", "cut", "END", "selectLastRow", - "HOME", "selectFirstRow", - "shift END", "selectLastRowExtendSelection", + "shift PAGE_UP","scrollUpExtendSelection", + "KP_UP", "selectPreviousRow", + "shift ctrl UP", "selectPreviousRowExtendSelection", + "ctrl HOME", "selectFirstRowChangeLead", + "shift LEFT", "selectPreviousColumnExtendSelection", + "ctrl END", "selectLastRowChangeLead", + "ctrl PAGE_DOWN", "scrollDownChangeLead", + "shift ctrl RIGHT", "selectNextColumnExtendSelection", + "LEFT", "selectPreviousColumn", + "ctrl PAGE_UP", "scrollUpChangeLead", + "KP_LEFT", "selectPreviousColumn", + "shift KP_RIGHT", "selectNextColumnExtendSelection", + "SPACE", "addToSelection", + "ctrl SPACE", "toggleAndAnchor", + "shift SPACE", "extendTo", + "shift ctrl SPACE", "moveSelectionTo", + "shift ctrl DOWN", "selectNextRowExtendSelection", + "ctrl BACK_SLASH", "clearSelection", "shift HOME", "selectFirstRowExtendSelection", - "UP", "selectPreviousRow", - "ctrl /", "selectAll", - "ctrl A", "selectAll", - "DOWN", "selectNextRow", - "shift UP", "selectPreviousRowExtendSelection", - "ctrl SPACE", "selectNextRowExtendSelection", + "RIGHT", "selectNextColumn", + "shift ctrl PAGE_UP", "scrollUpExtendSelection", "shift DOWN", "selectNextRowExtendSelection", - "KP_UP", "selectPreviousRow", - "shift PAGE_UP","scrollUpExtendSelection", - "KP_DOWN", "selectNextRow" + "PAGE_DOWN", "scrollDown", + "shift ctrl KP_UP", "selectPreviousRowExtendSelection", + "shift KP_LEFT", "selectPreviousColumnExtendSelection", + "ctrl X", "cut", + "shift ctrl PAGE_DOWN", "scrollDownExtendSelection", + "ctrl SLASH", "selectAll", + "ctrl C", "copy", + "ctrl KP_RIGHT", "selectNextColumnChangeLead", + "shift END", "selectLastRowExtendSelection", + "shift ctrl KP_DOWN", "selectNextRowExtendSelection", + "ctrl KP_LEFT", "selectPreviousColumnChangeLead", + "HOME", "selectFirstRow", + "ctrl V", "paste", + "KP_DOWN", "selectNextRow", + "ctrl KP_DOWN", "selectNextRowChangeLead", + "shift RIGHT", "selectNextColumnExtendSelection", + "ctrl A", "selectAll", + "shift ctrl END", "selectLastRowExtendSelection", + "COPY", "copy", + "ctrl KP_UP", "selectPreviousRowChangeLead", + "shift ctrl KP_LEFT", "selectPreviousColumnExtendSelection", + "shift KP_DOWN", "selectNextRowExtendSelection", + "UP", "selectPreviousRow", + "shift ctrl HOME", "selectFirstRowExtendSelection", + "shift PAGE_DOWN", "scrollDownExtendSelection", + "KP_RIGHT", "selectNextColumn", + "shift ctrl KP_RIGHT", "selectNextColumnExtendSelection", + "PAGE_UP", "scrollUp", + "PASTE", "paste" }), - "List.foreground", new ColorUIResource(darkShadow), - "List.selectionBackground", new ColorUIResource(Color.black), + "List.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "List.foreground", new ColorUIResource(Color.black), + "List.selectionBackground", new ColorUIResource(0, 0, 128), "List.selectionForeground", new ColorUIResource(Color.white), "List.focusCellHighlightBorder", new BorderUIResource. @@ -601,7 +647,6 @@ public abstract class BasicLookAndFeel extends LookAndFeel "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), @@ -624,7 +669,9 @@ public abstract class BasicLookAndFeel extends LookAndFeel "OptionPane.messageAreaBorder", new BorderUIResource.EmptyBorderUIResource(0, 0, 0, 0), "OptionPane.messageForeground", new ColorUIResource(darkShadow), - "OptionPane.minimumSize", new DimensionUIResource(262, 90), + "OptionPane.minimumSize", + new DimensionUIResource(BasicOptionPaneUI.MinimumWidth, + BasicOptionPaneUI.MinimumHeight), "OptionPane.noButtonText", "No", "OptionPane.okButtonText", "OK", // XXX Don't use gif @@ -660,16 +707,17 @@ public abstract class BasicLookAndFeel extends LookAndFeel "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.background", new ColorUIResource(Color.LIGHT_GRAY), + "ProgressBar.border", + new BorderUIResource.LineBorderUIResource(Color.GREEN, 2), "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), + "ProgressBar.foreground", new ColorUIResource(0, 0, 128), + "ProgressBar.selectionBackground", new ColorUIResource(0, 0, 128), + "ProgressBar.selectionForeground", new ColorUIResource(Color.LIGHT_GRAY), + "ProgressBar.repaintInterval", new Integer(50), + "ProgressBar.cycleTime", new Integer(3000), "RadioButton.background", new ColorUIResource(light), "RadioButton.border", new BorderUIResource.CompoundBorderUIResource(null, null), @@ -742,6 +790,7 @@ public abstract class BasicLookAndFeel extends LookAndFeel "ScrollBar.thumbShadow", new ColorUIResource(shadow), "ScrollBar.track", new ColorUIResource(light), "ScrollBar.trackHighlight", new ColorUIResource(shadow), + "ScrollBar.width", new Integer(16), "ScrollPane.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { "PAGE_UP", "scrollUp", "KP_LEFT", "unitScrollLeft", @@ -846,6 +895,24 @@ public abstract class BasicLookAndFeel extends LookAndFeel "TabbedPane.tabRunOverlay", new Integer(2), "TabbedPane.textIconGap", new Integer(4), "Table.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { + "ctrl DOWN", "selectNextRowChangeLead", + "ctrl RIGHT", "selectNextColumnChangeLead", + "ctrl UP", "selectPreviousRowChangeLead", + "ctrl LEFT", "selectPreviousColumnChangeLead", + "CUT", "cut", + "SPACE", "addToSelection", + "ctrl SPACE", "toggleAndAnchor", + "shift SPACE", "extendTo", + "shift ctrl SPACE", "moveSelectionTo", + "ctrl X", "cut", + "ctrl C", "copy", + "ctrl KP_RIGHT", "selectNextColumnChangeLead", + "ctrl KP_LEFT", "selectPreviousColumnChangeLead", + "ctrl V", "paste", + "ctrl KP_DOWN", "selectNextRowChangeLead", + "COPY", "copy", + "ctrl KP_UP", "selectPreviousRowChangeLead", + "PASTE", "paste", "shift PAGE_DOWN","scrollDownExtendSelection", "PAGE_DOWN", "scrollDownChangeSelection", "END", "selectLastColumn", @@ -896,25 +963,26 @@ public abstract class BasicLookAndFeel extends LookAndFeel "ctrl SLASH", "selectAll", "ctrl shift KP_DOWN", "selectNextRowExtendSelection", }), - "Table.background", new ColorUIResource(light), - "Table.focusCellBackground", new ColorUIResource(light), - "Table.focusCellForeground", new ColorUIResource(darkShadow), + "Table.background", new ColorUIResource(new ColorUIResource(255, 255, 255)), + "Table.focusCellBackground", new ColorUIResource(new ColorUIResource(255, 255, 255)), + "Table.focusCellForeground", new ColorUIResource(new ColorUIResource(0, 0, 0)), "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.foreground", new ColorUIResource(new ColorUIResource(0, 0, 0)), + "Table.gridColor", new ColorUIResource(new ColorUIResource(128, 128, 128)), "Table.scrollPaneBorder", new BorderUIResource.BevelBorderUIResource(0), - "Table.selectionBackground", new ColorUIResource(Color.black), - "Table.selectionForeground", new ColorUIResource(Color.white), - "TableHeader.background", new ColorUIResource(light), + "Table.selectionBackground", new ColorUIResource(new ColorUIResource(0, 0, 128)), + "Table.selectionForeground", new ColorUIResource(new ColorUIResource(255, 255, 255)), + "TableHeader.background", new ColorUIResource(new ColorUIResource(192, 192, 192)), "TableHeader.cellBorder", new BorderUIResource.BevelBorderUIResource(0), "TableHeader.font", new FontUIResource("Dialog", Font.PLAIN, 12), - "TableHeader.foreground", new ColorUIResource(darkShadow), + "TableHeader.foreground", new ColorUIResource(new ColorUIResource(0, 0, 0)), "TextArea.background", new ColorUIResource(light), - "TextArea.border", new BasicBorders.MarginBorder(), + "TextArea.border", + new BorderUIResource(BasicBorders.getMarginBorder()), "TextArea.caretBlinkRate", new Integer(500), "TextArea.caretForeground", new ColorUIResource(Color.black), "TextArea.font", new FontUIResource("MonoSpaced", Font.PLAIN, 12), @@ -945,8 +1013,8 @@ public abstract class BasicLookAndFeel extends LookAndFeel "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.inactiveBackground", new ColorUIResource(Color.LIGHT_GRAY), + "TextField.inactiveForeground", new ColorUIResource(Color.GRAY), "TextField.light", new ColorUIResource(highLight), "TextField.highlight", new ColorUIResource(light), "TextField.keyBindings", new JTextComponent.KeyBinding[] { @@ -964,7 +1032,7 @@ public abstract class BasicLookAndFeel extends LookAndFeel "TextField.selectionBackground", new ColorUIResource(Color.black), "TextField.selectionForeground", new ColorUIResource(Color.white), "TextPane.background", new ColorUIResource(Color.white), - "TextPane.border", new BasicBorders.MarginBorder(), + "TextPane.border", BasicBorders.getMarginBorder(), "TextPane.caretBlinkRate", new Integer(500), "TextPane.caretForeground", new ColorUIResource(Color.black), "TextPane.font", new FontUIResource("Serif", Font.PLAIN, 12), @@ -1036,7 +1104,7 @@ public abstract class BasicLookAndFeel extends LookAndFeel "Tree.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] { "ESCAPE", "cancel" }), - "Tree.background", new ColorUIResource(light), + "Tree.background", new ColorUIResource(new Color(255, 255, 255)), "Tree.changeSelectionWithFocus", Boolean.TRUE, // "Tree.closedIcon", new IconUIResource(new ImageIcon("icons/TreeClosed.png")), // "Tree.collapsedIcon", new IconUIResource(new ImageIcon("icons/TreeCollapsed.png")), @@ -1086,20 +1154,20 @@ public abstract class BasicLookAndFeel extends LookAndFeel "PAGE_UP", "scrollUpChangeSelection", "ctrl PAGE_DOWN", "scrollDownChangeLead" }), - "Tree.font", new FontUIResource(new Font("Helvetica", Font.PLAIN, 12)), + "Tree.font", new FontUIResource("Dialog", 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.rowHeight", new Integer(16), "Tree.scrollsOnExpand", Boolean.TRUE, "Tree.selectionBackground", new ColorUIResource(Color.black), - "Tree.nonSelectionBackground", new ColorUIResource(new Color(239, 235, 231)), + "Tree.nonSelectionBackground", new ColorUIResource(new Color(255, 255, 255)), "Tree.selectionBorderColor", new ColorUIResource(Color.black), "Tree.selectionBorder", new BorderUIResource.LineBorderUIResource(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), + "Tree.textBackground", new ColorUIResource(new Color(192, 192, 192)), + "Tree.textForeground", new ColorUIResource(new Color(0, 0, 0)), "Viewport.background", new ColorUIResource(light), "Viewport.foreground", new ColorUIResource(Color.black), "Viewport.font", new FontUIResource("Dialog", Font.PLAIN, 12) diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicMenuBarUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicMenuBarUI.java index 95f6b84..daa9b0d 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicMenuBarUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicMenuBarUI.java @@ -41,16 +41,19 @@ package javax.swing.plaf.basic; import java.awt.Dimension; import java.awt.event.ContainerEvent; import java.awt.event.ContainerListener; +import java.awt.event.MouseEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.BoxLayout; import javax.swing.JComponent; +import javax.swing.JMenu; import javax.swing.JMenuBar; -import javax.swing.UIDefaults; -import javax.swing.UIManager; +import javax.swing.LookAndFeel; +import javax.swing.MenuElement; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; +import javax.swing.event.MouseInputListener; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.MenuBarUI; @@ -63,12 +66,15 @@ public class BasicMenuBarUI extends MenuBarUI /*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; + + /* MouseListener that listens to the mouseEvents fired from menu bar*/ + private MouseInputListener mouseListener; /** * Creates a new BasicMenuBarUI object. @@ -78,6 +84,7 @@ public class BasicMenuBarUI extends MenuBarUI changeListener = createChangeListener(); containerListener = createContainerListener(); propertyChangeListener = new PropertyChangeHandler(); + mouseListener = new MouseInputHandler(); } /** @@ -159,12 +166,9 @@ public class BasicMenuBarUI extends MenuBarUI */ 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")); + LookAndFeel.installBorder(menuBar, "MenuBar.border"); + LookAndFeel.installColorsAndFont(menuBar, "MenuBar.background", + "MenuBar.foreground", "MenuBar.font"); menuBar.setOpaque(true); } @@ -183,6 +187,7 @@ public class BasicMenuBarUI extends MenuBarUI { menuBar.addContainerListener(containerListener); menuBar.addPropertyChangeListener(propertyChangeListener); + menuBar.addMouseListener(mouseListener); } /** @@ -229,6 +234,7 @@ public class BasicMenuBarUI extends MenuBarUI { menuBar.removeContainerListener(containerListener); menuBar.removePropertyChangeListener(propertyChangeListener); + menuBar.removeMouseListener(mouseListener); } /** @@ -250,6 +256,7 @@ public class BasicMenuBarUI extends MenuBarUI { public void stateChanged(ChangeEvent event) { + // TODO: What should be done here, if anything? } } @@ -301,4 +308,84 @@ public class BasicMenuBarUI extends MenuBarUI menuBar.repaint(); } } + + private class MouseInputHandler implements MouseInputListener + { + /** + * Handles mouse clicked event + * + * @param e Mouse event + */ + public void mouseClicked(MouseEvent e) + { + MenuElement[] me = menuBar.getSubElements(); + + for (int i = 0; i < me.length; i++) + { + JMenu menu = menuBar.getMenu(i); + if (menu != null) + menu.setSelected(false); + } + } + + /** + * Handles mouse pressed event + * + * @param e Mouse event + */ + public void mousePressed(MouseEvent e) + { + // TODO: What should be done here, if anything? + } + + /** + * Handles mouse released event + * + * @param e Mouse event + */ + public void mouseReleased(MouseEvent e) + { + // TODO: What should be done here, if anything? + } + + /** + * Handles mouse exited event + * + * @param e Mouse event + */ + public void mouseExited(MouseEvent e) + { + // TODO: What should be done here, if anything? + } + + /** + * Handles mouse dragged event + * + * @param e Mouse event + */ + public void mouseDragged(MouseEvent e) + { + // TODO: What should be done here, if anything? + } + + /** + * Handles mouse moved event + * + * @param e Mouse event + */ + public void mouseMoved(MouseEvent e) + { + // TODO: What should be done here, if anything? + } + + /** + * Handles mouse entered event + * + * @param e Mouse event + */ + public void mouseEntered(MouseEvent e) + { + // TODO: What should be done here, if anything? + } + } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicMenuItemUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicMenuItemUI.java index 8aa1193..2a3556a 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicMenuItemUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicMenuItemUI.java @@ -7,7 +7,7 @@ GNU Classpath is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. - + GNU Classpath is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU @@ -46,18 +46,27 @@ import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Insets; import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; 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.AbstractAction; +import javax.swing.ActionMap; +import javax.swing.ButtonModel; import javax.swing.Icon; +import javax.swing.InputMap; +import javax.swing.JCheckBoxMenuItem; import javax.swing.JComponent; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; import javax.swing.KeyStroke; +import javax.swing.LookAndFeel; import javax.swing.MenuElement; import javax.swing.MenuSelectionManager; import javax.swing.SwingConstants; @@ -69,6 +78,8 @@ import javax.swing.event.MenuDragMouseListener; import javax.swing.event.MenuKeyEvent; import javax.swing.event.MenuKeyListener; import javax.swing.event.MouseInputListener; +import javax.swing.plaf.ActionMapUIResource; +import javax.swing.plaf.ComponentInputMapUIResource; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.MenuItemUI; @@ -109,7 +120,7 @@ public class BasicMenuItemUI extends MenuItemUI * Number of spaces between icon and text. */ protected int defaultTextIconGap = 4; - + /** * Color of the text when menu item is disabled */ @@ -156,16 +167,69 @@ public class BasicMenuItemUI extends MenuItemUI private String acceleratorDelimiter; /** - * PropertyChangeListener to listen for property changes in the menu item + * ItemListener to listen for item changes in the menu item */ - private PropertyChangeListener propertyChangeListener; + private ItemListener itemListener; /** * Number of spaces between accelerator and menu item's label. */ - private int defaultAcceleratorLabelGap = 4; + private int defaultAcceleratorLabelGap = 10; /** + * The gap between different menus on the MenuBar. + */ + private int MenuGap = 10; + + /** A PropertyChangeListener to make UI updates after property changes **/ + PropertyChangeHandler propertyChangeListener; + + /** + * A class to handle PropertChangeEvents for the JMenuItem + * @author Anthony Balkissoon abalkiss at redhat dot com. + */ + class PropertyChangeHandler implements PropertyChangeListener + { + /** + * This method is called when a property of the menuItem is changed. + * Currently it is only used to update the accelerator key bindings. + * + * @param e + * the PropertyChangeEvent + */ + public void propertyChange(PropertyChangeEvent e) + { + if (e.getPropertyName() == "accelerator") + { + InputMap map = SwingUtilities.getUIInputMap(menuItem, JComponent.WHEN_IN_FOCUSED_WINDOW); + if (map != null) + map.remove((KeyStroke)e.getOldValue()); + else + map = new ComponentInputMapUIResource(menuItem); + map.put((KeyStroke)e.getNewValue(), "doClick"); + } + } + } + + /** + * A class to handle accelerator keys. This is the Action we will + * perform when the accelerator key for this JMenuItem is pressed. + * @author Anthony Balkissoon abalkiss at redhat dot com + * + */ + class ClickAction extends AbstractAction + { + /** + * This is what is done when the accelerator key for the JMenuItem is + * pressed. + */ + public void actionPerformed(ActionEvent event) + { + doClick(MenuSelectionManager.defaultManager()); + } + } + + /** * Creates a new BasicMenuItemUI object. */ public BasicMenuItemUI() @@ -173,14 +237,15 @@ public class BasicMenuItemUI extends MenuItemUI mouseInputListener = createMouseInputListener(menuItem); menuDragMouseListener = createMenuDragMouseListener(menuItem); menuKeyListener = createMenuKeyListener(menuItem); + itemListener = new ItemHandler(); propertyChangeListener = new PropertyChangeHandler(); } /** * Create MenuDragMouseListener to listen for mouse dragged events. - * - * @param c menu item to listen to - * + * + * @param c + * menu item to listen to * @return The MenuDragMouseListener */ protected MenuDragMouseListener createMenuDragMouseListener(JComponent c) @@ -189,11 +254,11 @@ public class BasicMenuItemUI extends MenuItemUI } /** - * Creates MenuKeyListener to listen to key events occuring when menu item - * is visible on the screen. - * - * @param c menu item to listen to - * + * 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) @@ -203,9 +268,9 @@ public class BasicMenuItemUI extends MenuItemUI /** * Handles mouse input events occuring for this menu item - * - * @param c menu item to listen to - * + * + * @param c + * menu item to listen to * @return The MouseInputListener */ protected MouseInputListener createMouseInputListener(JComponent c) @@ -216,9 +281,9 @@ public class BasicMenuItemUI extends MenuItemUI /** * 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. - * + * + * @param c + * The {@link JComponent} a UI is being created for. * @return A BasicMenuItemUI for the {@link JComponent}. */ public static ComponentUI createUI(JComponent c) @@ -228,8 +293,9 @@ public class BasicMenuItemUI extends MenuItemUI /** * Programatically clicks menu item. - * - * @param msm MenuSelectionManager for the menu hierarchy + * + * @param msm + * MenuSelectionManager for the menu hierarchy */ protected void doClick(MenuSelectionManager msm) { @@ -239,9 +305,9 @@ public class BasicMenuItemUI extends MenuItemUI /** * Returns maximum size for the specified menu item - * - * @param c component for which to get maximum size - * + * + * @param c + * component for which to get maximum size * @return Maximum size for the specified menu item. */ public Dimension getMaximumSize(JComponent c) @@ -251,9 +317,9 @@ public class BasicMenuItemUI extends MenuItemUI /** * Returns minimum size for the specified menu item - * - * @param c component for which to get minimum size - * + * + * @param c + * component for which to get minimum size * @return Minimum size for the specified menu item. */ public Dimension getMinimumSize(JComponent c) @@ -263,9 +329,9 @@ public class BasicMenuItemUI extends MenuItemUI /** * Returns path to this menu item. - * - * @return $MenuElement[]$ Returns array of menu elements - * that constitute a path to this menu item. + * + * @return $MenuElement[]$ Returns array of menu elements that constitute a + * path to this menu item. */ public MenuElement[] getPath() { @@ -278,12 +344,12 @@ public class BasicMenuItemUI extends MenuItemUI Component c = menuItem; while (c instanceof MenuElement) { - path.add(0, (MenuElement) c); + path.add(0, (MenuElement) c); - if (c instanceof JPopupMenu) - c = ((JPopupMenu) c).getInvoker(); - else - c = c.getParent(); + if (c instanceof JPopupMenu) + c = ((JPopupMenu) c).getInvoker(); + else + c = c.getParent(); } MenuElement[] pathArray = new MenuElement[path.size()]; @@ -293,12 +359,15 @@ public class BasicMenuItemUI extends MenuItemUI /** * Returns preferred size for the given menu item. - * - * @param c menu item for which to get preferred size - * @param checkIcon check 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 - * + * + * @param c + * menu item for which to get preferred size + * @param checkIcon + * check 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, @@ -308,7 +377,7 @@ public class BasicMenuItemUI extends MenuItemUI 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(); @@ -316,52 +385,57 @@ public class BasicMenuItemUI extends MenuItemUI if (accelerator != null) { - rect = getAcceleratorRect(accelerator, - m.getToolkit().getFontMetrics(acceleratorFont)); + rect = getAcceleratorRect( + accelerator, + m.getToolkit().getFontMetrics(acceleratorFont)); - // add width of accelerator's text - d.width = d.width + rect.width + defaultAcceleratorLabelGap; + // add width of accelerator's text + d.width += rect.width + defaultAcceleratorLabelGap; - // adjust the heigth of the preferred size if necessary - if (d.height < rect.height) - d.height = rect.height; + // 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; + d.width += checkIcon.getIconWidth() + defaultTextIconGap; - if (checkIcon.getIconHeight() > d.height) - d.height = checkIcon.getIconHeight(); + 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(); + int pWidth = m.getParent().getWidth(); + if (!((JMenu)c).isTopLevelMenu() && d.width < pWidth) + d.width = pWidth + - m.getInsets().left - m.getInsets().right; + else + d.width += arrowIcon.getIconWidth() + MenuGap; + + 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 - * + * + * @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); + return getPreferredMenuItemSize(c, checkIcon, arrowIcon, defaultTextIconGap); } /** * Returns the prefix for entries in the {@link UIDefaults} table. - * + * * @return "MenuItem" */ protected String getPropertyPrefix() @@ -371,8 +445,9 @@ public class BasicMenuItemUI extends MenuItemUI /** * This method installs the components for this {@link JMenuItem}. - * - * @param menuItem The {@link JMenuItem} to install components for. + * + * @param menuItem + * The {@link JMenuItem} to install components for. */ protected void installComponents(JMenuItem menuItem) { @@ -380,28 +455,27 @@ public class BasicMenuItemUI extends MenuItemUI } /** - * This method installs the defaults that are defined in the Basic look and + * 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"); - + String prefix = getPropertyPrefix(); + LookAndFeel.installBorder(menuItem, prefix + ".border"); + LookAndFeel.installColorsAndFont(menuItem, prefix + ".background", + prefix + ".foreground", prefix + ".font"); + menuItem.setMargin(UIManager.getInsets(prefix + ".margin")); + acceleratorFont = UIManager.getFont(prefix + ".acceleratorFont"); + acceleratorForeground = UIManager.getColor(prefix + ".acceleratorForeground"); + acceleratorSelectionForeground = UIManager.getColor(prefix + ".acceleratorSelectionForeground"); + selectionBackground = UIManager.getColor(prefix + ".selectionBackground"); + selectionForeground = UIManager.getColor(prefix + ".selectionForeground"); + acceleratorDelimiter = UIManager.getString(prefix + ".acceleratorDelimiter"); + checkIcon = UIManager.getIcon(prefix + ".checkIcon"); + menuItem.setHorizontalTextPosition(SwingConstants.TRAILING); menuItem.setHorizontalAlignment(SwingConstants.LEADING); + menuItem.setOpaque(true); } /** @@ -409,7 +483,17 @@ public class BasicMenuItemUI extends MenuItemUI */ protected void installKeyboardActions() { - // FIXME: Need to implement + InputMap focusedWindowMap = SwingUtilities.getUIInputMap(menuItem, JComponent.WHEN_IN_FOCUSED_WINDOW); + if (focusedWindowMap == null) + focusedWindowMap = new ComponentInputMapUIResource(menuItem); + focusedWindowMap.put(menuItem.getAccelerator(), "doClick"); + SwingUtilities.replaceUIInputMap(menuItem, JComponent.WHEN_IN_FOCUSED_WINDOW, focusedWindowMap); + + ActionMap UIActionMap = SwingUtilities.getUIActionMap(menuItem); + if (UIActionMap == null) + UIActionMap = new ActionMapUIResource(); + UIActionMap.put("doClick", new ClickAction()); + SwingUtilities.replaceUIActionMap(menuItem, UIActionMap); } /** @@ -421,15 +505,17 @@ public class BasicMenuItemUI extends MenuItemUI menuItem.addMouseMotionListener(mouseInputListener); menuItem.addMenuDragMouseListener(menuDragMouseListener); menuItem.addMenuKeyListener(menuKeyListener); + menuItem.addItemListener(itemListener); 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. + * 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) { @@ -438,13 +524,16 @@ public class BasicMenuItemUI extends MenuItemUI installDefaults(); installComponents(menuItem); installListeners(); + installKeyboardActions(); } /** * 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 + * + * @param g + * The graphics context used to paint this menu item + * @param c + * Menu Item to paint */ public void paint(Graphics g, JComponent c) { @@ -454,10 +543,13 @@ public class BasicMenuItemUI extends MenuItemUI /** * 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 + * + * @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) { @@ -470,15 +562,21 @@ public class BasicMenuItemUI extends MenuItemUI /** * 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 + * + * @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, @@ -496,7 +594,7 @@ public class BasicMenuItemUI extends MenuItemUI int horAlign = m.getHorizontalAlignment(); int vertTextPos = m.getVerticalTextPosition(); int horTextPos = m.getHorizontalTextPosition(); - + Font f = m.getFont(); g.setFont(f); FontMetrics fm = g.getFontMetrics(f); @@ -504,8 +602,10 @@ public class BasicMenuItemUI extends MenuItemUI 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. */ + /* + * 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; @@ -514,89 +614,93 @@ public class BasicMenuItemUI extends MenuItemUI // Menu item is considered to be highlighted when it is selected. // But we don't want to paint the background of JCheckBoxMenuItems - if ((m.isSelected() && checkIcon == null) || m.getModel().isArmed() && - (m.getParent() instanceof MenuElement)) + ButtonModel mod = m.getModel(); + if ((m.isSelected() && checkIcon == null) || (mod != null && + mod.isArmed()) + && (m.getParent() instanceof MenuElement)) { - if (m.isContentAreaFilled()) - { - g.setColor(selectionBackground); - g.fillRect(br.x, br.y, br.width, br.height); - } + 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 (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); + 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; + // 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); - } + if (!((JMenu) c).isTopLevelMenu()) + { + int width = arrowIcon.getIconWidth(); + int height = arrowIcon.getIconHeight(); + int offset = (vr.height - height) / 2; + arrowIcon.paintIcon(m, g, vr.width - width, vr.y + offset); + } } - // paint text and user menu icon if it exists + // 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); + 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 + // 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); + 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 - defaultTextIconGap; + + 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 + * + * @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) @@ -605,43 +709,46 @@ public class BasicMenuItemUI extends MenuItemUI g.setFont(f); FontMetrics fm = g.getFontMetrics(f); - if (text != null && ! text.equals("")) + if (text != null && !text.equals("")) { - if (menuItem.isEnabled()) + if (menuItem.isEnabled()) { // Menu item is considered to be highlighted when it is selected. // But not if it's a JCheckBoxMenuItem - if ((menuItem.isSelected() && checkIcon == null) || menuItem.getModel().isArmed() && - (menuItem.getParent() instanceof MenuElement)) + ButtonModel mod = menuItem.getModel(); + if ((menuItem.isSelected() && checkIcon == null) + || (mod != null && mod.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. - + 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(); + 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()); + 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. + * + * @param menuItem + * The {@link JMenuItem} to uninstall components for. */ protected void uninstallComponents(JMenuItem menuItem) { @@ -676,8 +783,9 @@ public class BasicMenuItemUI extends MenuItemUI * Uninstalls any keyboard actions. */ protected void uninstallKeyboardActions() - { - // FIXME: need to implement + { + SwingUtilities.replaceUIInputMap(menuItem, + JComponent.WHEN_IN_FOCUSED_WINDOW, null); } /** @@ -688,15 +796,17 @@ public class BasicMenuItemUI extends MenuItemUI menuItem.removeMouseListener(mouseInputListener); menuItem.removeMenuDragMouseListener(menuDragMouseListener); menuItem.removeMenuKeyListener(menuKeyListener); + menuItem.removeItemListener(itemListener); 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. + * 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) { @@ -708,9 +818,11 @@ public class BasicMenuItemUI extends MenuItemUI /** * This method calls paint. - * - * @param g The graphics context used to paint this menu item - * @param c The menu item to 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) { @@ -719,9 +831,9 @@ public class BasicMenuItemUI extends MenuItemUI /** * Return text representation of the specified accelerator - * - * @param accelerator Accelerator for which to return string representation - * + * + * @param accelerator + * Accelerator for which to return string representation * @return $String$ Text representation of the given accelerator */ private String getAcceleratorText(KeyStroke accelerator) @@ -744,10 +856,11 @@ public class BasicMenuItemUI extends MenuItemUI /** * 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 - * + * + * @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) @@ -759,12 +872,16 @@ public class BasicMenuItemUI extends MenuItemUI /** * 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 + * + * @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, @@ -785,10 +902,9 @@ public class BasicMenuItemUI extends MenuItemUI } /** - * 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. - * + * 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 { @@ -797,13 +913,15 @@ public class BasicMenuItemUI extends MenuItemUI */ protected MouseInputHandler() { + // Nothing to do here. } /** - * This method is called when mouse is clicked on the menu item. - * It forwards this event to MenuSelectionManager. - * - * @param e A {@link MouseEvent}. + * 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) { @@ -812,10 +930,11 @@ public class BasicMenuItemUI extends MenuItemUI } /** - * This method is called when mouse is dragged inside the menu item. - * It forwards this event to MenuSelectionManager. - * - * @param e A {@link MouseEvent}. + * 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) { @@ -824,29 +943,31 @@ public class BasicMenuItemUI extends MenuItemUI } /** - * 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}. + * 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); + 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}. + * 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) { @@ -855,10 +976,11 @@ public class BasicMenuItemUI extends MenuItemUI } /** - * 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}. + * 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) { @@ -869,8 +991,9 @@ public class BasicMenuItemUI extends MenuItemUI /** * This method is called when mouse is pressed. This event is forwarded to * MenuSelectionManager for further processing. - * - * @param e A {@link MouseEvent}. + * + * @param e + * A {@link MouseEvent}. */ public void mousePressed(MouseEvent e) { @@ -882,8 +1005,9 @@ public class BasicMenuItemUI extends MenuItemUI * 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}. + * + * @param e + * A {@link MouseEvent}. */ public void mouseReleased(MouseEvent e) { @@ -892,24 +1016,25 @@ public class BasicMenuItemUI extends MenuItemUI if (e.getX() > 0 && e.getX() < size.width && e.getY() > 0 && e.getY() < size.height) { - manager.clearSelectedPath(); - menuItem.doClick(); + manager.clearSelectedPath(); + menuItem.doClick(); } else - manager.processMouseEvent(e); + manager.processMouseEvent(e); } } /** * This class handles mouse dragged events. */ - protected class MenuDragMouseHandler implements MenuDragMouseListener + private class MenuDragMouseHandler implements MenuDragMouseListener { /** * Tbis method is invoked when mouse is dragged over the menu item. - * - * @param e The MenuDragMouseEvent + * + * @param e + * The MenuDragMouseEvent */ public void menuDragMouseDragged(MenuDragMouseEvent e) { @@ -918,10 +1043,11 @@ public class BasicMenuItemUI extends MenuItemUI } /** - * Tbis method is invoked when mouse enters the menu item while it is - * being dragged. - * - * @param e The MenuDragMouseEvent + * Tbis method is invoked when mouse enters the menu item while it is being + * dragged. + * + * @param e + * The MenuDragMouseEvent */ public void menuDragMouseEntered(MenuDragMouseEvent e) { @@ -930,27 +1056,29 @@ public class BasicMenuItemUI extends MenuItemUI } /** - * Tbis method is invoked when mouse exits the menu item while - * it is being dragged - * - * @param e The MenuDragMouseEvent + * Tbis method is invoked when mouse exits the menu item while it is being + * dragged + * + * @param e the MenuDragMouseEvent */ public void menuDragMouseExited(MenuDragMouseEvent e) { + // TODO: What should be done here, if anything? } /** - * Tbis method is invoked when mouse was dragged and released - * inside the menu item. - * - * @param e The MenuDragMouseEvent + * 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(); + ((JMenuItem) path[path.length - 1]).doClick(); MenuSelectionManager manager = MenuSelectionManager.defaultManager(); manager.clearSelectedPath(); @@ -961,50 +1089,63 @@ public class BasicMenuItemUI extends MenuItemUI * This class handles key events occuring when menu item is visible on the * screen. */ - protected class MenuKeyHandler implements MenuKeyListener + private class MenuKeyHandler implements MenuKeyListener { /** * This method is invoked when key has been pressed - * - * @param e A {@link MenuKeyEvent}. + * + * @param e + * A {@link MenuKeyEvent}. */ public void menuKeyPressed(MenuKeyEvent e) { + // TODO: What should be done here, if anything? } /** * This method is invoked when key has been pressed - * - * @param e A {@link MenuKeyEvent}. + * + * @param e + * A {@link MenuKeyEvent}. */ public void menuKeyReleased(MenuKeyEvent e) { + // TODO: What should be done here, if anything? } /** - * This method is invoked when key has been typed - * It handles the mnemonic key for the menu item. - * - * @param e A {@link MenuKeyEvent}. + * 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) { + // TODO: What should be done here, if anything? } } - + /** - * Helper class that listens for changes to the properties of the {@link + * Helper class that listens for item changes to the properties of the {@link * JMenuItem}. */ - protected class PropertyChangeHandler implements PropertyChangeListener + private class ItemHandler implements ItemListener { /** - * This method is called when one of the menu item's properties change. + * This method is called when one of the menu item changes. * - * @param evt A {@link PropertyChangeEvent}. + * @param evt A {@link ItemEvent}. */ - public void propertyChange(PropertyChangeEvent evt) + public void itemStateChanged(ItemEvent evt) { + boolean state = false; + if (menuItem instanceof JCheckBoxMenuItem) + { + if (evt.getStateChange() == ItemEvent.SELECTED) + state = true; + ((JCheckBoxMenuItem) menuItem).setState(state); + } menuItem.revalidate(); menuItem.repaint(); } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicMenuUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicMenuUI.java index 30be592..827cbb0 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicMenuUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicMenuUI.java @@ -38,6 +38,7 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import java.awt.Component; import java.awt.Dimension; import java.awt.event.MouseEvent; import java.beans.PropertyChangeEvent; @@ -46,8 +47,8 @@ import java.beans.PropertyChangeListener; import javax.swing.JComponent; import javax.swing.JMenu; import javax.swing.JMenuBar; -import javax.swing.JMenuItem; import javax.swing.JPopupMenu; +import javax.swing.LookAndFeel; import javax.swing.MenuSelectionManager; import javax.swing.UIDefaults; import javax.swing.UIManager; @@ -92,7 +93,7 @@ public class BasicMenuUI extends BasicMenuItemUI */ protected ChangeListener createChangeListener(JComponent c) { - return new ChangeHandler(); + return new ChangeHandler((JMenu) c, this); } /** @@ -180,12 +181,6 @@ public class BasicMenuUI extends BasicMenuItemUI */ public Dimension getMaximumSize(JComponent c) { - // If this menu is in a popup menu, treat it like a regular JMenuItem - if (!((JMenu)c).isTopLevelMenu()) - { - JMenuItem menuItem = new JMenuItem(((JMenu)c).getText(), ((JMenu)c).getIcon()); - return menuItem.getMaximumSize(); - } return c.getPreferredSize(); } @@ -205,20 +200,17 @@ public class BasicMenuUI extends BasicMenuItemUI */ 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"); + LookAndFeel.installBorder(menuItem, "Menu.border"); + LookAndFeel.installColorsAndFont(menuItem, "Menu.background", + "Menu.foreground", "Menu.font"); + menuItem.setMargin(UIManager.getInsets("Menu.margin")); + acceleratorFont = UIManager.getFont("Menu.acceleratorFont"); + acceleratorForeground = UIManager.getColor("Menu.acceleratorForeground"); + acceleratorSelectionForeground = UIManager.getColor("Menu.acceleratorSelectionForeground"); + selectionBackground = UIManager.getColor("Menu.selectionBackground"); + selectionForeground = UIManager.getColor("Menu.selectionForeground"); + arrowIcon = UIManager.getIcon("Menu.arrowIcon"); + oldBorderPainted = UIManager.getBoolean("Menu.borderPainted"); menuItem.setOpaque(true); } @@ -245,6 +237,7 @@ public class BasicMenuUI extends BasicMenuItemUI protected void setupPostTimer(JMenu menu) { + // TODO: Implement this properly. } /** @@ -356,6 +349,7 @@ public class BasicMenuUI extends BasicMenuItemUI public void mouseMoved(MouseEvent e) { + // TODO: What should be done here, if anything? } public void mousePressed(MouseEvent e) @@ -421,10 +415,13 @@ public class BasicMenuUI extends BasicMenuItemUI public void menuDeselected(MenuEvent e) { JMenu menu = (JMenu) menuItem; - if (menu.isTopLevelMenu()) - ((JMenuBar) menu.getParent()).getSelectionModel().clearSelection(); - else - ((JPopupMenu) menu.getParent()).getSelectionModel().clearSelection(); + if (menu.getParent() != null) + { + if (menu.isTopLevelMenu()) + ((JMenuBar) menu.getParent()).getSelectionModel().clearSelection(); + else + ((JPopupMenu) menu.getParent()).getSelectionModel().clearSelection(); + } } /** @@ -456,6 +453,7 @@ public class BasicMenuUI extends BasicMenuItemUI */ public void propertyChange(PropertyChangeEvent e) { + // TODO: Implement this properly. } } @@ -464,9 +462,40 @@ public class BasicMenuUI extends BasicMenuItemUI */ public class ChangeHandler implements ChangeListener { + /** + * Not used. + */ + public boolean isSelected; + + /** + * Not used. + */ + public JMenu menu; + + /** + * Not used. + */ + public BasicMenuUI ui; + + /** + * Not used. + */ + public Component wasFocused; + + /** + * Not used. + */ + public ChangeHandler(JMenu m, BasicMenuUI ui) + { + // Not used. + } + + /** + * Not used. + */ public void stateChanged(ChangeEvent e) { - // FIXME: It seems that this class is not used anywhere + // Not used. } } @@ -506,6 +535,7 @@ public class BasicMenuUI extends BasicMenuItemUI */ public void menuDragMouseExited(MenuDragMouseEvent e) { + // TODO: What should be done here, if anything? } /** @@ -516,6 +546,7 @@ public class BasicMenuUI extends BasicMenuItemUI */ public void menuDragMouseReleased(MenuDragMouseEvent e) { + // TODO: What should be done here, if anything? } } @@ -532,6 +563,7 @@ public class BasicMenuUI extends BasicMenuItemUI */ public void menuKeyPressed(MenuKeyEvent e) { + // TODO: What should be done here, if anything? } /** @@ -541,6 +573,7 @@ public class BasicMenuUI extends BasicMenuItemUI */ public void menuKeyReleased(MenuKeyEvent e) { + // TODO: What should be done here, if anything? } /** @@ -551,6 +584,7 @@ public class BasicMenuUI extends BasicMenuItemUI */ public void menuKeyTyped(MenuKeyEvent e) { + // TODO: What should be done here, if anything? } } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicOptionPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicOptionPaneUI.java index c9f6232..6b37d31 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicOptionPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicOptionPaneUI.java @@ -70,8 +70,8 @@ import javax.swing.JList; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTextField; +import javax.swing.LookAndFeel; import javax.swing.SwingUtilities; -import javax.swing.UIDefaults; import javax.swing.UIManager; import javax.swing.border.Border; import javax.swing.plaf.ComponentUI; @@ -141,13 +141,14 @@ public class BasicOptionPaneUI extends OptionPaneUI optionPane); if (inf != null) { - try - { - inf.setClosed(true); - } - catch (PropertyVetoException pve) - { - } + try + { + inf.setClosed(true); + } + catch (PropertyVetoException pve) + { + // We do nothing if attempt has been vetoed. + } } } } @@ -405,16 +406,30 @@ public class BasicOptionPaneUI extends OptionPaneUI || 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.remove(messageAreaContainer); + messageAreaContainer = createMessageArea(); + optionPane.add(messageAreaContainer); + Container newButtons = createButtonArea(); + optionPane.remove(buttonContainer); + optionPane.add(newButtons); + buttonContainer = newButtons; + optionPane.add(buttonContainer); } optionPane.invalidate(); optionPane.repaint(); } } + /** + * The minimum width for JOptionPanes. + */ + public static final int MinimumWidth = 262; + + /** + * The minimum height for JOptionPanes. + */ + public static final int MinimumHeight = 90; + /** Whether the JOptionPane contains custom components. */ protected boolean hasCustomComponents = false; @@ -433,12 +448,6 @@ public class BasicOptionPaneUI extends OptionPaneUI /** 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; @@ -518,6 +527,7 @@ public class BasicOptionPaneUI extends OptionPaneUI */ public void paintIcon(Component c, Graphics g, int x, int y) { + // Nothing to do here. } } @@ -637,6 +647,7 @@ public class BasicOptionPaneUI extends OptionPaneUI */ public BasicOptionPaneUI() { + // Nothing to do here. } /** @@ -860,10 +871,10 @@ public class BasicOptionPaneUI extends OptionPaneUI addIcon(messageArea); JPanel rightSide = new JPanel(); - rightSide.setBorder(BorderFactory.createEmptyBorder(0, 11, 17, 0)); + rightSide.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); rightSide.setLayout(new GridBagLayout()); GridBagConstraints con = createConstraints(); - + addMessageComponents(rightSide, con, getMessage(), getMaxCharactersPerLineCount(), false); @@ -886,7 +897,7 @@ public class BasicOptionPaneUI extends OptionPaneUI } } - messageArea.add(rightSide, BorderLayout.EAST); + messageArea.add(rightSide, BorderLayout.CENTER); return messageArea; } @@ -944,8 +955,14 @@ public class BasicOptionPaneUI extends OptionPaneUI 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 }; + case JOptionPane.DEFAULT_OPTION: + return (optionPane.getWantsInput() ) ? + new Object[] { OK_STRING, CANCEL_STRING } : + ( optionPane.getMessageType() == JOptionPane.QUESTION_MESSAGE ) ? + new Object[] { YES_STRING, NO_STRING, CANCEL_STRING } : + // ERROR_MESSAGE, INFORMATION_MESSAGE, WARNING_MESSAGE, PLAIN_MESSAGE + new Object[] { OK_STRING }; } return null; } @@ -1142,21 +1159,17 @@ public class BasicOptionPaneUI extends OptionPaneUI */ 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")); + LookAndFeel.installColorsAndFont(optionPane, "OptionPane.background", + "OptionPane.foreground", + "OptionPane.font"); + LookAndFeel.installBorder(optionPane, "OptionPane.border"); optionPane.setOpaque(true); - messageBorder = defaults.getBorder("OptionPane.messageAreaBorder"); - messageForeground = defaults.getColor("OptionPane.messageForeground"); - buttonBorder = defaults.getBorder("OptionPane.buttonAreaBorder"); + messageBorder = UIManager.getBorder("OptionPane.messageAreaBorder"); + messageForeground = UIManager.getColor("OptionPane.messageForeground"); + buttonBorder = UIManager.getBorder("OptionPane.buttonAreaBorder"); - minimumSize = defaults.getDimension("OptionPane.minimumSize"); - minimumWidth = minimumSize.width; - minimumHeight = minimumSize.height; + minimumSize = UIManager.getDimension("OptionPane.minimumSize"); // FIXME: Image icons don't seem to work properly right now. // Once they do, replace the synthetic icons with these ones. diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicPanelUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicPanelUI.java index b715c57..783cec4 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicPanelUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicPanelUI.java @@ -40,8 +40,7 @@ package javax.swing.plaf.basic; import javax.swing.JComponent; import javax.swing.JPanel; -import javax.swing.UIDefaults; -import javax.swing.UIManager; +import javax.swing.LookAndFeel; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.PanelUI; @@ -64,8 +63,29 @@ public class BasicPanelUI extends PanelUI public void installDefaults(JPanel p) { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - p.setBackground(defaults.getColor("Panel.background")); + LookAndFeel.installColorsAndFont(p, "Panel.background", "Panel.foreground", + "Panel.font"); p.setOpaque(true); } + + /** + * Uninstalls this UI from the JPanel. + * + * @param c the JPanel from which to uninstall this UI + */ + public void uninstallUI(JComponent c) + { + uninstallDefaults((JPanel) c); + } + + /** + * Uninstalls the UI defaults that have been install through + * {@link #installDefaults}. + * + * @param p the panel from which to uninstall the UI defaults + */ + protected void uninstallDefaults(JPanel p) + { + // Nothing to do here. + } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicPasswordFieldUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicPasswordFieldUI.java index 044027b..76dcfc4 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicPasswordFieldUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicPasswordFieldUI.java @@ -39,6 +39,7 @@ exception statement from your version. */ package javax.swing.plaf.basic; import javax.swing.JComponent; +import javax.swing.UIDefaults; import javax.swing.plaf.ComponentUI; import javax.swing.text.Element; import javax.swing.text.PasswordView; @@ -48,6 +49,7 @@ public class BasicPasswordFieldUI extends BasicTextFieldUI { public BasicPasswordFieldUI() { + // Nothing to do here. } public View create(Element elem) @@ -60,6 +62,11 @@ public class BasicPasswordFieldUI extends BasicTextFieldUI return new BasicPasswordFieldUI(); } + /** + * Returns the prefix for entries in the {@link UIDefaults} table. + * + * @return "PasswordField" + */ protected String getPropertyPrefix() { return "PasswordField"; diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuUI.java index 247117b..e15a17b 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicPopupMenuUI.java @@ -53,12 +53,11 @@ import javax.swing.JLayeredPane; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; +import javax.swing.LookAndFeel; 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; @@ -131,12 +130,9 @@ public class BasicPopupMenuUI extends PopupMenuUI */ 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")); + LookAndFeel.installColorsAndFont(popupMenu, "PopupMenu.background", + "PopupMenu.foreground", "PopupMenu.font"); + LookAndFeel.installBorder(popupMenu, "PopupMenu.border"); popupMenu.setOpaque(true); } @@ -277,23 +273,26 @@ public class BasicPopupMenuUI extends PopupMenuUI 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)) + if (rootContainer != null) { - // set glass pane not to interrupt mouse events and remove - // mouseInputListener - Container glassPane = (Container) rootContainer.getGlassPane(); - glassPane.setVisible(false); - glassPane.removeMouseListener(mouseInputListener); - mouseInputListener = null; + ((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; + } } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicProgressBarUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicProgressBarUI.java index d00628f..88d949b 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicProgressBarUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicProgressBarUI.java @@ -46,21 +46,24 @@ import java.awt.Graphics; import java.awt.Insets; import java.awt.Point; import java.awt.Rectangle; +import java.awt.Shape; 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.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.JComponent; import javax.swing.JProgressBar; +import javax.swing.LookAndFeel; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import javax.swing.Timer; -import javax.swing.UIDefaults; import javax.swing.UIManager; +import javax.swing.event.AncestorEvent; +import javax.swing.event.AncestorListener; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.plaf.ComponentUI; @@ -110,14 +113,56 @@ public class BasicProgressBarUI extends ProgressBarUI { // 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(); + if (e.getPropertyName().equals("indeterminate")) + if (((Boolean) e.getNewValue()).booleanValue() + && progressBar.isShowing()) + startAnimationTimer(); + else + stopAnimationTimer(); + } + } + + /** + * Receives notification when the progressbar is becoming visible or + * invisible and starts/stops the animation timer accordingly. + * + * @author Roman Kennke (kennke@aicas.com) + */ + private class AncestorHandler implements AncestorListener + { + + /** + * Receives notification when the progressbar is becoming visible. This + * starts the animation timer if the progressbar is indeterminate. + * + * @param event the ancestor event + */ + public void ancestorAdded(AncestorEvent event) + { + if (progressBar.isIndeterminate()) + startAnimationTimer(); + } + + /** + * Receives notification when the progressbar is becoming invisible. This + * stops the animation timer if the progressbar is indeterminate. + * + * @param event the ancestor event + */ + public void ancestorRemoved(AncestorEvent event) + { + stopAnimationTimer(); + } + + /** + * Receives notification when an ancestor has been moved. We don't need to + * do anything here. + */ + public void ancestorMoved(AncestorEvent event) + { + // Nothing to do here. } + } /** @@ -141,6 +186,35 @@ public class BasicProgressBarUI extends ProgressBarUI } } + /** + * Receives notification when the size of the progress bar changes and + * invalidates the layout information for the box calculation in + * {@link BasicProgressBarUI#getBox(Rectangle)}. + * + * @author Roman Kennke (kennke@aicas.com) + */ + private class ComponentHandler extends ComponentAdapter + { + /** + * Receives notification when the size of the progress bar changes and + * invalidates the layout information for the box calculation in + * {@link BasicProgressBarUI#getBox}. + * + * @param e the component event + */ + public void componentResized(ComponentEvent e) + { + boxDependent = -1; + boxIndependent = -1; + incr = -1; + } + } + + /** + * Holds the value of the bouncing box that is returned by {@link #getBox}. + */ + protected Rectangle boxRect; + /** The timer used to move the bouncing box. */ private transient Timer animationTimer; @@ -172,6 +246,27 @@ public class BasicProgressBarUI extends ProgressBarUI /** The progressBar for this UI. */ protected JProgressBar progressBar; + + /** + * The size of the box returned by {@link #getBox} in the orientation + * direction of the progress bar. This is package private to avoid accessor + * method. + */ + transient double boxDependent = - 1; + + /** + * The size of the box returned by {@link #getBox} against the orientation + * direction of the progress bar. This is package private to avoid accessor + * method. + */ + transient int boxIndependent = - 1; + + /** + * The increment for box animation. This is package private to avoid accessor + * method. + */ + transient double incr = -1; + /** The length of the cell. The cell is the painted part. */ private transient int cellLength; @@ -185,6 +280,18 @@ public class BasicProgressBarUI extends ProgressBarUI private transient Color selectionForeground; /** + * Listens for notification when the component becomes showing and + * starts/stops the animation timer. + */ + private AncestorListener ancestorListener; + + /** + * Listens for resize events on the progress bar and invalidates some + * layout info. + */ + private ComponentListener componentListener; + + /** * Creates a new BasicProgressBarUI object. */ public BasicProgressBarUI() @@ -248,48 +355,49 @@ public class BasicProgressBarUI extends ProgressBarUI { if (!progressBar.isIndeterminate()) return null; - //numFrames has to be an even number as defined by spec. - int iterations = numFrames / 2 + 1; + if (r == null) + r = new Rectangle(); - double boxDependent; - double boxIndependent; + Rectangle vr = new Rectangle(); + SwingUtilities.calculateInnerArea(progressBar, vr); - if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) + // Recalculate the metrics only when size of the progressbar has changed. + if (incr == -1 || boxDependent == -1 || boxIndependent == -1) { - Dimension dims = getPreferredInnerHorizontal(); - boxDependent = (double) dims.width / iterations; - boxIndependent = dims.height; - } - else - { - Dimension dims = getPreferredInnerVertical(); - boxDependent = (double) dims.height / iterations; - boxIndependent = dims.width; + //numFrames has to be an even number as defined by spec. + int iterations = numFrames / 2; + if (progressBar.getOrientation() == JProgressBar.HORIZONTAL) + { + boxDependent = vr.width / 6.; + incr = ((double) (vr.width - boxDependent)) / (double) iterations; + boxIndependent = vr.height; + } + else + { + boxDependent = vr.height / 6.; + incr = ((double) (vr.height - boxDependent)) / (double) iterations; + boxIndependent = vr.width; + } } - Rectangle vr = new Rectangle(); - SwingUtilities.calculateInnerArea(progressBar, vr); - int index = getAnimationIndex(); - if (animationIndex > (numFrames + 1) / 2) + if (animationIndex > (numFrames) / 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; + r.x = vr.x + (int) (incr * index); + 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; + r.x = vr.x; + r.y = vr.height - (int) (incr * index) + vr.y - (int) boxDependent; + r.width = (int) boxIndependent; + r.height = (int) boxDependent; } - return r; } @@ -324,7 +432,22 @@ public class BasicProgressBarUI extends ProgressBarUI */ public Dimension getMaximumSize(JComponent c) { - return getPreferredSize(c); + Insets insets = c.getInsets(); + Dimension ret; + int orientation = progressBar.getOrientation(); + if (orientation == JProgressBar.VERTICAL) + { + ret = getPreferredInnerVertical(); + ret.height = Short.MAX_VALUE; + ret.width += insets.left + insets.right; + } + else + { + ret = getPreferredInnerHorizontal(); + ret.width = Short.MAX_VALUE; + ret.height += insets.top + insets.bottom; + } + return ret; } /** @@ -338,7 +461,22 @@ public class BasicProgressBarUI extends ProgressBarUI */ public Dimension getMinimumSize(JComponent c) { - return getPreferredSize(c); + Insets insets = c.getInsets(); + Dimension ret; + int orientation = progressBar.getOrientation(); + if (orientation == JProgressBar.VERTICAL) + { + ret = getPreferredInnerVertical(); + ret.height = 10; + ret.width += insets.left + insets.right; + } + else + { + ret = getPreferredInnerHorizontal(); + ret.width = 10; + ret.height += insets.top + insets.bottom; + } + return ret; } /** @@ -351,11 +489,22 @@ public class BasicProgressBarUI extends ProgressBarUI */ protected Dimension getPreferredInnerHorizontal() { - Rectangle vr = new Rectangle(); + Font font = progressBar.getFont(); + FontMetrics fm = progressBar.getFontMetrics(font); - SwingUtilities.calculateInnerArea(progressBar, vr); + int stringWidth = 0; + String str = progressBar.getString(); + if (str != null) + stringWidth = fm.stringWidth(progressBar.getString()); + Insets i = progressBar.getInsets(); + int prefWidth = Math.max(200 - i.left - i.right, stringWidth); - return new Dimension(vr.width, vr.height); + int stringHeight = 0; + if (str != null) + stringHeight = fm.getHeight(); + int prefHeight = Math.max(16 - i.top - i.bottom, stringHeight); + + return new Dimension(prefWidth, prefHeight); } /** @@ -368,11 +517,22 @@ public class BasicProgressBarUI extends ProgressBarUI */ protected Dimension getPreferredInnerVertical() { - Rectangle vr = new Rectangle(); + Font font = progressBar.getFont(); + FontMetrics fm = progressBar.getFontMetrics(font); - SwingUtilities.calculateInnerArea(progressBar, vr); + int stringWidth = 0; + String str = progressBar.getString(); + if (str != null) + stringWidth = fm.stringWidth(progressBar.getString()); + Insets i = progressBar.getInsets(); + int prefHeight = Math.max(200 - i.left - i.right, stringWidth); + + int stringHeight = 0; + if (str != null) + stringHeight = fm.getHeight(); + int prefWidth = Math.max(16 - i.top - i.bottom, stringHeight); - return new Dimension(vr.width, vr.height); + return new Dimension(prefWidth, prefHeight); } /** @@ -386,36 +546,16 @@ public class BasicProgressBarUI extends ProgressBarUI */ 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; - } + Dimension ret; + int orientation = progressBar.getOrientation(); + if (orientation == JProgressBar.VERTICAL) + ret = getPreferredInnerVertical(); 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); + ret = getPreferredInnerHorizontal(); + ret.width += insets.left + insets.right; + ret.height += insets.top + insets.bottom; + return ret; } /** @@ -514,66 +654,22 @@ public class BasicProgressBarUI extends ProgressBarUI int min = progressBar.getMinimum(); int value = progressBar.getValue(); - Rectangle vr = new Rectangle(); - SwingUtilities.calculateInnerArea(c, vr); - - Rectangle or = c.getBounds(); - + Rectangle vr = SwingUtilities.calculateInnerArea(c, new Rectangle()); + Rectangle or = progressBar.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; - } - } + g.fillRect(vr.x, vr.y, amountFull, vr.height); } 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); - } - } + g.fillRect(vr.x, vr.y + vr.height - amountFull, vr.width, amountFull); } - } if (progressBar.isStringPainted() && !progressBar.getString().equals("")) paintString(g, 0, 0, or.width, or.height, amountFull, insets); @@ -599,13 +695,12 @@ public class BasicProgressBarUI extends ProgressBarUI SwingUtilities.calculateInnerArea(c, vr); g.setColor(c.getBackground()); - g.fill3DRect(vr.x, vr.y, vr.width, vr.height, false); + g.fillRect(vr.x, vr.y, vr.width, vr.height); - Rectangle box = new Rectangle(); - getBox(box); + boxRect = getBox(boxRect); g.setColor(c.getForeground()); - g.fill3DRect(box.x, box.y, box.width, box.height, true); + g.fillRect(boxRect.x, boxRect.y, boxRect.width, boxRect.height); if (progressBar.isStringPainted() && !progressBar.getString().equals("")) paintString(g, 0, 0, or.width, or.height, @@ -628,23 +723,34 @@ public class BasicProgressBarUI extends ProgressBarUI protected void paintString(Graphics g, int x, int y, int width, int height, int amountFull, Insets b) { + // FIXME: We do not support vertical text painting because Java2D is needed + // for this. + if (progressBar.getOrientation() == JProgressBar.VERTICAL) + return; + // 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); + Color savedColor = g.getColor(); + Shape savedClip = g.getClip(); FontMetrics fm = g.getFontMetrics(progressBar.getFont()); + int full = getAmountFull(b, width, height); + String str = progressBar.getString(); - g.drawString(progressBar.getString(), placement.x, - placement.y + fm.getAscent()); - - g.setColor(saved); + // We draw this string two times with different clips so that the text + // over the filled area is painted with selectionForeground and over + // the clear area with selectionBackground. + g.setColor(getSelectionForeground()); + g.setClip(0, 0, full + b.left, height); + g.drawString(str, placement.x, placement.y + fm.getAscent()); + g.setColor(getSelectionBackground()); + g.setClip(full + b.left, 0, width - full, height); + g.drawString(str, placement.x, placement.y + fm.getAscent()); + g.setClip(savedClip); + g.setColor(savedColor); } /** @@ -712,21 +818,19 @@ public class BasicProgressBarUI extends ProgressBarUI */ 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")); + LookAndFeel.installColorsAndFont(progressBar, "ProgressBar.background", + "ProgressBar.foreground", + "ProgressBar.font"); + LookAndFeel.installBorder(progressBar, "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"); + selectionForeground = UIManager.getColor("ProgressBar.selectionForeground"); + selectionBackground = UIManager.getColor("ProgressBar.selectionBackground"); + cellLength = UIManager.getInt("ProgressBar.cellLength"); + cellSpacing = UIManager.getInt("ProgressBar.cellSpacing"); - int repaintInterval = defaults.getInt("ProgressBar.repaintInterval"); - int cycleTime = defaults.getInt("ProgressBar.cycleTime"); + int repaintInterval = UIManager.getInt("ProgressBar.repaintInterval"); + int cycleTime = UIManager.getInt("ProgressBar.cycleTime"); if (cycleTime % repaintInterval != 0 && (cycleTime / repaintInterval) % 2 != 0) @@ -768,6 +872,12 @@ public class BasicProgressBarUI extends ProgressBarUI progressBar.addChangeListener(changeListener); progressBar.addPropertyChangeListener(propertyListener); animationTimer.addActionListener(animation); + + ancestorListener = new AncestorHandler(); + progressBar.addAncestorListener(ancestorListener); + + componentListener = new ComponentHandler(); + progressBar.addComponentListener(componentListener); } /** @@ -783,6 +893,14 @@ public class BasicProgressBarUI extends ProgressBarUI changeListener = null; propertyListener = null; animation = null; + + if (ancestorListener != null) + progressBar.removeAncestorListener(ancestorListener); + ancestorListener = null; + + if (componentListener != null) + progressBar.removeComponentListener(componentListener); + componentListener = null; } /** @@ -806,6 +924,8 @@ public class BasicProgressBarUI extends ProgressBarUI installDefaults(); installListeners(); } + if (progressBar.isIndeterminate()) + startAnimationTimer(); } /** @@ -824,4 +944,5 @@ public class BasicProgressBarUI extends ProgressBarUI animationTimer = null; progressBar = null; } + } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonMenuItemUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonMenuItemUI.java index fa74a00..8af5ff7 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonMenuItemUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonMenuItemUI.java @@ -59,8 +59,6 @@ public class BasicRadioButtonMenuItemUI extends BasicMenuItemUI public BasicRadioButtonMenuItemUI() { super(); - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - checkIcon = defaults.getIcon("RadioButtonMenuItem.checkIcon"); } /** @@ -98,5 +96,7 @@ public class BasicRadioButtonMenuItemUI extends BasicMenuItemUI MenuElement[] path, MenuSelectionManager manager) { + // TODO: May not be implemented properly. + item.processMouseEvent(e, path, manager); } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonUI.java index fbd2124..f3698e8 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicRadioButtonUI.java @@ -38,6 +38,8 @@ 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.Graphics; import java.awt.Rectangle; @@ -93,6 +95,10 @@ public class BasicRadioButtonUI extends BasicToggleButtonUI b.setIcon(icon); if (b.getSelectedIcon() == null) b.setSelectedIcon(icon); + if (b.getDisabledIcon() == null) + b.setDisabledIcon(icon); + if (b.getDisabledSelectedIcon() == null) + b.setDisabledSelectedIcon(icon); } /** @@ -139,10 +145,14 @@ public class BasicRadioButtonUI extends BasicToggleButtonUI g.setFont(f); Icon currentIcon = null; - if (b.isSelected()) + if (b.isSelected() && b.isEnabled()) currentIcon = b.getSelectedIcon(); - else + else if (!b.isSelected() && b.isEnabled()) currentIcon = b.getIcon(); + else if (b.isSelected() && !b.isEnabled()) + currentIcon = b.getDisabledSelectedIcon(); + else // (!b.isSelected() && !b.isEnabled()) + currentIcon = b.getDisabledIcon(); SwingUtilities.calculateInnerArea(b, vr); String text = SwingUtilities.layoutCompoundLabel @@ -157,6 +167,25 @@ public class BasicRadioButtonUI extends BasicToggleButtonUI } if (text != null) paintText(g, b, tr, text); - paintFocus(g, b, vr, tr, ir); + // TODO: Figure out what is the size parameter? + if (b.hasFocus() && b.isFocusPainted() && b.isEnabled()) + paintFocus(g, tr, null); + } + + /** + * Paints the focus indicator for JRadioButtons. + * + * @param g the graphics context + * @param tr the rectangle for the text label + * @param size the size (??) + */ + // TODO: Figure out what for is the size parameter. + protected void paintFocus(Graphics g, Rectangle tr, Dimension size) + { + Color focusColor = UIManager.getColor(getPropertyPrefix() + ".focus"); + Color saved = g.getColor(); + g.setColor(focusColor); + g.drawRect(tr.x, tr.y, tr.width, tr.height); + g.setColor(saved); } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicRootPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicRootPaneUI.java index d97f7ba..2a698e8 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicRootPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicRootPaneUI.java @@ -42,6 +42,7 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.JComponent; +import javax.swing.JRootPane; import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.RootPaneUI; @@ -56,11 +57,127 @@ public class BasicRootPaneUI extends RootPaneUI public void installUI(JComponent c) { - c.setBackground(UIManager.getColor("control")); super.installUI(c); + if (c instanceof JRootPane) + { + JRootPane rp = (JRootPane) c; + installDefaults(rp); + installComponents(rp); + installListeners(rp); + installKeyboardActions(rp); + } + } + + /** + * Installs the look and feel defaults for JRootPane. + * + * @param rp the root pane to install the defaults to + */ + protected void installDefaults(JRootPane rp) + { + // Is this ok? + rp.setBackground(UIManager.getColor("control")); + } + + /** + * Installs additional look and feel components to the root pane. + * + * @param rp the root pane to install the components to + */ + protected void installComponents(JRootPane rp) + { + // All components are initialized in the JRootPane constructor, and since + // the createXXXPane methods are protected, I see no reasonable way, + // and no need to initialize them here. This method is here anyway + // for compatibility and to provide the necessary hooks to subclasses. + } + + /** + * Installs any look and feel specific listeners on the root pane. + * + * @param rp the root pane to install the listeners to + */ + protected void installListeners(JRootPane rp) + { + rp.addPropertyChangeListener(this); + } + + /** + * Installs look and feel keyboard actions on the root pane. + * + * @param rp the root pane to install the keyboard actions to + */ + protected void installKeyboardActions(JRootPane rp) + { + // We currently do not install any keyboard actions here. + // This method is here anyway for compatibility and to provide + // the necessary hooks to subclasses. } public void propertyChange(PropertyChangeEvent event) { + // TODO: Implement this properly. + } + + /** + * Uninstalls this UI from the root pane. This calls + * {@link #uninstallDefaults}, {@link #uninstallComponents}, + * {@link #uninstallListeners}, {@link #uninstallKeyboardActions} + * in this order. + * + * @param c the root pane to uninstall the UI from + */ + public void uninstallUI(JComponent c) + { + super.uninstallUI(c); + if (c instanceof JRootPane) + { + JRootPane rp = (JRootPane) c; + uninstallDefaults(rp); + uninstallComponents(rp); + uninstallListeners(rp); + uninstallKeyboardActions(rp); + } + } + + /** + * Uninstalls the look and feel defaults that have been installed in + * {@link #installDefaults}. + * + * @param rp the root pane to uninstall the defaults from + */ + protected void uninstallDefaults(JRootPane rp) + { + // We do nothing here. + } + + /** + * Uninstalls look and feel components from the root pane. + * + * @param rp the root pane to uninstall the components from + */ + protected void uninstallComponents(JRootPane rp) + { + // We do nothing here. + } + + /** + * Uninstalls any look and feel specific listeners from the root pane. + * + * @param rp the root pane to uninstall the listeners from + */ + protected void uninstallListeners(JRootPane rp) + { + rp.removePropertyChangeListener(this); + } + + /** + * Uninstalls look and feel keyboard actions from the root pane. + * + * @param rp the root pane to uninstall the keyboard actions from + */ + protected void uninstallKeyboardActions(JRootPane rp) + { + // We do nothing here. } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicScrollBarUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicScrollBarUI.java index 22242af..2f5eaf3 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicScrollBarUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicScrollBarUI.java @@ -58,6 +58,7 @@ import javax.swing.BoundedRangeModel; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JScrollBar; +import javax.swing.LookAndFeel; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import javax.swing.Timer; @@ -80,6 +81,7 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, */ 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. @@ -91,9 +93,10 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, scrollTimer.stop(); scrollListener.setScrollByBlock(false); if (e.getSource() == incrButton) - scrollListener.setDirection(POSITIVE_SCROLL); - else - scrollListener.setDirection(NEGATIVE_SCROLL); + scrollListener.setDirection(POSITIVE_SCROLL); + else if (e.getSource() == decrButton) + scrollListener.setDirection(NEGATIVE_SCROLL); + scrollTimer.setDelay(100); scrollTimer.start(); } @@ -105,6 +108,11 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, public void mouseReleased(MouseEvent e) { scrollTimer.stop(); + scrollTimer.setDelay(300); + if (e.getSource() == incrButton) + scrollByUnit(POSITIVE_SCROLL); + else if (e.getSource() == decrButton) + scrollByUnit(NEGATIVE_SCROLL); } } @@ -120,9 +128,8 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, */ public void stateChanged(ChangeEvent e) { - // System.err.println(this + ".stateChanged()"); calculatePreferredSize(); - getThumbBounds(); + updateThumbRect(); scrollbar.repaint(); } } @@ -141,31 +148,27 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, { if (e.getPropertyName().equals("model")) { - ((BoundedRangeModel) e.getOldValue()).removeChangeListener(modelListener); - scrollbar.getModel().addChangeListener(modelListener); - getThumbBounds(); + ((BoundedRangeModel) e.getOldValue()).removeChangeListener(modelListener); + scrollbar.getModel().addChangeListener(modelListener); + updateThumbRect(); } 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(); + uninstallListeners(); + uninstallComponents(); + uninstallDefaults(); + installDefaults(); + installComponents(); + installListeners(); + } + else if (e.getPropertyName().equals("enabled")) + { + Boolean b = (Boolean) e.getNewValue(); + if (incrButton != null) + incrButton.setEnabled(b.booleanValue()); + if (decrButton != null) + decrButton.setEnabled(b.booleanValue()); } - scrollbar.repaint(); } } @@ -233,19 +236,19 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, { 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); + // 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); + scrollByUnit(direction); } } @@ -316,9 +319,6 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, else value = valueForYPosition(currentMouseY); - if (value == scrollbar.getValue()) - return; - if (! thumbRect.contains(e.getPoint())) { scrollTimer.stop(); @@ -333,6 +333,7 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, trackHighlight = DECREASE_HIGHLIGHT; scrollListener.setDirection(NEGATIVE_SCROLL); } + scrollTimer.setDelay(100); scrollTimer.start(); } else @@ -343,8 +344,10 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, // "lower" edge of the thumb. The value at which // the cursor is at must be greater or equal // to that value. + + scrollListener.setScrollByBlock(false); scrollbar.setValueIsAdjusting(true); - offset = value - scrollbar.getValue(); + offset = value - scrollbar.getValue(); } scrollbar.repaint(); } @@ -357,11 +360,19 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, */ public void mouseReleased(MouseEvent e) { - trackHighlight = NO_HIGHLIGHT; scrollTimer.stop(); + scrollTimer.setDelay(300); + currentMouseX = e.getX(); + currentMouseY = e.getY(); - if (scrollbar.getValueIsAdjusting()) - scrollbar.setValueIsAdjusting(false); + if (shouldScroll(POSITIVE_SCROLL)) + scrollByBlock(POSITIVE_SCROLL); + else if (shouldScroll(NEGATIVE_SCROLL)) + scrollByBlock(NEGATIVE_SCROLL); + + trackHighlight = NO_HIGHLIGHT; + scrollListener.setScrollByBlock(false); + scrollbar.setValueIsAdjusting(true); scrollbar.repaint(); } @@ -381,6 +392,9 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, else value = valueForYPosition(currentMouseY); + if (thumbRect.contains(currentMouseX, currentMouseY)) + return false; + if (direction == POSITIVE_SCROLL) return (value > scrollbar.getValue()); else @@ -517,11 +531,7 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, */ protected JButton createIncreaseButton(int orientation) { - if (incrButton == null) - incrButton = new BasicArrowButton(orientation); - else - ((BasicArrowButton) incrButton).setDirection(orientation); - return incrButton; + return new BasicArrowButton(orientation); } /** @@ -534,11 +544,7 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, */ protected JButton createDecreaseButton(int orientation) { - if (decrButton == null) - decrButton = new BasicArrowButton(orientation); - else - ((BasicArrowButton) decrButton).setDirection(orientation); - return decrButton; + return new BasicArrowButton(orientation); } /** @@ -602,7 +608,7 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, */ public Dimension getMaximumSize(JComponent c) { - return getPreferredSize(c); + return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); } /** @@ -644,7 +650,6 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, */ void calculatePreferredSize() { - // System.err.println(this + ".calculatePreferredSize()"); int height; int width; height = width = 0; @@ -707,48 +712,6 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, */ 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; } @@ -760,22 +723,6 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, */ 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; } @@ -785,6 +732,18 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, */ protected void installComponents() { + if (incrButton != null) + scrollbar.add(incrButton); + if (decrButton != null) + scrollbar.add(decrButton); + } + + /** + * This method installs the defaults for the scrollbar specified by the + * Basic Look and Feel. + */ + protected void installDefaults() + { int orientation = scrollbar.getOrientation(); switch (orientation) { @@ -797,31 +756,20 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, 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")); + LookAndFeel.installColors(scrollbar, "ScrollBar.background", + "ScrollBar.foreground"); + LookAndFeel.installBorder(scrollbar, "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"); + thumbColor = UIManager.getColor("ScrollBar.thumb"); + thumbDarkShadowColor = UIManager.getColor("ScrollBar.thumbDarkShadow"); + thumbHighlightColor = UIManager.getColor("ScrollBar.thumbHighlight"); + thumbLightShadowColor = UIManager.getColor("ScrollBar.thumbShadow"); - maximumThumbSize = defaults.getDimension("ScrollBar.maximumThumbSize"); - minimumThumbSize = defaults.getDimension("ScrollBar.minimumThumbSize"); + maximumThumbSize = UIManager.getDimension("ScrollBar.maximumThumbSize"); + minimumThumbSize = UIManager.getDimension("ScrollBar.minimumThumbSize"); } /** @@ -873,11 +821,10 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, trackRect = new Rectangle(); thumbRect = new Rectangle(); - scrollTimer = new Timer(200, null); - scrollTimer.setRepeats(true); + scrollTimer = new Timer(300, null); + installDefaults(); installComponents(); - installDefaults(); configureScrollBarColors(); installListeners(); @@ -908,17 +855,20 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, */ 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(); + + // calculate and update the track bounds + SwingUtilities.calculateInnerArea(scrollbar, trackRect); + trackRect.width -= incrDims.getWidth(); + trackRect.width -= decrDims.getWidth(); + trackRect.x += decrDims.getWidth(); + updateThumbRect(); + decrButton.setBounds(vr.x, vr.y, decrDims.width, trackRect.height); incrButton.setBounds(trackRect.x + trackRect.width, vr.y, incrDims.width, trackRect.height); @@ -934,12 +884,16 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, Rectangle vr = new Rectangle(); SwingUtilities.calculateInnerArea(scrollbar, vr); - // Update rectangles - getTrackBounds(); - getThumbBounds(); - Dimension incrDims = incrButton.getPreferredSize(); Dimension decrDims = decrButton.getPreferredSize(); + + // Update rectangles + SwingUtilities.calculateInnerArea(scrollbar, trackRect); + trackRect.height -= incrDims.getHeight(); + trackRect.height -= decrDims.getHeight(); + trackRect.y += decrDims.getHeight(); + + updateThumbRect(); decrButton.setBounds(vr.x, vr.y, trackRect.width, decrDims.height); incrButton.setBounds(vr.x, trackRect.y + trackRect.height, @@ -947,6 +901,58 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, } /** + * Updates the thumb rect. + */ + void updateThumbRect() + { + int max = scrollbar.getMaximum(); + int min = scrollbar.getMinimum(); + int value = scrollbar.getValue(); + int extent = scrollbar.getVisibleAmount(); + if (max - extent <= min) + { + if (scrollbar.getOrientation() == JScrollBar.HORIZONTAL) + { + thumbRect.x = trackRect.x; + thumbRect.y = trackRect.y; + thumbRect.width = getMinimumThumbSize().width; + thumbRect.height = trackRect.height; + } + else + { + thumbRect.x = trackRect.x; + thumbRect.y = trackRect.y; + thumbRect.width = trackRect.width; + thumbRect.height = getMinimumThumbSize().height; + } + } + else + { + if (scrollbar.getOrientation() == JScrollBar.HORIZONTAL) + { + thumbRect.x = trackRect.x; + thumbRect.width = Math.max(extent * trackRect.width / (max - min), + getMinimumThumbSize().width); + int availableWidth = trackRect.width - thumbRect.width; + thumbRect.x += (value - min) * availableWidth / (max - min - extent); + thumbRect.y = trackRect.y; + thumbRect.height = trackRect.height; + } + else + { + thumbRect.x = trackRect.x; + thumbRect.height = Math.max(extent * trackRect.height / (max - min), + getMinimumThumbSize().height); + int availableHeight = trackRect.height - thumbRect.height; + thumbRect.y = trackRect.y + + (value - min) * availableHeight / (max - min - extent); + thumbRect.width = trackRect.width; + } + } + + } + + /** * This method returns the minimum size required for the layout. * * @param scrollbarContainer The Container that is laid out. @@ -1124,10 +1130,10 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, */ protected void uninstallComponents() { - scrollbar.remove(incrButton); - scrollbar.remove(decrButton); - incrButton = null; - decrButton = null; + if (incrButton != null) + scrollbar.remove(incrButton); + if (decrButton != null) + scrollbar.remove(decrButton); } /** @@ -1138,7 +1144,9 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, { scrollbar.setForeground(null); scrollbar.setBackground(null); - scrollbar.setBorder(null); + LookAndFeel.uninstallBorder(scrollbar); + incrButton = null; + decrButton = null; } /** @@ -1155,17 +1163,22 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, */ protected void uninstallListeners() { - scrollTimer.removeActionListener(scrollListener); + if (scrollTimer != null) + scrollTimer.removeActionListener(scrollListener); - scrollbar.getModel().removeChangeListener(modelListener); - scrollbar.removePropertyChangeListener(propertyChangeListener); - - decrButton.removeMouseListener(buttonListener); - incrButton.removeMouseListener(buttonListener); - - scrollbar.removeMouseListener(trackListener); - scrollbar.removeMouseMotionListener(trackListener); + if (scrollbar != null) + { + scrollbar.getModel().removeChangeListener(modelListener); + scrollbar.removePropertyChangeListener(propertyChangeListener); + scrollbar.removeMouseListener(trackListener); + scrollbar.removeMouseMotionListener(trackListener); + } + if (decrButton != null) + decrButton.removeMouseListener(buttonListener); + if (incrButton != null) + incrButton.removeMouseListener(buttonListener); + propertyChangeListener = null; modelListener = null; buttonListener = null; @@ -1182,8 +1195,8 @@ public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager, */ public void uninstallUI(JComponent c) { - uninstallDefaults(); uninstallListeners(); + uninstallDefaults(); uninstallComponents(); scrollTimer = null; diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicScrollPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicScrollPaneUI.java index bd1576f..808ed27 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicScrollPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicScrollPaneUI.java @@ -40,13 +40,21 @@ package javax.swing.plaf.basic; import java.awt.Dimension; import java.awt.Graphics; +import java.awt.Point; +import java.awt.event.MouseWheelEvent; +import java.awt.event.MouseWheelListener; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import javax.swing.JComponent; +import javax.swing.JScrollBar; import javax.swing.JScrollPane; +import javax.swing.JViewport; +import javax.swing.LookAndFeel; import javax.swing.ScrollPaneConstants; import javax.swing.ScrollPaneLayout; -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.ScrollPaneUI; @@ -54,9 +62,207 @@ public class BasicScrollPaneUI extends ScrollPaneUI implements ScrollPaneConstants { + /** + * Listens for changes in the state of the horizontal scrollbar's model and + * updates the scrollpane accordingly. + * + * @author Roman Kennke (kennke@aicas.com) + */ + public class HSBChangeListener implements ChangeListener + { + + /** + * Receives notification when the state of the horizontal scrollbar + * model has changed. + * + * @param event the change event + */ + public void stateChanged(ChangeEvent event) + { + JScrollBar hsb = scrollpane.getHorizontalScrollBar(); + JViewport vp = scrollpane.getViewport(); + Point viewPosition = vp.getViewPosition(); + int xpos = hsb.getValue(); + + if (xpos != viewPosition.x) + { + viewPosition.x = xpos; + vp.setViewPosition(viewPosition); + } + + viewPosition.y = 0; + JViewport columnHeader = scrollpane.getColumnHeader(); + if (columnHeader != null + && !columnHeader.getViewPosition().equals(viewPosition)) + columnHeader.setViewPosition(viewPosition); + } + + } + + /** + * Listens for changes in the state of the vertical scrollbar's model and + * updates the scrollpane accordingly. + * + * @author Roman Kennke (kennke@aicas.com) + */ + public class VSBChangeListener implements ChangeListener + { + + /** + * Receives notification when the state of the vertical scrollbar + * model has changed. + * + * @param event the change event + */ + public void stateChanged(ChangeEvent event) + { + JScrollBar vsb = scrollpane.getVerticalScrollBar(); + JViewport vp = scrollpane.getViewport(); + Point viewPosition = vp.getViewPosition(); + int ypos = vsb.getValue(); + if (ypos != viewPosition.y) + { + viewPosition.y = ypos; + vp.setViewPosition(viewPosition); + } + + viewPosition.x = 0; + JViewport rowHeader = scrollpane.getRowHeader(); + if (rowHeader != null + && !rowHeader.getViewPosition().equals(viewPosition)) + rowHeader.setViewPosition(viewPosition); + } + + } + + /** + * Listens for changes of the viewport's extent size and updates the + * scrollpane accordingly. + * + * @author Roman Kennke (kennke@aicas.com) + */ + public class ViewportChangeHandler implements ChangeListener + { + + /** + * Receives notification when the view's size, position or extent size + * changes. When the extents size has changed, this method calls + * {@link BasicScrollPaneUI#syncScrollPaneWithViewport()} to adjust the + * scrollbars extents as well. + * + * @param event the change event + */ + public void stateChanged(ChangeEvent event) + { + JViewport vp = scrollpane.getViewport(); + JScrollBar hsb = scrollpane.getHorizontalScrollBar(); + JScrollBar vsb = scrollpane.getVerticalScrollBar(); + syncScrollPaneWithViewport(); + } + + } + + /** + * Listens for property changes on the scrollpane and update the view + * accordingly. + * + * @author Roman Kennke (kennke@aicas.com) + */ + public class PropertyChangeHandler implements PropertyChangeListener + { + + /** + * Receives notification when any of the scrollpane's bound property + * changes. This method calls the appropriate update method on the + * <code>ScrollBarUI</code>. + * + * @param e the property change event + * + * @see BasicScrollPaneUI#updateColumnHeader(PropertyChangeEvent) + * @see BasicScrollPaneUI#updateRowHeader(PropertyChangeEvent) + * @see BasicScrollPaneUI#updateScrollBarDisplayPolicy(PropertyChangeEvent) + * @see BasicScrollPaneUI#updateViewport(PropertyChangeEvent) + */ + public void propertyChange(PropertyChangeEvent e) + { + String propName = e.getPropertyName(); + if (propName.equals("viewport")) + updateViewport(e); + else if (propName.equals("rowHeader")) + updateRowHeader(e); + else if (propName.equals("columnHeader")) + updateColumnHeader(e); + else if (propName.equals("horizontalScrollBarPolicy") + || e.getPropertyName().equals("verticalScrollBarPolicy")) + updateScrollBarDisplayPolicy(e); + else if (propName.equals("verticalScrollBar")) + { + JScrollBar oldSb = (JScrollBar) e.getOldValue(); + oldSb.getModel().removeChangeListener(vsbChangeListener); + JScrollBar newSb = (JScrollBar) e.getNewValue(); + newSb.getModel().addChangeListener(vsbChangeListener); + } + else if (propName.equals("horizontalScrollBar")) + { + JScrollBar oldSb = (JScrollBar) e.getOldValue(); + oldSb.getModel().removeChangeListener(hsbChangeListener); + JScrollBar newSb = (JScrollBar) e.getNewValue(); + newSb.getModel().addChangeListener(hsbChangeListener); + } + } + + } + + /** + * Listens for mouse wheel events and update the scrollpane accordingly. + * + * @author Roman Kennke (kennke@aicas.com) + * + * @since 1.4 + */ + protected class MouseWheelHandler implements MouseWheelListener + { + + /** + * Receives notification whenever the mouse wheel is moved. + * + * @param event the mouse wheel event + */ + public void mouseWheelMoved(MouseWheelEvent event) + { + // TODO: Implement this properly. + } + + } + /** The Scrollpane for which the UI is provided by this class. */ protected JScrollPane scrollpane; + /** + * The horizontal scrollbar listener. + */ + protected ChangeListener hsbChangeListener; + + /** + * The vertical scrollbar listener. + */ + protected ChangeListener vsbChangeListener; + + /** + * The viewport listener. + */ + protected ChangeListener viewportChangeListener; + + /** + * The scrollpane property change listener. + */ + protected PropertyChangeListener spPropertyChangeListener; + + /** + * The mousewheel listener for the scrollpane. + */ + MouseWheelListener mouseWheelListener; + public static ComponentUI createUI(final JComponent c) { return new BasicScrollPaneUI(); @@ -65,11 +271,10 @@ public class BasicScrollPaneUI extends ScrollPaneUI 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")); + LookAndFeel.installColorsAndFont(p, "ScrollPane.background", + "ScrollPane.foreground", + "ScrollPane.font"); + LookAndFeel.installBorder(p, "ScrollPane.border"); p.setOpaque(true); } @@ -85,16 +290,141 @@ public class BasicScrollPaneUI extends ScrollPaneUI public void installUI(final JComponent c) { super.installUI(c); - this.installDefaults((JScrollPane)c); + installDefaults((JScrollPane) c); + installListeners((JScrollPane) c); + installKeyboardActions((JScrollPane) c); + } + + /** + * Installs the listeners on the scrollbars, the viewport and the scrollpane. + * + * @param sp the scrollpane on which to install the listeners + */ + protected void installListeners(JScrollPane sp) + { + if (spPropertyChangeListener == null) + spPropertyChangeListener = createPropertyChangeListener(); + sp.addPropertyChangeListener(spPropertyChangeListener); + + if (hsbChangeListener == null) + hsbChangeListener = createHSBChangeListener(); + sp.getHorizontalScrollBar().getModel().addChangeListener(hsbChangeListener); + + if (vsbChangeListener == null) + vsbChangeListener = createVSBChangeListener(); + sp.getVerticalScrollBar().getModel().addChangeListener(vsbChangeListener); + + if (viewportChangeListener == null) + viewportChangeListener = createViewportChangeListener(); + sp.getViewport().addChangeListener(viewportChangeListener); + + if (mouseWheelListener == null) + mouseWheelListener = createMouseWheelListener(); + sp.addMouseWheelListener(mouseWheelListener); + } + + /** + * Installs additional keyboard actions on the scrollpane. This is a hook + * method provided to subclasses in order to install their own keyboard + * actions. + * + * @param sp the scrollpane to install keyboard actions on + */ + protected void installKeyboardActions(JScrollPane sp) + { + // TODO: Is this only a hook method or should we actually do something + // here? If the latter, than figure out what and implement this. + } + + /** + * Creates and returns the change listener for the horizontal scrollbar. + * + * @return the change listener for the horizontal scrollbar + */ + protected ChangeListener createHSBChangeListener() + { + return new HSBChangeListener(); + } + + /** + * Creates and returns the change listener for the vertical scrollbar. + * + * @return the change listener for the vertical scrollbar + */ + protected ChangeListener createVSBChangeListener() + { + return new VSBChangeListener(); + } + + /** + * Creates and returns the change listener for the viewport. + * + * @return the change listener for the viewport + */ + protected ChangeListener createViewportChangeListener() + { + return new ViewportChangeHandler(); + } + + /** + * Creates and returns the property change listener for the scrollpane. + * + * @return the property change listener for the scrollpane + */ + protected PropertyChangeListener createPropertyChangeListener() + { + return new PropertyChangeHandler(); + } + + /** + * Creates and returns the mouse wheel listener for the scrollpane. + * + * @return the mouse wheel listener for the scrollpane + */ + protected MouseWheelListener createMouseWheelListener() + { + return new MouseWheelHandler(); } public void uninstallUI(final JComponent c) { super.uninstallUI(c); this.uninstallDefaults((JScrollPane)c); + uninstallListeners((JScrollPane) c); + installKeyboardActions((JScrollPane) c); + } + + /** + * Uninstalls all the listeners that have been installed in + * {@link #installListeners(JScrollPane)}. + * + * @param c the scrollpane from which to uninstall the listeners + */ + protected void uninstallListeners(JComponent c) + { + JScrollPane sp = (JScrollPane) c; + sp.removePropertyChangeListener(spPropertyChangeListener); + sp.getHorizontalScrollBar().getModel() + .removeChangeListener(hsbChangeListener); + sp.getVerticalScrollBar().getModel() + .removeChangeListener(vsbChangeListener); + sp.getViewport().removeChangeListener(viewportChangeListener); + sp.removeMouseWheelListener(mouseWheelListener); + } + + /** + * Uninstalls all keyboard actions from the JScrollPane that have been + * installed by {@link #installKeyboardActions}. This is a hook method + * provided to subclasses to add their own keyboard actions. + * + * @param sp the scrollpane to uninstall keyboard actions from + */ + protected void uninstallKeyboardActions(JScrollPane sp) + { + // TODO: Is this only a hook method or should we actually do something + // here? If the latter, than figure out what and implement this. } - public Dimension getMinimumSize(JComponent c) { JScrollPane p = (JScrollPane ) c; @@ -107,6 +437,76 @@ public class BasicScrollPaneUI extends ScrollPaneUI // do nothing; the normal painting-of-children algorithm, along with // ScrollPaneLayout, does all the relevant work. } + + /** + * Synchronizes the scrollbars with the viewport's extents. + */ + protected void syncScrollPaneWithViewport() + { + JViewport vp = scrollpane.getViewport(); + + // Update the horizontal scrollbar. + JScrollBar hsb = scrollpane.getHorizontalScrollBar(); + hsb.setMaximum(vp.getViewSize().width); + hsb.setValue(vp.getViewPosition().x); + hsb.setVisibleAmount(vp.getExtentSize().width); + + // Update the vertical scrollbar. + JScrollBar vsb = scrollpane.getVerticalScrollBar(); + vsb.setMaximum(vp.getViewSize().height); + vsb.setValue(vp.getViewPosition().y); + vsb.setVisibleAmount(vp.getExtentSize().height); + } + + /** + * Receives notification when the <code>columnHeader</code> property has + * changed on the scrollpane. + * + * @param ev the property change event + */ + protected void updateColumnHeader(PropertyChangeEvent ev) + { + // TODO: Find out what should be done here. Or is this only a hook? + } + + /** + * Receives notification when the <code>rowHeader</code> property has changed + * on the scrollpane. + * + * @param ev the property change event + */ + protected void updateRowHeader(PropertyChangeEvent ev) + { + // TODO: Find out what should be done here. Or is this only a hook? + } + + /** + * Receives notification when the <code>scrollBarDisplayPolicy</code> + * property has changed on the scrollpane. + * + * @param ev the property change event + */ + protected void updateScrollBarDisplayPolicy(PropertyChangeEvent ev) + { + // TODO: Find out what should be done here. Or is this only a hook? + } + + /** + * Receives notification when the <code>viewport</code> property has changed + * on the scrollpane. + * + * This method sets removes the viewportChangeListener from the old viewport + * and adds it to the new viewport. + * + * @param ev the property change event + */ + protected void updateViewport(PropertyChangeEvent ev) + { + JViewport oldViewport = (JViewport) ev.getOldValue(); + oldViewport.removeChangeListener(viewportChangeListener); + JViewport newViewport = (JViewport) ev.getNewValue(); + oldViewport.addChangeListener(viewportChangeListener); + } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicSeparatorUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicSeparatorUI.java index 38c9c7a..97caa3a 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicSeparatorUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicSeparatorUI.java @@ -41,13 +41,11 @@ 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; @@ -121,10 +119,8 @@ public class BasicSeparatorUI extends SeparatorUI */ protected void installDefaults(JSeparator s) { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - - shadow = defaults.getColor("Separator.shadow"); - highlight = defaults.getColor("Separator.highlight"); + shadow = UIManager.getColor("Separator.shadow"); + highlight = UIManager.getColor("Separator.highlight"); s.setOpaque(false); } @@ -165,8 +161,8 @@ public class BasicSeparatorUI extends SeparatorUI /** * 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 + * the shadow color (or left line if it's vertical). The bottom + * or right line will be the highlight 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. @@ -180,9 +176,6 @@ public class BasicSeparatorUI extends SeparatorUI 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; @@ -190,21 +183,24 @@ public class BasicSeparatorUI extends SeparatorUI 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); - } + { + int midAB = r.height / 2; + g.setColor(shadow); + g.drawLine(r.x, r.y + midAB - 1, r.x + r.width, r.y + midAB - 1); + + g.setColor(highlight); + g.fillRect(r.x, r.y + midAB, r.x + r.width, r.y + midAB); + } + else + { + int midAD = r.height / 2 + r.y; + g.setColor(shadow); + g.drawLine(r.x, r.y, r.x, r.y + r.height); + + g.setColor(highlight); + g.fillRect(r.x + midAD, r.y + r.height, r.x + midAD, r.y + r.height); + } + g.setColor(saved); } /** @@ -217,28 +213,14 @@ public class BasicSeparatorUI extends SeparatorUI */ public Dimension getPreferredSize(JComponent c) { - Dimension dims = new Dimension(0, 0); - Insets insets = c.getInsets(); - + Dimension pref = new Dimension(2, 0); 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; - } + pref = new Dimension(0, 2); } - dims.width += insets.left + insets.right; - dims.height += insets.top + insets.bottom; - - return dims; + return pref; } /** @@ -251,7 +233,7 @@ public class BasicSeparatorUI extends SeparatorUI */ public Dimension getMinimumSize(JComponent c) { - return getPreferredSize(c); + return new Dimension(0, 0); } /** @@ -264,6 +246,7 @@ public class BasicSeparatorUI extends SeparatorUI */ public Dimension getMaximumSize(JComponent c) { - return getPreferredSize(c); + return new Dimension(Short.MAX_VALUE, + Short.MAX_VALUE); } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicSliderUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicSliderUI.java index 0b40584..26f5805 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicSliderUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicSliderUI.java @@ -60,13 +60,14 @@ import java.beans.PropertyChangeListener; import java.util.Dictionary; import java.util.Enumeration; +import javax.swing.AbstractAction; import javax.swing.BoundedRangeModel; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JSlider; +import javax.swing.LookAndFeel; 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; @@ -470,6 +471,34 @@ public class BasicSliderUI extends SliderUI } } + /** + * This class is no longer used as of JDK1.3. + */ + public class ActionScroller extends AbstractAction + { + /** + * Not used. + * + * @param slider not used + * @param dir not used + * @param block not used + */ + public ActionScroller(JSlider slider, int dir, boolean block) + { + // Not used. + } + + /** + * Not used. + * + * @param event not used + */ + public void actionPerformed(ActionEvent event) + { + // Not used. + } + } + /** Listener for changes from the model. */ protected ChangeListener changeListener; @@ -680,16 +709,14 @@ public class BasicSliderUI extends SliderUI */ 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")); + LookAndFeel.installColors(slider, "Slider.background", + "Slider.foreground"); + LookAndFeel.installBorder(slider, "Slider.border"); + shadowColor = UIManager.getColor("Slider.shadow"); + highlightColor = UIManager.getColor("Slider.highlight"); + focusColor = UIManager.getColor("Slider.focus"); + focusInsets = UIManager.getInsets("Slider.focusInsets"); slider.setOpaque(true); - focusInsets = defaults.getInsets("Slider.focusInsets"); } /** @@ -1465,7 +1492,7 @@ public class BasicSliderUI extends SliderUI // 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(); + calculateGeometry(); if (slider.getPaintTrack()) paintTrack(g); @@ -1958,7 +1985,7 @@ public class BasicSliderUI extends SliderUI public void paintThumb(Graphics g) { Color saved_color = g.getColor(); - + Point a = new Point(thumbRect.x, thumbRect.y); Point b = new Point(a); Point c = new Point(a); diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicSpinnerUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicSpinnerUI.java index 97ab97b..3b7399e 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicSpinnerUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicSpinnerUI.java @@ -53,9 +53,8 @@ import java.beans.PropertyChangeListener; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JSpinner; +import javax.swing.LookAndFeel; import javax.swing.Timer; -import javax.swing.UIDefaults; -import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.SpinnerUI; @@ -167,16 +166,9 @@ public class BasicSpinnerUI extends SpinnerUI */ 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")); - */ + LookAndFeel.installColorsAndFont(spinner, "Spinner.background", + "Spinner.foreground", "Spinner.font"); + LookAndFeel.installBorder(spinner, "Spinner.border"); spinner.setLayout(createLayout()); spinner.setOpaque(true); } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneDivider.java b/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneDivider.java index b8674ed..69ed2be 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneDivider.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneDivider.java @@ -802,6 +802,7 @@ public class BasicSplitPaneDivider extends Container */ protected DividerLayout() { + // Nothing to do here. } /** diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneUI.java index ef8e228..746f628 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicSplitPaneUI.java @@ -58,7 +58,7 @@ import java.beans.PropertyChangeListener; import javax.swing.JComponent; import javax.swing.JSplitPane; import javax.swing.KeyStroke; -import javax.swing.UIDefaults; +import javax.swing.LookAndFeel; import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.SplitPaneUI; @@ -404,7 +404,7 @@ public class BasicSplitPaneUI extends SplitPaneUI */ 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; @@ -637,7 +637,6 @@ public class BasicSplitPaneUI extends SplitPaneUI int x = insets.left; int h = size; int w = containerSize.width - insets.left - insets.right; - c.setBounds(x, y, w, h); } @@ -817,15 +816,12 @@ public class BasicSplitPaneUI extends SplitPaneUI int newSize = splitPane.getDividerSize(); int[] tmpSizes = layoutManager.getSizes(); dividerSize = tmpSizes[2]; - Component left = splitPane.getLeftComponent(); - Component right = splitPane.getRightComponent(); - int newSpace = newSize - tmpSizes[2]; - + 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)) @@ -942,6 +938,7 @@ public class BasicSplitPaneUI extends SplitPaneUI */ public BasicSplitPaneUI() { + // Nothing to do here. } /** @@ -991,16 +988,16 @@ public class BasicSplitPaneUI extends SplitPaneUI */ protected void installDefaults() { + LookAndFeel.installColors(splitPane, "SplitPane.background", + "SplitPane.foreground"); + LookAndFeel.installBorder(splitPane, "SplitPane.border"); 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.setDividerSize(UIManager.getInt("SplitPane.dividerSize")); splitPane.setOpaque(true); } @@ -1301,15 +1298,41 @@ public class BasicSplitPaneUI extends SplitPaneUI */ public void setDividerLocation(JSplitPane jc, int location) { + location = validLocation(location); + Container p = jc.getParent(); + Dimension rightPrefSize = jc.getRightComponent().getPreferredSize(); + Dimension size = jc.getSize(); + // check if the size has been set for the splitpane + if (size.width == 0 && size.height == 0) + size = jc.getPreferredSize(); + + if (getOrientation() == 0 && location > size.height) + { + location = size.height; + while (p != null) + { + p.setSize(p.getWidth(), p.getHeight() + rightPrefSize.height); + p = p.getParent(); + } + } + else if (location > size.width) + { + location = size.width; + while (p != null) + { + p.setSize(p.getWidth() + rightPrefSize.width, p.getHeight()); + p = p.getParent(); + } + } + setLastDragLocation(getDividerLocation(splitPane)); splitPane.setLastDividerLocation(getDividerLocation(splitPane)); int[] tmpSizes = layoutManager.getSizes(); - tmpSizes[0] = location + tmpSizes[0] = location - layoutManager.getInitialLocation(splitPane.getInsets()); tmpSizes[1] = layoutManager.getAvailableSize(splitPane.getSize(), splitPane.getInsets()) - - tmpSizes[0] - tmpSizes[1]; - + - tmpSizes[0]; layoutManager.setSizes(tmpSizes); splitPane.revalidate(); splitPane.repaint(); @@ -1338,11 +1361,9 @@ public class BasicSplitPaneUI extends SplitPaneUI */ public int getMinimumDividerLocation(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); + int value = layoutManager.getInitialLocation(jc.getInsets()); + if (layoutManager.components[0] != null) + value -= layoutManager.minimumSizeOfComponent(0); return value; } @@ -1388,6 +1409,7 @@ public class BasicSplitPaneUI extends SplitPaneUI */ public void paint(Graphics g, JComponent jc) { + // TODO: What should be done here? } /** @@ -1550,10 +1572,12 @@ public class BasicSplitPaneUI extends SplitPaneUI */ private int validLocation(int location) { - if (location < getMinimumDividerLocation(splitPane)) - return getMinimumDividerLocation(splitPane); - if (location > getMaximumDividerLocation(splitPane)) - return getMaximumDividerLocation(splitPane); + int min = getMinimumDividerLocation(splitPane); + int max = getMaximumDividerLocation(splitPane); + if (min > 0 && location < min) + return min; + if (max > 0 && location > max) + return max; return location; } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTabbedPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTabbedPaneUI.java index 7e9d9b9..ce9ea3e 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicTabbedPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTabbedPaneUI.java @@ -64,9 +64,9 @@ import javax.swing.JPanel; import javax.swing.JTabbedPane; import javax.swing.JViewport; import javax.swing.KeyStroke; +import javax.swing.LookAndFeel; 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; @@ -136,36 +136,36 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants 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; - } + 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); @@ -173,7 +173,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants // 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.setSelectedIndex(index); tabPane.revalidate(); tabPane.repaint(); } @@ -198,15 +198,15 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants { if (e.getPropertyName().equals("tabLayoutPolicy")) { - layoutManager = createLayoutManager(); - - tabPane.setLayout(layoutManager); + layoutManager = createLayoutManager(); + + tabPane.setLayout(layoutManager); } else if (e.getPropertyName().equals("tabPlacement") - && tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) + && tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT) { - incrButton = createIncreaseButton(); - decrButton = createDecreaseButton(); + incrButton = createIncreaseButton(); + decrButton = createDecreaseButton(); } tabPane.layout(); tabPane.repaint(); @@ -245,13 +245,13 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants 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); + 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); } } @@ -275,35 +275,35 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants 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); - } + 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; + 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; + int min = calculateMaxTabHeight(tabPlacement); + height = Math.max(min, componentHeight); + + int tabAreaWidth = preferredTabAreaWidth(tabPlacement, height); + width = tabAreaWidth + componentWidth; } return new Dimension(width, height); @@ -330,7 +330,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants protected void calculateTabRects(int tabPlacement, int tabCount) { if (tabCount == 0) - return; + return; assureRectsCreated(tabCount); FontMetrics fm = getFontMetrics(); @@ -343,113 +343,112 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants 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; - } + 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; - } + 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; @@ -457,62 +456,62 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants normalizeTabRuns(tabPlacement, tabCount, start, max); selectedRun = getRunForTab(tabCount, tabPane.getSelectedIndex()); if (shouldRotateTabRuns(tabPlacement)) - rotateTabRuns(tabPlacement, selectedRun); + 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; - } + 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()); } @@ -565,74 +564,74 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants 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; - } - } + // 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; - } - } + 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; + } + } } } @@ -673,42 +672,42 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants 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; - } + 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; - } + 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; + } } } @@ -736,7 +735,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants protected int preferredTabAreaHeight(int tabPlacement, int width) { if (tabPane.getTabCount() == 0) - return calculateTabAreaHeight(tabPlacement, 0, 0); + return calculateTabAreaHeight(tabPlacement, 0, 0); int runs = 0; int runWidth = 0; @@ -758,14 +757,14 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants // 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; + tabWidth = calculateTabWidth(tabPlacement, i, fm); + if (runWidth + tabWidth > width) + { + runWidth = tabWidth; + runs++; + } + else + runWidth += tabWidth; } runs++; @@ -787,7 +786,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants protected int preferredTabAreaWidth(int tabPlacement, int height) { if (tabPane.getTabCount() == 0) - return calculateTabAreaHeight(tabPlacement, 0, 0); + return calculateTabAreaHeight(tabPlacement, 0, 0); int runs = 0; int runHeight = 0; @@ -804,14 +803,14 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants for (int i = 0; i < tabPane.getTabCount(); i++) { - tabHeight = calculateTabHeight(tabPlacement, i, fontHeight); - if (runHeight + tabHeight > height) - { - runHeight = tabHeight; - runs++; - } - else - runHeight += tabHeight; + tabHeight = calculateTabHeight(tabPlacement, i, fontHeight); + if (runHeight + tabHeight > height) + { + runHeight = tabHeight; + runs++; + } + else + runHeight += tabHeight; } runs++; @@ -831,19 +830,19 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants protected void rotateTabRuns(int tabPlacement, int selectedRun) { if (runCount == 1 || selectedRun == 1 || selectedRun == -1) - return; + return; int[] newTabRuns = new int[tabRuns.length]; int currentRun = selectedRun; int i = 1; do { - newTabRuns[i] = tabRuns[currentRun]; - currentRun = getNextTabRun(currentRun); - i++; + newTabRuns[i] = tabRuns[currentRun]; + currentRun = getNextTabRun(currentRun); + i++; } while (i < runCount); if (runCount > 1) - newTabRuns[0] = tabRuns[currentRun]; + newTabRuns[0] = tabRuns[currentRun]; tabRuns = newTabRuns; BasicTabbedPaneUI.this.selectedRun = 1; @@ -902,7 +901,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants protected int preferredTabAreaHeight(int tabPlacement, int width) { if (tabPane.getTabCount() == 0) - return calculateTabAreaHeight(tabPlacement, 0, 0); + return calculateTabAreaHeight(tabPlacement, 0, 0); int runs = 1; @@ -923,7 +922,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants protected int preferredTabAreaWidth(int tabPlacement, int height) { if (tabPane.getTabCount() == 0) - return calculateTabAreaHeight(tabPlacement, 0, 0); + return calculateTabAreaHeight(tabPlacement, 0, 0); int runs = 1; @@ -944,7 +943,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants protected void calculateTabRects(int tabPlacement, int tabCount) { if (tabCount == 0) - return; + return; assureRectsCreated(tabCount); FontMetrics fm = getFontMetrics(); @@ -958,76 +957,76 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants 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; - } + 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; - } + 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; @@ -1047,68 +1046,68 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants int tabCount = tabPane.getTabCount(); Point p = null; if (tabCount == 0) - return; + 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 (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(); - } + 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); + 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(); @@ -1160,7 +1159,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants */ public void paint(Graphics g, JComponent c) { - paintTabArea(g, tabPane.getTabPlacement(), tabPane.getSelectedIndex()); + paintTabArea(g, tabPane.getTabPlacement(), tabPane.getSelectedIndex()); } } @@ -1182,6 +1181,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants */ private class ScrollingViewport extends JViewport implements UIResource { + // TODO: Maybe remove this inner class. } /** @@ -1407,22 +1407,22 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants 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; - } + 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; - } + 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); @@ -1451,16 +1451,16 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants super.installUI(c); if (c instanceof JTabbedPane) { - tabPane = (JTabbedPane) c; - - installComponents(); - installDefaults(); - installListeners(); - installKeyboardActions(); - - layoutManager = createLayoutManager(); - tabPane.setLayout(layoutManager); - tabPane.layout(); + tabPane = (JTabbedPane) c; + + installComponents(); + installDefaults(); + installListeners(); + installKeyboardActions(); + + layoutManager = createLayoutManager(); + tabPane.setLayout(layoutManager); + tabPane.layout(); } } @@ -1495,23 +1495,23 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants 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(); + 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(); } } @@ -1536,28 +1536,26 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants */ 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")); + LookAndFeel.installColorsAndFont(tabPane, "TabbedPane.background", + "TabbedPane.foreground", + "TabbedPane.font"); tabPane.setOpaque(false); - highlight = defaults.getColor("TabbedPane.highlight"); - lightHighlight = defaults.getColor("TabbedPane.lightHighlight"); + highlight = UIManager.getColor("TabbedPane.highlight"); + lightHighlight = UIManager.getColor("TabbedPane.lightHighlight"); - shadow = defaults.getColor("TabbedPane.shadow"); - darkShadow = defaults.getColor("TabbedPane.darkShadow"); + shadow = UIManager.getColor("TabbedPane.shadow"); + darkShadow = UIManager.getColor("TabbedPane.darkShadow"); - focus = defaults.getColor("TabbedPane.focus"); + focus = UIManager.getColor("TabbedPane.focus"); - textIconGap = defaults.getInt("TabbedPane.textIconGap"); - tabRunOverlay = defaults.getInt("TabbedPane.tabRunOverlay"); + textIconGap = UIManager.getInt("TabbedPane.textIconGap"); + tabRunOverlay = UIManager.getInt("TabbedPane.tabRunOverlay"); - tabInsets = defaults.getInsets("TabbedPane.tabbedPaneTabInsets"); - selectedTabPadInsets = defaults.getInsets("TabbedPane.tabbedPaneTabPadInsets"); - tabAreaInsets = defaults.getInsets("TabbedPane.tabbedPaneTabAreaInsets"); - contentBorderInsets = defaults.getInsets("TabbedPane.tabbedPaneContentBorderInsets"); + tabInsets = UIManager.getInsets("TabbedPane.tabbedPaneTabInsets"); + selectedTabPadInsets = UIManager.getInsets("TabbedPane.tabbedPaneTabPadInsets"); + tabAreaInsets = UIManager.getInsets("TabbedPane.tabbedPaneTabAreaInsets"); + contentBorderInsets = UIManager.getInsets("TabbedPane.tabbedPaneContentBorderInsets"); calcRect = new Rectangle(); tabRuns = new int[10]; @@ -1737,38 +1735,42 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants // we WANT to paint the outermost run first and then work our way in. int tabCount = tabPane.getTabCount(); int currRun = 1; + + if (tabCount > runCount) + runCount = tabCount; + if (tabCount < 1) return; - + if (runCount > 1) - currRun = 0; + 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); + 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); @@ -1800,24 +1802,24 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants 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; - } + 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, @@ -1856,7 +1858,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants SwingConstants.CENTER, SwingConstants.CENTER, SwingConstants.CENTER, - SwingConstants.CENTER, tabRect, + SwingConstants.RIGHT, tabRect, iconRect, textRect, textIconGap); int shiftX = getTabLabelShiftX(tabPlacement, tabIndex, isSelected); @@ -1904,8 +1906,8 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants View textView = getTextViewForTab(tabIndex); if (textView != null) { - textView.paint(g, textRect); - return; + textView.paint(g, textRect); + return; } Color fg = tabPane.getForegroundAt(tabIndex); @@ -1921,37 +1923,37 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants if (tabPane.isEnabledAt(tabIndex)) { - g.setColor(fg); + g.setColor(fg); - int mnemIndex = tabPane.getDisplayedMnemonicIndexAt(tabIndex); + 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()); + 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(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); @@ -2037,30 +2039,30 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants 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); + 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); + 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); + 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(lightHighlight); + g.drawLine(x, y, x + w, y); } g.setColor(saved); @@ -2087,10 +2089,10 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants g.setColor(Color.LIGHT_GRAY); else { - Color bg = tabPane.getBackgroundAt(tabIndex); - if (bg == null) - bg = Color.GRAY; - g.setColor(bg); + Color bg = tabPane.getBackgroundAt(tabIndex); + if (bg == null) + bg = Color.GRAY; + g.setColor(bg); } g.fillRect(x, y, w, h); @@ -2144,14 +2146,14 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants 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); + 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); @@ -2184,14 +2186,14 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants 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); + 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); @@ -2223,26 +2225,26 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants 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); + 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(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); @@ -2271,26 +2273,26 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants 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); + 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(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); @@ -2337,16 +2339,16 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants 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); + 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; } @@ -2400,10 +2402,10 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants return; else { - int numToCopy = Math.min(tabCount, rects.length); - Rectangle[] tmp = new Rectangle[tabCount]; - System.arraycopy(rects, 0, tmp, 0, numToCopy); - rects = tmp; + int numToCopy = Math.min(tabCount, rects.length); + Rectangle[] tmp = new Rectangle[tabCount]; + System.arraycopy(rects, 0, tmp, 0, numToCopy); + rects = tmp; } } @@ -2418,9 +2420,9 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants tabRuns = new int[10]; else { - int[] newRuns = new int[tabRuns.length + 10]; - System.arraycopy(tabRuns, 0, newRuns, 0, tabRuns.length); - tabRuns = newRuns; + int[] newRuns = new int[tabRuns.length + 10]; + System.arraycopy(tabRuns, 0, newRuns, 0, tabRuns.length); + tabRuns = newRuns; } } @@ -2438,12 +2440,12 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants 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; + 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; } @@ -2560,21 +2562,22 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants Icon icon = getIconForTab(tabIndex); Insets insets = getTabInsets(tabPlacement, tabIndex); + int height = 0; 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); + 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()); + height = tr.union(ir).height; } else - calcRect.height = fontHeight; + height = fontHeight; - calcRect.height += insets.top + insets.bottom; - return calcRect.height; + height += insets.top + insets.bottom; + return height; } /** @@ -2614,21 +2617,22 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants Icon icon = getIconForTab(tabIndex); Insets insets = getTabInsets(tabPlacement, tabIndex); + int width = 0; 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); + 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()); + width = tr.union(ir).width; } else - calcRect.width = metrics.stringWidth(tabPane.getTitleAt(tabIndex)); + width = metrics.stringWidth(tabPane.getTitleAt(tabIndex)); - calcRect.width += insets.left + insets.right; - return calcRect.width; + width += insets.left + insets.right; + return width; } /** @@ -2775,37 +2779,37 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants 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 (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); - } + 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); + } } } @@ -2869,16 +2873,16 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants 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; - } + { + 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) @@ -3042,31 +3046,31 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants // 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; - } + { + 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 index 700b406..ec0467a 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicTableHeaderUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTableHeaderUI.java @@ -46,7 +46,7 @@ import java.awt.event.MouseEvent; import javax.swing.CellRendererPane; import javax.swing.JComponent; -import javax.swing.UIDefaults; +import javax.swing.LookAndFeel; import javax.swing.UIManager; import javax.swing.border.Border; import javax.swing.event.MouseInputListener; @@ -57,8 +57,7 @@ import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; -public class BasicTableHeaderUI - extends TableHeaderUI +public class BasicTableHeaderUI extends TableHeaderUI { public static ComponentUI createUI(JComponent h) @@ -71,16 +70,42 @@ public class BasicTableHeaderUI protected CellRendererPane rendererPane; protected Border cellBorder; - class MouseInputHandler - implements MouseInputListener + public 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) {} + public void mouseClicked(MouseEvent e) + { + // TODO: Implement this properly. + } + + public void mouseDragged(MouseEvent e) + { + // TODO: Implement this properly. + } + + public void mouseEntered(MouseEvent e) + { + // TODO: Implement this properly. + } + + public void mouseExited(MouseEvent e) + { + // TODO: Implement this properly. + } + + public void mouseMoved(MouseEvent e) + { + // TODO: Implement this properly. + } + + public void mousePressed(MouseEvent e) + { + // TODO: Implement this properly. + } + + public void mouseReleased(MouseEvent e) + { + // TODO: Implement this properly. + } } protected MouseInputListener createMouseInputListener() @@ -95,15 +120,15 @@ public class BasicTableHeaderUI 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"); + LookAndFeel.installColorsAndFont(header, "TableHeader.background", + "TableHeader.foreground", + "TableHeader.font"); + cellBorder = UIManager.getBorder("TableHeader.cellBorder"); } protected void installKeyboardActions() { + // TODO: Implement this properly. } protected void installListeners() @@ -128,6 +153,7 @@ public class BasicTableHeaderUI protected void uninstallKeyboardActions() { + // TODO: Implement this properly. } protected void uninstallListeners() @@ -157,6 +183,7 @@ public class BasicTableHeaderUI Rectangle bounds = header.getHeaderRect(i); if (bounds.intersects(clip)) { + Rectangle oldClip = gfx.getClipBounds(); TableColumn col = cmod.getColumn(i); TableCellRenderer rend = col.getHeaderRenderer(); if (rend == null) @@ -173,10 +200,12 @@ public class BasicTableHeaderUI if (comp instanceof JComponent) ((JComponent)comp).setBorder(cellBorder); gfx.translate(bounds.x, bounds.y); + gfx.setClip(0, 0, bounds.width, bounds.height); comp.setSize(bounds.width, bounds.height); comp.setLocation(0,0); comp.paint(gfx); gfx.translate(-bounds.x, -bounds.y); + gfx.setClip(oldClip); } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTableUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTableUI.java index 4559937..25a845b 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicTableUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTableUI.java @@ -49,35 +49,38 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; -import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import javax.swing.AbstractAction; import javax.swing.ActionMap; -import javax.swing.BorderFactory; import javax.swing.CellRendererPane; +import javax.swing.DefaultListSelectionModel; import javax.swing.InputMap; import javax.swing.JComponent; import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.KeyStroke; import javax.swing.ListSelectionModel; +import javax.swing.LookAndFeel; import javax.swing.UIDefaults; import javax.swing.UIManager; import javax.swing.border.Border; import javax.swing.event.ChangeEvent; import javax.swing.event.MouseInputListener; +import javax.swing.plaf.ActionMapUIResource; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.InputMapUIResource; import javax.swing.plaf.TableUI; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; +import javax.swing.table.TableModel; -public class BasicTableUI - extends TableUI +public class BasicTableUI extends TableUI { public static ComponentUI createUI(JComponent comp) { @@ -93,23 +96,72 @@ public class BasicTableUI /** The normal cell border. */ Border cellBorder; - /** The cell border for selected/highlighted cells. */ - Border highlightCellBorder; - /** The action bound to KeyStrokes. */ TableAction action; - class FocusHandler implements FocusListener + /** + * Listens for changes to the tables properties. + */ + private PropertyChangeListener propertyChangeListener; + + /** + * Handles key events for the JTable. Key events should be handled through + * the InputMap/ActionMap mechanism since JDK1.3. This class is only there + * for backwards compatibility. + * + * @author Roman Kennke (kennke@aicas.com) + */ + public class KeyHandler implements KeyListener + { + + /** + * Receives notification that a key has been pressed and released. + * + * @param event the key event + */ + public void keyTyped(KeyEvent event) + { + // Key events should be handled through the InputMap/ActionMap mechanism + // since JDK1.3. This class is only there for backwards compatibility. + } + + /** + * Receives notification that a key has been pressed. + * + * @param event the key event + */ + public void keyPressed(KeyEvent event) + { + // Key events should be handled through the InputMap/ActionMap mechanism + // since JDK1.3. This class is only there for backwards compatibility. + } + + /** + * Receives notification that a key has been released. + * + * @param event the key event + */ + public void keyReleased(KeyEvent event) + { + // Key events should be handled through the InputMap/ActionMap mechanism + // since JDK1.3. This class is only there for backwards compatibility. + } + } + + public class FocusHandler implements FocusListener { public void focusGained(FocusEvent e) { + // TODO: Implement this properly. } + public void focusLost(FocusEvent e) { + // TODO: Implement this properly. } } - class MouseInputHandler implements MouseInputListener + public class MouseInputHandler implements MouseInputListener { Point begin, curr; @@ -145,54 +197,123 @@ public class BasicTableUI public void mouseClicked(MouseEvent e) { + // TODO: What should be done here, if anything? } + public void mouseDragged(MouseEvent e) { - curr = new Point(e.getX(), e.getY()); - updateSelection(e.isControlDown()); + if (table.isEnabled()) + { + curr = new Point(e.getX(), e.getY()); + updateSelection(e.isControlDown()); + } } + public void mouseEntered(MouseEvent e) { + // TODO: What should be done here, if anything? } + public void mouseExited(MouseEvent e) { + // TODO: What should be done here, if anything? } + public void mouseMoved(MouseEvent e) { + // TODO: What should be done here, if anything? } + public void mousePressed(MouseEvent e) { - ListSelectionModel rowModel = table.getSelectionModel(); - ListSelectionModel colModel = table.getColumnModel().getSelectionModel(); - int rowLead = rowModel.getLeadSelectionIndex(); - int colLead = colModel.getLeadSelectionIndex(); + if (table.isEnabled()) + { + ListSelectionModel rowModel = table.getSelectionModel(); + ListSelectionModel colModel = table.getColumnModel().getSelectionModel(); + int rowLead = rowModel.getLeadSelectionIndex(); + int colLead = colModel.getLeadSelectionIndex(); - 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()); + 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()); - // If we were editing, but the moved to another cell, stop editing - if (rowLead != rowModel.getLeadSelectionIndex() || - colLead != colModel.getLeadSelectionIndex()) - if (table.isEditing()) - table.editingStopped(new ChangeEvent(e)); + // If we were editing, but the moved to another cell, stop editing + if (rowLead != rowModel.getLeadSelectionIndex() || + colLead != colModel.getLeadSelectionIndex()) + if (table.isEditing()) + table.editingStopped(new ChangeEvent(e)); + } } + public void mouseReleased(MouseEvent e) { - begin = null; - curr = null; + if (table.isEnabled()) + { + begin = null; + curr = null; + } + } + } + + /** + * Listens for changes to the model property of the JTable and adjusts some + * settings. + * + * @author Roman Kennke (kennke@aicas.com) + */ + private class PropertyChangeHandler implements PropertyChangeListener + { + /** + * Receives notification if one of the JTable's properties changes. + * + * @param ev the property change event + */ + public void propertyChange(PropertyChangeEvent ev) + { + String propName = ev.getPropertyName(); + if (propName.equals("model")) + { + ListSelectionModel rowSel = table.getSelectionModel(); + rowSel.clearSelection(); + ListSelectionModel colSel = table.getColumnModel().getSelectionModel(); + colSel.clearSelection(); + TableModel model = table.getModel(); + + // Adjust lead and anchor selection indices of the row and column + // selection models. + if (model.getRowCount() > 0) + { + rowSel.setAnchorSelectionIndex(0); + rowSel.setLeadSelectionIndex(0); + } + else + { + rowSel.setAnchorSelectionIndex(-1); + rowSel.setLeadSelectionIndex(-1); + } + if (model.getColumnCount() > 0) + { + colSel.setAnchorSelectionIndex(0); + colSel.setLeadSelectionIndex(0); + } + else + { + colSel.setAnchorSelectionIndex(-1); + colSel.setLeadSelectionIndex(-1); + } + } } } @@ -206,6 +327,17 @@ public class BasicTableUI return new MouseInputHandler(); } + + /** + * Creates and returns a key listener for the JTable. + * + * @return a key listener for the JTable + */ + protected KeyListener createKeyListener() + { + return new KeyHandler(); + } + /** * Return the maximum size of the table. The maximum height is the row * height times the number of rows. The maximum width is the sum of @@ -255,47 +387,13 @@ public class BasicTableUI 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")); + LookAndFeel.installColorsAndFont(table, "Table.background", + "Table.foreground", "Table.font"); + table.setGridColor(UIManager.getColor("Table.gridColor")); + table.setSelectionForeground(UIManager.getColor("Table.selectionForeground")); + table.setSelectionBackground(UIManager.getColor("Table.selectionBackground")); table.setOpaque(true); - - highlightCellBorder = defaults.getBorder("Table.focusCellHighlightBorder"); - cellBorder = BorderFactory.createEmptyBorder(1, 1, 1, 1); - } - - private int convertModifiers(int mod) - { - if ((mod & KeyEvent.SHIFT_DOWN_MASK) != 0) - { - mod |= KeyEvent.SHIFT_MASK; - mod &= ~KeyEvent.SHIFT_DOWN_MASK; - } - if ((mod & KeyEvent.CTRL_DOWN_MASK) != 0) - { - mod |= KeyEvent.CTRL_MASK; - mod &= ~KeyEvent.CTRL_DOWN_MASK; - } - if ((mod & KeyEvent.META_DOWN_MASK) != 0) - { - mod |= KeyEvent.META_MASK; - mod &= ~KeyEvent.META_DOWN_MASK; - } - if ((mod & KeyEvent.ALT_DOWN_MASK) != 0) - { - mod |= KeyEvent.ALT_MASK; - mod &= ~KeyEvent.ALT_DOWN_MASK; - } - if ((mod & KeyEvent.ALT_GRAPH_DOWN_MASK) != 0) - { - mod |= KeyEvent.ALT_GRAPH_MASK; - mod &= ~KeyEvent.ALT_GRAPH_DOWN_MASK; - } - return mod; + rendererPane = new CellRendererPane(); } protected void installKeyboardActions() @@ -304,27 +402,21 @@ public class BasicTableUI InputMap ancestorMap = (InputMap)defaults.get("Table.ancestorInputMap"); InputMapUIResource parentInputMap = new InputMapUIResource(); // FIXME: The JDK uses a LazyActionMap for parentActionMap - ActionMap parentActionMap = new ActionMap(); + ActionMap parentActionMap = new ActionMapUIResource(); action = new TableAction(); Object keys[] = ancestorMap.allKeys(); // Register key bindings in the UI InputMap-ActionMap pair - // Note that we register key bindings with both the old and new modifier - // masks: InputEvent.SHIFT_MASK and InputEvent.SHIFT_DOWN_MASK and so on. for (int i = 0; i < keys.length; i++) { - parentInputMap.put(KeyStroke.getKeyStroke - (((KeyStroke)keys[i]).getKeyCode(), convertModifiers - (((KeyStroke)keys[i]).getModifiers())), - (String)ancestorMap.get((KeyStroke)keys[i])); + KeyStroke stroke = (KeyStroke)keys[i]; + String actionString = (String) ancestorMap.get(stroke); - parentInputMap.put(KeyStroke.getKeyStroke - (((KeyStroke)keys[i]).getKeyCode(), - ((KeyStroke)keys[i]).getModifiers()), - (String)ancestorMap.get((KeyStroke)keys[i])); + parentInputMap.put(KeyStroke.getKeyStroke(stroke.getKeyCode(), + stroke.getModifiers()), + actionString); - parentActionMap.put - ((String)ancestorMap.get((KeyStroke)keys[i]), new ActionListenerProxy - (action, (String)ancestorMap.get((KeyStroke)keys[i]))); + parentActionMap.put (actionString, + new ActionListenerProxy (action, actionString)); } // Set the UI InputMap-ActionMap pair to be the parents of the @@ -383,8 +475,8 @@ public class BasicTableUI */ public void actionPerformed (ActionEvent e) { - ListSelectionModel rowModel = table.getSelectionModel(); - ListSelectionModel colModel = table.getColumnModel().getSelectionModel(); + DefaultListSelectionModel rowModel = (DefaultListSelectionModel) table.getSelectionModel(); + DefaultListSelectionModel colModel = (DefaultListSelectionModel) table.getColumnModel().getSelectionModel(); int rowLead = rowModel.getLeadSelectionIndex(); int rowMax = table.getModel().getRowCount() - 1; @@ -392,74 +484,75 @@ public class BasicTableUI int colLead = colModel.getLeadSelectionIndex(); int colMax = table.getModel().getColumnCount() - 1; - if (e.getActionCommand().equals("selectPreviousRowExtendSelection")) + String command = e.getActionCommand(); + + if (command.equals("selectPreviousRowExtendSelection")) { rowModel.setLeadSelectionIndex(Math.max(rowLead - 1, 0)); colModel.setLeadSelectionIndex(colLead); } - else if (e.getActionCommand().equals("selectLastColumn")) + else if (command.equals("selectLastColumn")) { - table.clearSelection(); rowModel.setSelectionInterval(rowLead, rowLead); colModel.setSelectionInterval(colMax, colMax); } - else if (e.getActionCommand().equals("startEditing")) + else if (command.equals("startEditing")) { if (table.isCellEditable(rowLead, colLead)) table.editCellAt(rowLead,colLead); } - else if (e.getActionCommand().equals("selectFirstRowExtendSelection")) + else if (command.equals("selectFirstRowExtendSelection")) { rowModel.setLeadSelectionIndex(0); colModel.setLeadSelectionIndex(colLead); } - else if (e.getActionCommand().equals("selectFirstColumn")) + else if (command.equals("selectFirstColumn")) { rowModel.setSelectionInterval(rowLead, rowLead); colModel.setSelectionInterval(0, 0); } - else if (e.getActionCommand().equals("selectFirstColumnExtendSelection")) + else if (command.equals("selectFirstColumnExtendSelection")) { colModel.setLeadSelectionIndex(0); rowModel.setLeadSelectionIndex(rowLead); - } - else if (e.getActionCommand().equals("selectLastRow")) + } + else if (command.equals("selectLastRow")) { rowModel.setSelectionInterval(rowMax,rowMax); colModel.setSelectionInterval(colLead, colLead); } - else if (e.getActionCommand().equals("selectNextRowExtendSelection")) + else if (command.equals("selectNextRowExtendSelection")) { rowModel.setLeadSelectionIndex(Math.min(rowLead + 1, rowMax)); colModel.setLeadSelectionIndex(colLead); } - else if (e.getActionCommand().equals("selectFirstRow")) + else if (command.equals("selectFirstRow")) { rowModel.setSelectionInterval(0,0); colModel.setSelectionInterval(colLead, colLead); } - else if (e.getActionCommand().equals("selectNextColumnExtendSelection")) + else if (command.equals("selectNextColumnExtendSelection")) { colModel.setLeadSelectionIndex(Math.min(colLead + 1, colMax)); rowModel.setLeadSelectionIndex(rowLead); } - else if (e.getActionCommand().equals("selectLastColumnExtendSelection")) + else if (command.equals("selectLastColumnExtendSelection")) { colModel.setLeadSelectionIndex(colMax); rowModel.setLeadSelectionIndex(rowLead); } - else if (e.getActionCommand().equals("selectPreviousColumnExtendSelection")) + else if (command.equals("selectPreviousColumnExtendSelection")) { colModel.setLeadSelectionIndex(Math.max(colLead - 1, 0)); rowModel.setLeadSelectionIndex(rowLead); } - else if (e.getActionCommand().equals("selectNextRow")) + else if (command.equals("selectNextRow")) { rowModel.setSelectionInterval(Math.min(rowLead + 1, rowMax), Math.min(rowLead + 1, rowMax)); colModel.setSelectionInterval(colLead,colLead); } - else if (e.getActionCommand().equals("scrollUpExtendSelection")) + else if (command.equals("scrollUpExtendSelection")) { int target; if (rowLead == getFirstVisibleRowIndex()) @@ -472,13 +565,13 @@ public class BasicTableUI rowModel.setLeadSelectionIndex(target); colModel.setLeadSelectionIndex(colLead); } - else if (e.getActionCommand().equals("selectPreviousRow")) + else if (command.equals("selectPreviousRow")) { rowModel.setSelectionInterval(Math.max(rowLead - 1, 0), Math.max(rowLead - 1, 0)); colModel.setSelectionInterval(colLead,colLead); } - else if (e.getActionCommand().equals("scrollRightChangeSelection")) + else if (command.equals("scrollRightChangeSelection")) { int target; if (colLead == getLastVisibleColumnIndex()) @@ -491,13 +584,13 @@ public class BasicTableUI colModel.setSelectionInterval(target, target); rowModel.setSelectionInterval(rowLead, rowLead); } - else if (e.getActionCommand().equals("selectPreviousColumn")) + else if (command.equals("selectPreviousColumn")) { rowModel.setSelectionInterval(rowLead,rowLead); colModel.setSelectionInterval(Math.max(colLead - 1, 0), Math.max(colLead - 1, 0)); } - else if (e.getActionCommand().equals("scrollLeftChangeSelection")) + else if (command.equals("scrollLeftChangeSelection")) { int target; if (colLead == getFirstVisibleColumnIndex()) @@ -510,11 +603,11 @@ public class BasicTableUI colModel.setSelectionInterval(target, target); rowModel.setSelectionInterval(rowLead, rowLead); } - else if (e.getActionCommand().equals("clearSelection")) + else if (command.equals("clearSelection")) { table.clearSelection(); } - else if (e.getActionCommand().equals("cancel")) + else if (command.equals("cancel")) { // FIXME: implement other parts of "cancel" like undo-ing last // selection. Right now it just calls editingCancelled if @@ -522,10 +615,10 @@ public class BasicTableUI if (table.isEditing()) table.editingCanceled(new ChangeEvent("cancel")); } - else if (e.getActionCommand().equals("selectNextRowCell") - || e.getActionCommand().equals("selectPreviousRowCell") - || e.getActionCommand().equals("selectNextColumnCell") - || e.getActionCommand().equals("selectPreviousColumnCell")) + else if (command.equals("selectNextRowCell") + || command.equals("selectPreviousRowCell") + || command.equals("selectNextColumnCell") + || command.equals("selectPreviousColumnCell")) { // If nothing is selected, select the first cell in the table if (table.getSelectedRowCount() == 0 && @@ -561,13 +654,13 @@ public class BasicTableUI // when you get to the edges of the table. if (!multColsSelected && !multRowsSelected) { - if (e.getActionCommand().indexOf("Column") != -1) + if (command.indexOf("Column") != -1) advanceSingleSelection(colModel, colMax, rowModel, rowMax, - (e.getActionCommand().equals + (command.equals ("selectPreviousColumnCell"))); else advanceSingleSelection(rowModel, rowMax, colModel, colMax, - (e.getActionCommand().equals + (command.equals ("selectPreviousRowCell"))); return; } @@ -588,25 +681,25 @@ public class BasicTableUI // If there are multiple rows and columns selected, select the next // cell and wrap at the edges of the selection. - if (e.getActionCommand().indexOf("Column") != -1) + if (command.indexOf("Column") != -1) advanceMultipleSelection(colModel, colMinSelected, colMaxSelected, rowModel, rowMinSelected, rowMaxSelected, - (e.getActionCommand().equals + (command.equals ("selectPreviousColumnCell")), true); else advanceMultipleSelection(rowModel, rowMinSelected, rowMaxSelected, colModel, colMinSelected, colMaxSelected, - (e.getActionCommand().equals + (command.equals ("selectPreviousRowCell")), false); } - else if (e.getActionCommand().equals("selectNextColumn")) + else if (command.equals("selectNextColumn")) { rowModel.setSelectionInterval(rowLead,rowLead); colModel.setSelectionInterval(Math.min(colLead + 1, colMax), Math.min(colLead + 1, colMax)); } - else if (e.getActionCommand().equals("scrollLeftExtendSelection")) + else if (command.equals("scrollLeftExtendSelection")) { int target; if (colLead == getFirstVisibleColumnIndex()) @@ -619,7 +712,7 @@ public class BasicTableUI colModel.setLeadSelectionIndex(target); rowModel.setLeadSelectionIndex(rowLead); } - else if (e.getActionCommand().equals("scrollDownChangeSelection")) + else if (command.equals("scrollDownChangeSelection")) { int target; if (rowLead == getLastVisibleRowIndex()) @@ -632,7 +725,7 @@ public class BasicTableUI rowModel.setSelectionInterval(target, target); colModel.setSelectionInterval(colLead, colLead); } - else if (e.getActionCommand().equals("scrollRightExtendSelection")) + else if (command.equals("scrollRightExtendSelection")) { int target; if (colLead == getLastVisibleColumnIndex()) @@ -645,16 +738,16 @@ public class BasicTableUI colModel.setLeadSelectionIndex(target); rowModel.setLeadSelectionIndex(rowLead); } - else if (e.getActionCommand().equals("selectAll")) + else if (command.equals("selectAll")) { table.selectAll(); } - else if (e.getActionCommand().equals("selectLastRowExtendSelection")) + else if (command.equals("selectLastRowExtendSelection")) { rowModel.setLeadSelectionIndex(rowMax); colModel.setLeadSelectionIndex(colLead); } - else if (e.getActionCommand().equals("scrollDownExtendSelection")) + else if (command.equals("scrollDownExtendSelection")) { int target; if (rowLead == getLastVisibleRowIndex()) @@ -666,8 +759,8 @@ public class BasicTableUI rowModel.setLeadSelectionIndex(target); colModel.setLeadSelectionIndex(colLead); - } - else if (e.getActionCommand().equals("scrollUpChangeSelection")) + } + else if (command.equals("scrollUpChangeSelection")) { int target; if (rowLead == getFirstVisibleRowIndex()) @@ -680,22 +773,119 @@ public class BasicTableUI rowModel.setSelectionInterval(target, target); colModel.setSelectionInterval(colLead, colLead); } + else if (command.equals("selectNextRowChangeLead")) + { + if (rowModel.getSelectionMode() != ListSelectionModel.MULTIPLE_INTERVAL_SELECTION) + { + // just "selectNextRow" + rowModel.setSelectionInterval(Math.min(rowLead + 1, rowMax), + Math.min(rowLead + 1, rowMax)); + colModel.setSelectionInterval(colLead,colLead); + } + else + rowModel.moveLeadSelectionIndex(Math.min(rowLead + 1, rowMax)); + } + else if (command.equals("selectPreviousRowChangeLead")) + { + if (rowModel.getSelectionMode() != ListSelectionModel.MULTIPLE_INTERVAL_SELECTION) + { + // just selectPreviousRow + rowModel.setSelectionInterval(Math.max(rowLead - 1, 0), + Math.min(rowLead -1, 0)); + colModel.setSelectionInterval(colLead,colLead); + } + else + rowModel.moveLeadSelectionIndex(Math.max(rowLead - 1, 0)); + } + else if (command.equals("selectNextColumnChangeLead")) + { + if (colModel.getSelectionMode() != ListSelectionModel.MULTIPLE_INTERVAL_SELECTION) + { + // just selectNextColumn + rowModel.setSelectionInterval(rowLead,rowLead); + colModel.setSelectionInterval(Math.min(colLead + 1, colMax), + Math.min(colLead + 1, colMax)); + } + else + colModel.moveLeadSelectionIndex(Math.min(colLead + 1, colMax)); + } + else if (command.equals("selectPreviousColumnChangeLead")) + { + if (colModel.getSelectionMode() != ListSelectionModel.MULTIPLE_INTERVAL_SELECTION) + { + // just selectPreviousColumn + rowModel.setSelectionInterval(rowLead,rowLead); + colModel.setSelectionInterval(Math.max(colLead - 1, 0), + Math.max(colLead - 1, 0)); + + } + else + colModel.moveLeadSelectionIndex(Math.max(colLead - 1, 0)); + } + else if (command.equals("addToSelection")) + { + if (!table.isEditing()) + { + int oldRowAnchor = rowModel.getAnchorSelectionIndex(); + int oldColAnchor = colModel.getAnchorSelectionIndex(); + rowModel.addSelectionInterval(rowLead, rowLead); + colModel.addSelectionInterval(colLead, colLead); + rowModel.setAnchorSelectionIndex(oldRowAnchor); + colModel.setAnchorSelectionIndex(oldColAnchor); + } + } + else if (command.equals("extendTo")) + { + rowModel.setSelectionInterval(rowModel.getAnchorSelectionIndex(), + rowLead); + colModel.setSelectionInterval(colModel.getAnchorSelectionIndex(), + colLead); + } + else if (command.equals("toggleAndAnchor")) + { + if (rowModel.isSelectedIndex(rowLead)) + rowModel.removeSelectionInterval(rowLead, rowLead); + else + rowModel.addSelectionInterval(rowLead, rowLead); + + if (colModel.isSelectedIndex(colLead)) + colModel.removeSelectionInterval(colLead, colLead); + else + colModel.addSelectionInterval(colLead, colLead); + + rowModel.setAnchorSelectionIndex(rowLead); + colModel.setAnchorSelectionIndex(colLead); + } else { // If we're here that means we bound this TableAction class // to a keyboard input but we either want to ignore that input // or we just haven't implemented its action yet. + + // Uncomment the following line to print the names of unused bindings + // when their keys are pressed + + // System.out.println ("not implemented: "+e.getActionCommand()); } - if (table.isEditing() && e.getActionCommand() != "startEditing") - table.editingCanceled(new ChangeEvent("update")); - table.repaint(); - + // Any commands whose keyStrokes should be used by the Editor should not + // cause editing to be stopped: ie, the SPACE sends "addToSelection" but + // if the table is in editing mode, the space should not cause us to stop + // editing because it should be used by the Editor. + if (table.isEditing() && command != "startEditing" + && command != "addToSelection") + table.editingStopped(new ChangeEvent("update")); + table.scrollRectToVisible (table.getCellRect(rowModel.getLeadSelectionIndex(), colModel.getLeadSelectionIndex(), false)); + table.repaint(); } + /** + * Returns the column index of the first visible column. + * @return the column index of the first visible column. + */ int getFirstVisibleColumnIndex() { ComponentOrientation or = table.getComponentOrientation(); @@ -922,10 +1112,19 @@ public class BasicTableUI protected void installListeners() { - table.addFocusListener(focusListener); + if (focusListener == null) + focusListener = createFocusListener(); + table.addFocusListener(focusListener); + if (keyListener == null) + keyListener = createKeyListener(); table.addKeyListener(keyListener); + if (mouseInputListener == null) + mouseInputListener = createMouseInputListener(); table.addMouseListener(mouseInputListener); table.addMouseMotionListener(mouseInputListener); + if (propertyChangeListener == null) + propertyChangeListener = new PropertyChangeHandler(); + table.addPropertyChangeListener(propertyChangeListener); } protected void uninstallDefaults() @@ -950,6 +1149,7 @@ public class BasicTableUI protected void uninstallKeyboardActions() { + // TODO: Implement this properly. } protected void uninstallListeners() @@ -958,13 +1158,13 @@ public class BasicTableUI table.removeKeyListener(keyListener); table.removeMouseListener(mouseInputListener); table.removeMouseMotionListener(mouseInputListener); + table.removePropertyChangeListener(propertyChangeListener); + propertyChangeListener = null; } public void installUI(JComponent comp) { table = (JTable)comp; - focusListener = createFocusListener(); - mouseInputListener = createMouseInputListener(); installDefaults(); installKeyboardActions(); installListeners(); @@ -977,6 +1177,60 @@ public class BasicTableUI uninstallDefaults(); } + /** + * Paints a single cell in the table. + * + * @param g The graphics context to paint in + * @param row The row number to paint + * @param col The column 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 + * table + * @param rend A cell renderer to paint with + * @param data The data to provide to the cell renderer + * @param rowLead The lead selection for the rows of the table. + * @param colLead The lead selection for the columns of the table. + */ + void paintCell(Graphics g, int row, int col, Rectangle bounds, + TableCellRenderer rend, TableModel data, + int rowLead, int colLead) + { + boolean rowSelAllowed = table.getRowSelectionAllowed(); + boolean colSelAllowed = table.getColumnSelectionAllowed(); + boolean isSel = false; + if (rowSelAllowed && colSelAllowed || !rowSelAllowed && !colSelAllowed) + isSel = table.isCellSelected(row, col); + else + isSel = table.isRowSelected(row) && table.getRowSelectionAllowed() + || table.isColumnSelected(col) && table.getColumnSelectionAllowed(); + + // Determine the focused cell. The focused cell is the cell at the + // leadSelectionIndices of the row and column selection model. + ListSelectionModel rowSel = table.getSelectionModel(); + ListSelectionModel colSel = table.getColumnModel().getSelectionModel(); + boolean hasFocus = table.hasFocus() && table.isEnabled() + && rowSel.getLeadSelectionIndex() == row + && colSel.getLeadSelectionIndex() == col; + + Component comp = rend.getTableCellRendererComponent(table, + data.getValueAt(row, col), + isSel, hasFocus, row, col); + + rendererPane.paintComponent(g, comp, table, bounds); + + // FIXME: this is manual painting of the Caret, why doesn't the + // JTextField take care of this itself? + if (comp instanceof JTextField) + { + Rectangle oldClip = g.getClipBounds(); + g.translate(bounds.x, bounds.y); + g.clipRect(0, 0, bounds.width, bounds.height); + ((JTextField)comp).getCaret().paint(g); + g.translate(-bounds.x, -bounds.y); + g.setClip(oldClip); + } + } + public void paint(Graphics gfx, JComponent ignored) { int ncols = table.getColumnCount(); @@ -1002,40 +1256,24 @@ public class BasicTableUI y = y0; TableColumn col = cols.getColumn(c); int width = col.getWidth(); - int modelCol = col.getModelIndex(); - + int halfGapWidth = gap.width / 2; + int halfGapHeight = gap.height / 2; 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. - // Only the lead selection cell gets a border - if (comp instanceof JComponent) - { - if (table.getSelectionModel().getLeadSelectionIndex() == r - && table.getColumnModel().getSelectionModel(). - getLeadSelectionIndex() == c) - ((JComponent) comp).setBorder(highlightCellBorder); - else - ((JComponent) comp).setBorder(cellBorder); - } - comp.paint(gfx); - if (comp instanceof JTextField) - ((JTextField)comp).getCaret().paint(gfx); - gfx.translate(-x, -y); + Rectangle bounds = new Rectangle(x + halfGapWidth, + y + halfGapHeight + 1, + width - gap.width + 1, + height - gap.height); + if (bounds.intersects(clip)) + { + paintCell(gfx, r, c, bounds, table.getCellRenderer(r, c), + table.getModel(), + table.getSelectionModel().getLeadSelectionIndex(), + table.getColumnModel().getSelectionModel().getLeadSelectionIndex()); } - y += height; - if (gap != null) - y += gap.height; + y += height; } x += width; - if (gap != null) - x += gap.width; } // tighten up the x and y max bounds @@ -1044,7 +1282,7 @@ public class BasicTableUI Color grid = table.getGridColor(); - // paint vertical grid lines + // paint vertical grid lines if (grid != null && table.getShowVerticalLines()) { x = x0; @@ -1053,9 +1291,7 @@ public class BasicTableUI boolean paintedLine = false; for (int c = 0; c < ncols && x < xmax; ++c) { - x += cols.getColumn(c).getWidth();; - if (gap != null) - x += gap.width; + x += cols.getColumn(c).getWidth(); gfx.drawLine(x, y0, x, ymax); paintedLine = true; } @@ -1072,8 +1308,6 @@ public class BasicTableUI 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; } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTextAreaUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTextAreaUI.java index 97b0ccb..36854e0 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicTextAreaUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTextAreaUI.java @@ -39,11 +39,16 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import java.beans.PropertyChangeEvent; + import javax.swing.JComponent; +import javax.swing.JTextArea; +import javax.swing.UIDefaults; import javax.swing.plaf.ComponentUI; import javax.swing.text.Element; import javax.swing.text.PlainView; import javax.swing.text.View; +import javax.swing.text.WrappedPlainView; public class BasicTextAreaUI extends BasicTextUI { @@ -54,15 +59,55 @@ public class BasicTextAreaUI extends BasicTextUI public BasicTextAreaUI() { + // Nothing to do here. } + /** + * Create the view. Returns a WrappedPlainView if the text area + * has lineWrap set to true, otherwise returns a PlainView. If + * lineWrap is true has to check whether the wrap style is word + * or character and return an appropriate WrappedPlainView. + * + * @param elem the element to create a View for + * @return an appropriate View for the element + */ public View create(Element elem) { - return new PlainView(elem); + JTextArea comp = (JTextArea)getComponent(); + if (comp.getLineWrap()) + { + if (comp.getWrapStyleWord()) + return new WrappedPlainView(elem, true); + else + return new WrappedPlainView(elem, false); + } + else + return new PlainView(elem); } + /** + * Returns the prefix for entries in the {@link UIDefaults} table. + * + * @return "TextArea" + */ protected String getPropertyPrefix() { return "TextArea"; } + + /** + * Receives notification whenever one of the text component's bound + * properties changes. This changes the view to WrappedPlainView + * if setLineWrap(true) is called, and back to PlainView if + * setLineWrap(false) is called. + * + * @param ev the property change event + */ + protected void propertyChange(PropertyChangeEvent ev) + { + JTextArea comp = (JTextArea)getComponent(); + if (ev.getPropertyName() == "lineWrap" + || ev.getPropertyName() == "wrapStyleWord") + modelChanged(); + } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTextFieldUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTextFieldUI.java index a300446..4e2ca9f 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicTextFieldUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTextFieldUI.java @@ -41,6 +41,7 @@ package javax.swing.plaf.basic; import java.beans.PropertyChangeEvent; import javax.swing.JComponent; +import javax.swing.UIDefaults; import javax.swing.plaf.ComponentUI; import javax.swing.text.Element; import javax.swing.text.FieldView; @@ -63,6 +64,11 @@ public class BasicTextFieldUI extends BasicTextUI return new BasicTextFieldUI(); } + /** + * Returns the prefix for entries in the {@link UIDefaults} table. + * + * @return "TextField" + */ protected String getPropertyPrefix() { return "TextField"; @@ -73,8 +79,22 @@ public class BasicTextFieldUI extends BasicTextUI super.installUI(c); } + /** + * Receives notification whenever one of the text component's bound + * properties changes. Here we check for the editable and enabled + * properties and adjust the background color accordingly. + * + * @param event the property change event + */ protected void propertyChange(PropertyChangeEvent event) { - // Does nothing by default. + if (event.getPropertyName().equals("editable")) + { + boolean editable = ((Boolean) event.getNewValue()).booleanValue(); + if (editable) + textComponent.setBackground(background); + else + textComponent.setBackground(inactiveBackground); + } } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTextPaneUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTextPaneUI.java index 55d908e..decbed5 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicTextPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTextPaneUI.java @@ -38,10 +38,18 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import java.awt.Color; + import javax.swing.JComponent; +import javax.swing.JTextPane; +import javax.swing.plaf.ColorUIResource; +import javax.swing.UIDefaults; import javax.swing.plaf.ComponentUI; import javax.swing.text.Element; import javax.swing.text.PlainView; +import javax.swing.text.Style; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyleContext; import javax.swing.text.View; public class BasicTextPaneUI extends BasicEditorPaneUI @@ -61,8 +69,32 @@ public class BasicTextPaneUI extends BasicEditorPaneUI return new PlainView(elem); } + /** + * Returns the prefix for entries in the {@link UIDefaults} table. + * + * @return "TextPane" + */ protected String getPropertyPrefix() { return "TextPane"; } + + /** + * Installs this UI on the specified <code>JTextPane</code>. This calls the + * super implementation and then adds a default style to the text pane. + * + * @param c the text pane to install the UI to + */ + public void installUI(JComponent c) + { + super.installUI(c); + JTextPane tp = (JTextPane) c; + Style defaultStyle = tp.getStyle(StyleContext.DEFAULT_STYLE); + defaultStyle.addAttribute(StyleConstants.Foreground, + new ColorUIResource(Color.BLACK)); + defaultStyle.addAttribute(StyleConstants.FontFamily, "Serif"); + defaultStyle.addAttribute(StyleConstants.Italic, Boolean.FALSE); + defaultStyle.addAttribute(StyleConstants.Bold, Boolean.FALSE); + defaultStyle.addAttribute(StyleConstants.FontSize, new Integer(12)); + } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTextUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTextUI.java index 91ccb00..b9de926 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicTextUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTextUI.java @@ -38,6 +38,7 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import java.awt.Color; import java.awt.Container; import java.awt.Dimension; import java.awt.Graphics; @@ -54,6 +55,8 @@ import javax.swing.Action; import javax.swing.ActionMap; import javax.swing.InputMap; import javax.swing.JComponent; +import javax.swing.LookAndFeel; +import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import javax.swing.UIDefaults; import javax.swing.UIManager; @@ -73,7 +76,6 @@ 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; @@ -92,11 +94,11 @@ public abstract class BasicTextUI extends TextUI /** * A {@link DefaultCaret} that implements {@link UIResource}. */ - public static class BasicCaret extends DefaultCaret - implements UIResource + public static class BasicCaret extends DefaultCaret implements UIResource { public BasicCaret() { + // Nothing to do here. } } @@ -108,6 +110,7 @@ public abstract class BasicTextUI extends TextUI { public BasicHighlighter() { + // Nothing to do here. } } @@ -241,7 +244,7 @@ public abstract class BasicTextUI extends TextUI public void paint(Graphics g, Shape s) { if (view != null) - view.paint(g, s); + view.paint(g, s); } @@ -252,10 +255,10 @@ public abstract class BasicTextUI extends TextUI * * This is delegated to the real root view. * - * @param pos the position of the character in the model + * @param position the position of the character in the model * @param a the area that is occupied by the view - * @param bias either {@link Position.Bias.Forward} or - * {@link Position.Bias.Backward} depending on the preferred + * @param bias either {@link Position.Bias#Forward} or + * {@link Position.Bias#Backward} depending on the preferred * direction bias. If <code>null</code> this defaults to * <code>Position.Bias.Forward</code> * @@ -327,12 +330,41 @@ public abstract class BasicTextUI extends TextUI { view.changedUpdate(ev, shape, vf); } + + /** + * Returns the document position that is (visually) nearest to the given + * document position <code>pos</code> in the given direction <code>d</code>. + * + * @param c the text component + * @param pos the document position + * @param b the bias for <code>pos</code> + * @param d the direction, must be either {@link SwingConstants#NORTH}, + * {@link SwingConstants#SOUTH}, {@link SwingConstants#WEST} or + * {@link SwingConstants#EAST} + * @param biasRet an array of {@link Position.Bias} that can hold at least + * one element, which is filled with the bias of the return position + * on method exit + * + * @return the document position that is (visually) nearest to the given + * document position <code>pos</code> in the given direction + * <code>d</code> + * + * @throws BadLocationException if <code>pos</code> is not a valid offset in + * the document model + */ + public int getNextVisualPositionFrom(JTextComponent c, int pos, + Position.Bias b, int d, + Position.Bias[] biasRet) + throws BadLocationException + { + return view.getNextVisualPositionFrom(c, pos, b, d, biasRet); + } } /** * Receives notifications when properties of the text component change. */ - class UpdateHandler implements PropertyChangeListener + class PropertyChangeHandler implements PropertyChangeListener { /** * Notifies when a property of the text component changes. @@ -342,10 +374,12 @@ public abstract class BasicTextUI extends TextUI public void propertyChange(PropertyChangeEvent event) { if (event.getPropertyName().equals("document")) - { + { // Document changed. - modelChanged(); - } + modelChanged(); + } + + BasicTextUI.this.propertyChange(event); } } @@ -364,11 +398,10 @@ public abstract class BasicTextUI extends TextUI */ public void changedUpdate(DocumentEvent ev) { - Dimension size = textComponent.getSize(); - rootView.changedUpdate(ev, new Rectangle(0, 0, size.width, size.height), + rootView.changedUpdate(ev, getVisibleEditorRect(), rootView.getViewFactory()); } - + /** * Notification about a document insert event. * @@ -376,12 +409,8 @@ public abstract class BasicTextUI extends TextUI */ public void insertUpdate(DocumentEvent ev) { - Dimension size = textComponent.getSize(); - rootView.insertUpdate(ev, new Rectangle(0, 0, size.width, size.height), + rootView.insertUpdate(ev, getVisibleEditorRect(), rootView.getViewFactory()); - int caretPos = textComponent.getCaretPosition(); - if (caretPos >= ev.getOffset()) - textComponent.setCaretPosition(caretPos + ev.getLength()); } /** @@ -391,12 +420,8 @@ public abstract class BasicTextUI extends TextUI */ public void removeUpdate(DocumentEvent ev) { - Dimension size = textComponent.getSize(); - rootView.removeUpdate(ev, new Rectangle(0, 0, size.width, size.height), + rootView.removeUpdate(ev, getVisibleEditorRect(), rootView.getViewFactory()); - int caretPos = textComponent.getCaretPosition(); - if (caretPos >= ev.getOffset()) - textComponent.setCaretPosition(ev.getOffset()); } } @@ -419,16 +444,29 @@ public abstract class BasicTextUI extends TextUI /** * Receives notification when the model changes. */ - UpdateHandler updateHandler = new UpdateHandler(); + PropertyChangeHandler updateHandler = new PropertyChangeHandler(); /** The DocumentEvent handler. */ DocumentHandler documentHandler = new DocumentHandler(); /** + * The standard background color. This is the color which is used to paint + * text in enabled text components. + */ + Color background; + + /** + * The inactive background color. This is the color which is used to paint + * text in disabled text components. + */ + Color inactiveBackground; + + /** * Creates a new <code>BasicTextUI</code> instance. */ public BasicTextUI() { + // Nothing to do here. } /** @@ -506,14 +544,20 @@ public abstract class BasicTextUI extends TextUI 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")); + LookAndFeel.installColorsAndFont(textComponent, prefix + ".background", + prefix + ".foreground", prefix + ".font"); + LookAndFeel.installBorder(textComponent, prefix + ".border"); + textComponent.setMargin(UIManager.getInsets(prefix + ".margin")); + + caret.setBlinkRate(UIManager.getInt(prefix + ".caretBlinkRate")); + + // Fetch the colors for enabled/disabled text components. + background = UIManager.getColor(prefix + ".background"); + inactiveBackground = UIManager.getColor(prefix + ".inactiveBackground"); + textComponent.setDisabledTextColor + (UIManager.getColor(prefix + ".inactiveForeground")); + textComponent.setSelectedTextColor(UIManager.getColor(prefix + ".selectionForeground")); + textComponent.setSelectionColor(UIManager.getColor(prefix + ".selectionBackground")); } /** @@ -704,6 +748,7 @@ public abstract class BasicTextUI extends TextUI protected void uninstallListeners() { textComponent.removeFocusListener(focuslistener); + textComponent.getDocument().removeDocumentListener(documentHandler); } /** @@ -757,6 +802,18 @@ public abstract class BasicTextUI extends TextUI } /** + * Returns the minimum size for text components. This returns the size + * of the component's insets. + * + * @return the minimum size for text components + */ + public Dimension getMinimumSize(JComponent c) + { + Insets i = c.getInsets(); + return new Dimension(i.left + i.right, i.top + i.bottom); + } + + /** * Paints the text component. * * @param g the <code>Graphics</code> context to paint to @@ -776,10 +833,10 @@ public abstract class BasicTextUI extends TextUI { Caret caret = textComponent.getCaret(); Highlighter highlighter = textComponent.getHighlighter(); - + if (textComponent.isOpaque()) paintBackground(g); - + if (highlighter != null && textComponent.getSelectionStart() != textComponent.getSelectionEnd()) highlighter.paint(g); @@ -797,8 +854,10 @@ public abstract class BasicTextUI extends TextUI */ protected void paintBackground(Graphics g) { - g.setColor(textComponent.getBackground()); - g.fillRect(0, 0, textComponent.getWidth(), textComponent.getHeight()); + // This method does nothing. All the background filling is done by the + // ComponentUI update method. However, the method is called by paint + // to provide a way for subclasses to draw something different (e.g. + // background images etc) on the background. } /** @@ -885,10 +944,10 @@ public abstract class BasicTextUI extends TextUI /** * Maps a position in the document into the coordinate space of the View. * The output rectangle usually reflects the font height but has a width - * of zero. A bias of {@link Position.Bias.Forward} is used in this method. + * of zero. A bias of {@link Position.Bias#Forward} is used in this method. * + * @param t the text component * @param pos the position of the character in the model - * @param a the area that is occupied by the view * * @return a rectangle that gives the location of the document position * inside the view coordinate space @@ -908,10 +967,10 @@ public abstract class BasicTextUI extends TextUI * The output rectangle usually reflects the font height but has a width * of zero. * + * @param t the text component * @param pos the position of the character in the model - * @param a the area that is occupied by the view - * @param bias either {@link Position.Bias.Forward} or - * {@link Position.Bias.Backward} depending on the preferred + * @param bias either {@link Position.Bias#Forward} or + * {@link Position.Bias#Backward} depending on the preferred * direction bias. If <code>null</code> this defaults to * <code>Position.Bias.Forward</code> * @@ -957,7 +1016,7 @@ public abstract class BasicTextUI extends TextUI */ public int viewToModel(JTextComponent t, Point pt, Position.Bias[] biasReturn) { - return 0; // FIXME: Implement me. + return rootView.viewToModel(pt.x, pt.y, getVisibleEditorRect(), biasReturn); } /** @@ -999,16 +1058,17 @@ public abstract class BasicTextUI extends TextUI */ protected Rectangle getVisibleEditorRect() { + JTextComponent textComponent = getComponent(); int width = textComponent.getWidth(); int height = textComponent.getHeight(); if (width <= 0 || height <= 0) - return null; + return new Rectangle(0, 0, 0, 0); Insets insets = textComponent.getInsets(); return new Rectangle(insets.left, insets.top, - width - insets.left + insets.right, - height - insets.top + insets.bottom); + width - insets.left - insets.right, + height - insets.top - insets.bottom); } /** @@ -1020,6 +1080,8 @@ public abstract class BasicTextUI extends TextUI { rootView.setView(view); view.setParent(rootView); + textComponent.revalidate(); + textComponent.repaint(); } /** @@ -1043,4 +1105,17 @@ public abstract class BasicTextUI extends TextUI View view = factory.create(elem); setView(view); } + + /** + * Receives notification whenever one of the text component's bound + * properties changes. This default implementation does nothing. + * It is a hook that enables subclasses to react to property changes + * on the text component. + * + * @param ev the property change event + */ + protected void propertyChange(PropertyChangeEvent ev) + { + // The default implementation does nothing. + } } diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicToggleButtonUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicToggleButtonUI.java index 9106b0b..896ea0c 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicToggleButtonUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicToggleButtonUI.java @@ -38,7 +38,13 @@ exception statement from your version. */ package javax.swing.plaf.basic; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Rectangle; + +import javax.swing.AbstractButton; import javax.swing.JComponent; +import javax.swing.SwingUtilities; import javax.swing.plaf.ComponentUI; public class BasicToggleButtonUI extends BasicButtonUI @@ -58,5 +64,62 @@ public class BasicToggleButtonUI extends BasicButtonUI { return "ToggleButton."; } -} + /** + * 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); + + if (b.isBorderPainted()) + SwingUtilities.calculateInnerArea(b, vr); + else + vr = SwingUtilities.getLocalBounds(b); + 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); + + paintIcon(g, b, ir); + if (text != null) + paintText(g, b, tr, text); + if (b.isFocusOwner() && b.isFocusPainted()) + paintFocus(g, b, vr, tr, ir); + } + + /** + * Paints the icon for the toggle button. This delegates to + * {@link BasicButtonUI#paintIcon(Graphics, JComponent, Rectangle)}. + * + * @param g the graphics context + * @param b the button to paint the icon for + * @param iconRect the area allocated for the icon + */ + protected void paintIcon(Graphics g, AbstractButton b, Rectangle iconRect) + { + super.paintIcon(g, b, iconRect); + } +} diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicToolBarSeparatorUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicToolBarSeparatorUI.java index db29fdc..79cf0b0 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicToolBarSeparatorUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicToolBarSeparatorUI.java @@ -43,7 +43,6 @@ 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; @@ -73,9 +72,7 @@ public class BasicToolBarSeparatorUI extends BasicSeparatorUI */ protected void installDefaults(JSeparator s) { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - - size = defaults.getDimension("ToolBar.separatorSize"); + size = UIManager.getDimension("ToolBar.separatorSize"); } /** diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicToolBarUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicToolBarUI.java index 8be89ef..ef4ed83 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicToolBarUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicToolBarUI.java @@ -65,10 +65,11 @@ import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JToolBar; +import javax.swing.KeyStroke; +import javax.swing.LookAndFeel; 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; @@ -133,6 +134,26 @@ public class BasicToolBarUI extends ToolBarUI implements SwingConstants protected FocusListener toolBarFocusListener; /** + * @deprecated since JDK1.3. + */ + protected KeyStroke leftKey; + + /** + * @deprecated since JDK1.3. + */ + protected KeyStroke rightKey; + + /** + * @deprecated since JDK1.3. + */ + protected KeyStroke upKey; + + /** + * @deprecated since JDK1.3. + */ + protected KeyStroke downKey; + + /** * The floating window that is responsible for holding the JToolBar when it * is dragged outside of its original parent. */ @@ -566,18 +587,16 @@ public class BasicToolBarUI extends ToolBarUI implements SwingConstants */ protected void installDefaults() { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + LookAndFeel.installBorder(toolBar, "ToolBar.border"); + LookAndFeel.installColorsAndFont(toolBar, "ToolBar.background", + "ToolBar.foreground", "ToolBar.font"); - toolBar.setBorder(new ToolBarBorder()); - toolBar.setBackground(defaults.getColor("ToolBar.background")); - toolBar.setForeground(defaults.getColor("ToolBar.foreground")); - toolBar.setFont(defaults.getFont("ToolBar.font")); + dockingBorderColor = UIManager.getColor("ToolBar.dockingForeground"); + dockingColor = UIManager.getColor("ToolBar.dockingBackground"); - dockingBorderColor = defaults.getColor("ToolBar.dockingForeground"); - dockingColor = defaults.getColor("ToolBar.dockingBackground"); - - floatingBorderColor = defaults.getColor("ToolBar.floatingForeground"); - floatingColor = defaults.getColor("ToolBar.floatingBackground"); + floatingBorderColor = UIManager.getColor("ToolBar.floatingForeground"); + floatingColor = UIManager.getColor("ToolBar.floatingBackground"); + setRolloverBorders(toolBar.isRollover()); } /** @@ -591,10 +610,8 @@ public class BasicToolBarUI extends ToolBarUI implements SwingConstants /** * This method installs listeners for the JToolBar. - * - * @param toolbar The JToolBar to register listeners for. */ - protected void installListeners(JToolBar toolbar) + protected void installListeners() { dockingListener = createDockingListener(); toolBar.addMouseListener(dockingListener); @@ -694,7 +711,7 @@ public class BasicToolBarUI extends ToolBarUI implements SwingConstants toolBar.setOpaque(true); installDefaults(); installComponents(); - installListeners(toolBar); + installListeners(); installKeyboardActions(); } } @@ -1000,6 +1017,7 @@ public class BasicToolBarUI extends ToolBarUI implements SwingConstants */ public void mouseMoved(MouseEvent e) { + // TODO: What should be done here, if anything? } /** @@ -1030,13 +1048,15 @@ public class BasicToolBarUI extends ToolBarUI implements SwingConstants } origin = new Point(0, 0); - SwingUtilities.convertPointToScreen(ssd, toolBar); + if (toolBar.isShowing()) + 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); + + if (toolBar.isShowing()) + SwingUtilities.convertPointToScreen(origin, toolBar); isDragging = true; diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicToolTipUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicToolTipUI.java index b7a08aa..5cec2e3 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicToolTipUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicToolTipUI.java @@ -1,5 +1,5 @@ /* BasicToolTipUI.java -- - Copyright (C) 2004 Free Software Foundation, Inc. + Copyright (C) 2004, 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -39,20 +39,18 @@ 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 java.awt.Toolkit; import javax.swing.JComponent; import javax.swing.JToolTip; +import javax.swing.LookAndFeel; 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; @@ -61,58 +59,12 @@ import javax.swing.plaf.ToolTipUI; */ 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); - } + /** The shared instance of BasicToolTipUI used for all ToolTips. */ + private static BasicToolTipUI shared; - /** - * 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; + /** The tooltip's text */ + private String text; /** * Creates a new BasicToolTipUI object. @@ -124,7 +76,7 @@ public class BasicToolTipUI extends ToolTipUI /** * This method creates a new BasicToolTip UI for the given - * JComponent. + * JComponent. * * @param c The JComponent to create a UI for. * @@ -132,9 +84,9 @@ public class BasicToolTipUI extends ToolTipUI */ public static ComponentUI createUI(JComponent c) { - if (shared == null) - shared = new BasicToolTipUI(); - return shared; + if (shared == null) + shared = new BasicToolTipUI(); + return shared; } /** @@ -171,12 +123,16 @@ public class BasicToolTipUI extends ToolTipUI public Dimension getPreferredSize(JComponent c) { JToolTip tip = (JToolTip) c; + FontMetrics fm; + Toolkit g = tip.getToolkit(); + text = tip.getTipText(); + 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, + fm = g.getFontMetrics(tip.getFont()); + SwingUtilities.layoutCompoundLabel(tip, fm, text, null, SwingConstants.CENTER, SwingConstants.CENTER, SwingConstants.CENTER, @@ -192,11 +148,9 @@ public class BasicToolTipUI extends ToolTipUI */ 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); + LookAndFeel.installColorsAndFont(c, "ToolTip.background", + "ToolTip.foreground", "ToolTip.font"); + LookAndFeel.installBorder(c, "ToolTip.border"); } /** @@ -206,6 +160,7 @@ public class BasicToolTipUI extends ToolTipUI */ protected void installListeners(JComponent c) { + // TODO: Implement this properly. } /** @@ -231,6 +186,7 @@ public class BasicToolTipUI extends ToolTipUI JToolTip tip = (JToolTip) c; String text = tip.getTipText(); + Toolkit t = tip.getToolkit(); if (text == null) return; @@ -238,19 +194,19 @@ public class BasicToolTipUI extends ToolTipUI 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, + FontMetrics fm = t.getFontMetrics(tip.getFont()); + int ascent = fm.getAscent(); + SwingUtilities.layoutCompoundLabel(tip, fm, text, 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.drawString(text, vr.x, vr.y + ascent); - g.setColor(saved); + g.setColor(saved); } /** @@ -273,6 +229,7 @@ public class BasicToolTipUI extends ToolTipUI */ protected void uninstallListeners(JComponent c) { + // TODO: Implement this properly. } /** diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicTreeUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicTreeUI.java index 6f714a3..e967cd4 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicTreeUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicTreeUI.java @@ -44,6 +44,7 @@ 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; @@ -62,6 +63,7 @@ import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.util.Enumeration; import java.util.Hashtable; import javax.swing.AbstractAction; @@ -76,6 +78,7 @@ import javax.swing.JScrollPane; import javax.swing.JTextField; import javax.swing.JTree; import javax.swing.KeyStroke; +import javax.swing.LookAndFeel; import javax.swing.SwingUtilities; import javax.swing.Timer; import javax.swing.UIDefaults; @@ -89,6 +92,7 @@ import javax.swing.event.TreeModelEvent; import javax.swing.event.TreeModelListener; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; +import javax.swing.plaf.ActionMapUIResource; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.InputMapUIResource; import javax.swing.plaf.TreeUI; @@ -96,7 +100,6 @@ import javax.swing.text.Caret; import javax.swing.tree.AbstractLayoutCache; import javax.swing.tree.DefaultTreeCellEditor; import javax.swing.tree.DefaultTreeCellRenderer; -import javax.swing.tree.ExpandVetoException; import javax.swing.tree.FixedHeightLayoutCache; import javax.swing.tree.TreeCellEditor; import javax.swing.tree.TreeCellRenderer; @@ -110,11 +113,11 @@ import javax.swing.tree.TreeSelectionModel; * the Basic look and feel. * * @see javax.swing.JTree - * @author Sascha Brawer (brawer@dandelis.ch) + * * @author Lillian Angel (langel@redhat.com) + * @author Sascha Brawer (brawer@dandelis.ch) */ -public class BasicTreeUI - extends TreeUI +public class BasicTreeUI extends TreeUI { /** Collapse Icon for the tree. */ protected transient Icon collapsedIcon; @@ -136,9 +139,6 @@ public class BasicTreeUI */ protected int totalChildIndent; - /** Minimum preferred size. */ - protected Dimension preferredMinsize; - /** Index of the row that was last selected. */ protected int lastSelectedRow; @@ -174,6 +174,9 @@ public class BasicTreeUI /** Size needed to completely display all the nodes. */ protected Dimension preferredSize; + + /** Minimum size needed to completely display all the nodes. */ + protected Dimension preferredMinSize; /** Is the preferredSize valid? */ protected boolean validCachedPreferredSize; @@ -223,38 +226,38 @@ public class BasicTreeUI /** Set to true if the editor has a different size than the renderer. */ protected boolean editorHasDifferentSize; - + /** The action listener for the editor's Timer. */ - private Timer editorTimer = new EditorUpdateTimer(); + Timer editorTimer = new EditorUpdateTimer(); /** The new value of the node after editing. */ - private Object newVal; + Object newVal; /** The action bound to KeyStrokes. */ - private TreeAction action; + TreeAction action; /** Boolean to keep track of editing. */ - private boolean isEditing; + boolean isEditing; + + /** The bounds of the current cell. */ + Rectangle bounds; + + /** The current path of the visible nodes in the tree. */ + TreePath currentVisiblePath; + + /** The gap between the icon and text. */ + int gap = 4; /** Listeners */ private PropertyChangeListener propertyChangeListener; - private FocusListener focusListener; - private TreeSelectionListener treeSelectionListener; - - private MouseInputListener mouseInputListener; - + private MouseListener mouseListener; private KeyListener keyListener; - private PropertyChangeListener selectionModelPropertyChangeListener; - private ComponentListener componentListener; - - private CellEditorListener cellEditorListener; - + CellEditorListener cellEditorListener; private TreeExpansionListener treeExpansionListener; - private TreeModelListener treeModelListener; /** @@ -262,6 +265,7 @@ public class BasicTreeUI */ public BasicTreeUI() { + validCachedPreferredSize = false; drawingCache = new Hashtable(); nodeDimensions = createNodeDimensions(); configureLayoutCache(); @@ -269,7 +273,7 @@ public class BasicTreeUI propertyChangeListener = createPropertyChangeListener(); focusListener = createFocusListener(); treeSelectionListener = createTreeSelectionListener(); - mouseInputListener = new MouseInputHandler(null, null, null); + mouseListener = createMouseListener(); keyListener = createKeyListener(); selectionModelPropertyChangeListener = createSelectionModelPropertyChangeListener(); componentListener = createComponentListener(); @@ -331,7 +335,7 @@ public class BasicTreeUI * * @return the indent value for the left child. */ - public int getLeftChildIndent(int newAmount) + public int getLeftChildIndent() { return leftChildIndent; } @@ -456,7 +460,6 @@ public class BasicTreeUI protected void setCellRenderer(TreeCellRenderer tcr) { currentCellRenderer = tcr; - tree.setCellRenderer(tcr); updateRenderer(); } @@ -625,14 +628,13 @@ public class BasicTreeUI { Object cell = path.getLastPathComponent(); - TreeModel mod = tree.getModel(); - if (mod != null) + if (treeModel != null) { - Object root = mod.getRoot(); + Object root = treeModel.getRoot(); + if (!tree.isRootVisible() && tree.isExpanded(new TreePath(root))) root = getNextNode(root); - - Point loc = getCellLocation(0, 0, tree, mod, cell, root); + Point loc = getCellLocation(0, 0, tree, treeModel, cell, root); return getCellBounds(loc.x, loc.y, cell); } } @@ -650,21 +652,11 @@ public class BasicTreeUI */ public TreePath getPathForRow(JTree tree, int row) { - TreeModel mod = tree.getModel(); - if (mod != null) + if (treeModel != null && currentVisiblePath != null) { - Object node = mod.getRoot(); - if (!tree.isRootVisible() - && tree.isExpanded(new TreePath(getPathToRoot(node, 0)))) - node = getNextNode(node); - - for (int i = 0; i < row; i++) - node = getNextVisibleNode(node); - - if (node == null) - return null; - - return new TreePath(getPathToRoot(node, 0)); + Object[] nodes = currentVisiblePath.getPath(); + if (row < nodes.length) + return new TreePath(getPathToRoot(nodes[row], 0)); } return null; } @@ -683,17 +675,20 @@ public class BasicTreeUI */ public int getRowForPath(JTree tree, TreePath path) { - int row = path.getPathCount(); - if (tree.isVisible(path)) - return row; - - path = path.getParentPath(); - while (row > 0 && !tree.isVisible(path)) + int row = 0; + Object dest = path.getLastPathComponent(); + int rowCount = getRowCount(tree); + if (currentVisiblePath != null) { - path = path.getParentPath(); - row--; + Object[] nodes = currentVisiblePath.getPath(); + while (row < rowCount) + { + if (dest.equals(nodes[row])) + return row; + row++; + } } - return row; + return -1; } /** @@ -705,22 +700,10 @@ public class BasicTreeUI */ public int getRowCount(JTree tree) { - TreeModel mod = tree.getModel(); - int count = 0; - if (mod != null) - { - Object node = mod.getRoot(); - if (!tree.isRootVisible() - && tree.isExpanded(new TreePath((getPathToRoot(node, 0))))) - node = getNextNode(node); - - while (node != null) - { - count++; - node = getNextVisibleNode(node); - } - } - return count; + updateCurrentVisiblePath(); + if (currentVisiblePath != null) + return currentVisiblePath.getPathCount(); + return 0; } /** @@ -739,9 +722,6 @@ public class BasicTreeUI */ public TreePath getClosestPathForLocation(JTree tree, int x, int y) { - // FIXME: what if root is hidden? should not depend on (0,0) - // should start counting rows from where root is. - int row = Math.round(y / getRowHeight()); TreePath path = getPathForRow(tree, row); @@ -828,7 +808,7 @@ public class BasicTreeUI */ protected void prepareForUIInstall() { - // FIXME: not implemented + // TODO: Implement this properly. } /** @@ -837,7 +817,7 @@ public class BasicTreeUI */ protected void completeUIInstall() { - // FIXME: not implemented + // TODO: Implement this properly. } /** @@ -846,7 +826,7 @@ public class BasicTreeUI */ protected void completeUIUninstall() { - // FIXME: not implemented + // TODO: Implement this properly. } /** @@ -854,7 +834,10 @@ public class BasicTreeUI */ protected void installComponents() { - // FIXME: not implemented + currentCellRenderer = createDefaultCellRenderer(); + rendererPane = createCellRendererPane(); + createdRenderer = true; + setCellRenderer(currentCellRenderer); } /** @@ -865,8 +848,7 @@ public class BasicTreeUI */ protected AbstractLayoutCache.NodeDimensions createNodeDimensions() { - // FIXME: not implemented - return null; + return new NodeDimensionsHandler(); } /** @@ -1035,7 +1017,7 @@ public class BasicTreeUI tree.removePropertyChangeListener(propertyChangeListener); tree.removeFocusListener(focusListener); tree.removeTreeSelectionListener(treeSelectionListener); - tree.removeMouseListener(mouseInputListener); + tree.removeMouseListener(mouseListener); tree.removeKeyListener(keyListener); tree.removePropertyChangeListener(selectionModelPropertyChangeListener); tree.removeComponentListener(componentListener); @@ -1044,9 +1026,8 @@ public class BasicTreeUI TreeCellEditor tce = tree.getCellEditor(); if (tce != null) tce.removeCellEditorListener(cellEditorListener); - TreeModel tm = tree.getModel(); - if (tm != null) - tm.removeTreeModelListener(treeModelListener); + if (treeModel != null) + treeModel.removeTreeModelListener(treeModelListener); } /** @@ -1054,6 +1035,7 @@ public class BasicTreeUI */ protected void uninstallKeyboardActions() { + // TODO: Implement this properly. } /** @@ -1061,7 +1043,10 @@ public class BasicTreeUI */ protected void uninstallComponents() { - // FIXME: not implemented + currentCellRenderer = null; + rendererPane = null; + createdRenderer = false; + setCellRenderer(currentCellRenderer); } /** @@ -1072,8 +1057,7 @@ public class BasicTreeUI */ protected int getVerticalLegBuffer() { - // FIXME: not implemented - return 0; + return getRowHeight() / 2; } /** @@ -1085,17 +1069,17 @@ public class BasicTreeUI */ protected int getHorizontalLegBuffer() { - // FIXME: not implemented - return 0; + return rightChildIndent / 2; } /** * Make all the nodes that are expanded in JTree expanded in LayoutCache. This - * invokes update ExpandedDescendants with the root path. + * invokes updateExpandedDescendants with the root path. */ protected void updateLayoutCacheExpandedNodes() { - // FIXME: not implemented + if (treeModel != null) + updateExpandedDescendants(new TreePath(treeModel.getRoot())); } /** @@ -1108,7 +1092,9 @@ public class BasicTreeUI */ protected void updateExpandedDescendants(TreePath path) { - // FIXME: not implemented + Enumeration expanded = tree.getExpandedDescendants(path); + while (expanded.hasMoreElements()) + treeState.setExpandedState(((TreePath) expanded.nextElement()), true); } /** @@ -1128,7 +1114,7 @@ public class BasicTreeUI */ protected void updateDepthOffset() { - // FIXME: not implemented + depthOffset += getVerticalLegBuffer(); } /** @@ -1148,7 +1134,15 @@ public class BasicTreeUI */ protected void updateRenderer() { - // FIXME: not implemented + if (tree != null) + { + if(tree.getCellRenderer() == null) + { + if(currentCellRenderer == null) + currentCellRenderer = createDefaultCellRenderer(); + tree.setCellRenderer(currentCellRenderer); + } + } } /** @@ -1166,19 +1160,36 @@ public class BasicTreeUI */ protected void updateSize() { - // FIXME: not implemented + preferredSize = null; + updateCachedPreferredSize(); + tree.treeDidChange(); } /** * 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. + * returned from <code>getPreferredSize()</code>. */ protected void updateCachedPreferredSize() { - // FIXME: not implemented + int maxWidth = 0; + boolean isLeaf = false; + if (currentVisiblePath != null) + { + Object[] path = currentVisiblePath.getPath(); + for (int i = 0; i < path.length; i++) + { + TreePath curr = new TreePath(getPathToRoot(path[i], 0)); + Rectangle bounds = getPathBounds(tree, curr); + if (treeModel != null) + isLeaf = treeModel.isLeaf(path[i]); + if (!isLeaf && hasControlIcons()) + bounds.width += getCurrentControlIcon(curr).getIconWidth(); + maxWidth = Math.max(maxWidth, bounds.x + bounds.width); + } + preferredSize = new Dimension(maxWidth, (getRowHeight() * path.length)); + } + else preferredSize = new Dimension(0, 0); + validCachedPreferredSize = true; } /** @@ -1189,7 +1200,9 @@ public class BasicTreeUI */ protected void pathWasExpanded(TreePath path) { - // FIXME: not implemented + validCachedPreferredSize = false; + tree.revalidate(); + tree.repaint(); } /** @@ -1197,28 +1210,28 @@ public class BasicTreeUI */ protected void pathWasCollapsed(TreePath path) { - // FIXME: not implemented + validCachedPreferredSize = false; + tree.revalidate(); + tree.repaint(); } /** * Install all defaults for the tree. - * - * @param tree - * is the JTree to install defaults for */ - protected void installDefaults(JTree tree) + protected void installDefaults() { - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - - tree.setFont(defaults.getFont("Tree.font")); - tree.setForeground(defaults.getColor("Tree.foreground")); - tree.setBackground(defaults.getColor("Tree.background")); + LookAndFeel.installColorsAndFont(tree, "Tree.background", + "Tree.foreground", "Tree.font"); tree.setOpaque(true); - rightChildIndent = defaults.getInt("Tree.rightChildIndent"); - leftChildIndent = defaults.getInt("Tree.leftChildIndent"); - setRowHeight(defaults.getInt("Tree.rowHeight")); + rightChildIndent = UIManager.getInt("Tree.rightChildIndent"); + leftChildIndent = UIManager.getInt("Tree.leftChildIndent"); + setRowHeight(UIManager.getInt("Tree.rowHeight")); + tree.setRowHeight(UIManager.getInt("Tree.rowHeight")); tree.requestFocusInWindow(false); + tree.setScrollsOnExpand(UIManager.getBoolean("Tree.scrollsOnExpand")); + setExpandedIcon(UIManager.getIcon("Tree.expandedIcon")); + setCollapsedIcon(UIManager.getIcon("Tree.collapsedIcon")); } /** @@ -1229,7 +1242,7 @@ public class BasicTreeUI UIDefaults defaults = UIManager.getLookAndFeelDefaults(); InputMap focusInputMap = (InputMap) defaults.get("Tree.focusInputMap"); InputMapUIResource parentInputMap = new InputMapUIResource(); - ActionMap parentActionMap = new ActionMap(); + ActionMap parentActionMap = new ActionMapUIResource(); action = new TreeAction(); Object keys[] = focusInputMap.allKeys(); @@ -1308,7 +1321,7 @@ public class BasicTreeUI tree.addPropertyChangeListener(propertyChangeListener); tree.addFocusListener(focusListener); tree.addTreeSelectionListener(treeSelectionListener); - tree.addMouseListener(mouseInputListener); + tree.addMouseListener(mouseListener); tree.addKeyListener(keyListener); tree.addPropertyChangeListener(selectionModelPropertyChangeListener); tree.addComponentListener(componentListener); @@ -1325,37 +1338,36 @@ public class BasicTreeUI */ public void installUI(JComponent c) { - super.installUI(c); - installDefaults((JTree) c); tree = (JTree) c; + prepareForUIInstall(); + super.installUI(c); + installDefaults(); - currentCellRenderer = createDefaultCellRenderer(); - rendererPane = createCellRendererPane(); - createdRenderer = true; - + installComponents(); + installKeyboardActions(); + installListeners(); + setCellEditor(createDefaultCellEditor()); createdCellEditor = true; isEditing = false; - + TreeModel mod = tree.getModel(); setModel(mod); - tree.setRootVisible(true); if (mod != null) - tree.expandPath(new TreePath(mod.getRoot())); + { + TreePath path = new TreePath(mod.getRoot()); + if (!tree.isExpanded(path)) + toggleExpandState(path); + } treeSelectionModel = tree.getSelectionModel(); - installKeyboardActions(); - installListeners(); completeUIInstall(); } /** * Uninstall the defaults for the tree - * - * @param tree - * to uninstall defaults for */ - protected void uninstallDefaults(JTree tree) + protected void uninstallDefaults() { tree.setFont(null); tree.setForeground(null); @@ -1370,10 +1382,12 @@ public class BasicTreeUI */ public void uninstallUI(JComponent c) { - uninstallDefaults((JTree) c); + prepareForUIUninstall(); + uninstallDefaults(); uninstallKeyboardActions(); uninstallListeners(); tree = null; + uninstallComponents(); completeUIUninstall(); } @@ -1393,20 +1407,16 @@ public class BasicTreeUI public void paint(Graphics g, JComponent c) { JTree tree = (JTree) c; - - TreeModel mod = tree.getModel(); - - if (mod != null) + if (currentVisiblePath == null) + updateCurrentVisiblePath(); + + if (currentVisiblePath != null && treeModel != null) { - Object root = mod.getRoot(); - - if (!tree.isRootVisible()) - tree.expandPath(new TreePath(root)); - - paintRecursive(g, 0, 0, 0, 0, tree, mod, root); - + Object root = treeModel.getRoot(); + paintRecursive(g, 0, 0, 0, tree, treeModel, root); + if (hasControlIcons()) - paintControlIcons(g, 0, 0, 0, 0, tree, mod, root); + paintControlIcons(g, 0, 0, 0, tree, treeModel, root); } } @@ -1420,7 +1430,19 @@ public class BasicTreeUI */ protected void ensureRowsAreVisible(int beginRow, int endRow) { - // FIXME: not implemented + if (beginRow < endRow) + { + int temp = endRow; + endRow = beginRow; + beginRow = temp; + } + + for (int i = beginRow; i < endRow; i++) + { + TreePath path = getPathForRow(tree, i); + if (!tree.isVisible(path)) + tree.makeVisible(path); + } } /** @@ -1431,7 +1453,7 @@ public class BasicTreeUI */ public void setPreferredMinSize(Dimension newSize) { - // FIXME: not implemented + preferredMinSize = newSize; } /** @@ -1441,8 +1463,7 @@ public class BasicTreeUI */ public Dimension getPreferredMinSize() { - // FIXME: not implemented - return null; + return preferredMinSize; } /** @@ -1472,28 +1493,10 @@ public class BasicTreeUI */ public Dimension getPreferredSize(JComponent c, boolean checkConsistancy) { - // FIXME: checkConsistancy not implemented, c not used - TreeModel model = tree.getModel(); - int maxWidth = 0; - int count = 0; - if (model != null) - { - Object node = model.getRoot(); - if (node != null) - { - maxWidth = (int) (getCellBounds(0, 0, node).getWidth()); - while (node != null) - { - count++; - Object nextNode = getNextVisibleNode(node); - if (nextNode != null) - maxWidth = Math.max(maxWidth, - (int) (getCellBounds(0, 0, nextNode).getWidth())); - node = nextNode; - } - } - } - return new Dimension(maxWidth, (getRowHeight() * count)); + // FIXME: checkConsistancy not implemented, c not used + if(!validCachedPreferredSize) + updateCachedPreferredSize(); + return preferredSize; } /** @@ -1506,8 +1509,10 @@ public class BasicTreeUI */ public Dimension getMinimumSize(JComponent c) { - // FIXME: not implemented - return getPreferredSize(c); + Dimension min = getPreferredMinSize(); + if (min == null) + return new Dimension(); + return min; } /** @@ -1520,8 +1525,9 @@ public class BasicTreeUI */ public Dimension getMaximumSize(JComponent c) { - // FIXME: not implemented - return getPreferredSize(c); + if (c instanceof JTree) + return ((JTree) c).getPreferredSize(); + return new Dimension(); } /** @@ -1565,7 +1571,7 @@ public class BasicTreeUI } if (messageTree) - tree.getModel().valueForPathChanged(tree.getLeadSelectionPath(), newVal); + treeModel.valueForPathChanged(tree.getLeadSelectionPath(), newVal); } /** @@ -1584,7 +1590,7 @@ public class BasicTreeUI int y; if (event == null) { - Rectangle bounds = getPathBounds(tree, path); + bounds = getPathBounds(tree, path); x = bounds.x; y = bounds.y; } @@ -1600,6 +1606,7 @@ public class BasicTreeUI { editingPath = path; editingRow = tree.getRowForPath(editingPath); + Object val = editingPath.getLastPathComponent(); cellEditor.addCellEditorListener(cellEditorListener); stopEditingInCompleteEditing = false; @@ -1613,6 +1620,8 @@ public class BasicTreeUI editingComponent.getParent().validate(); tree.add(editingComponent.getParent()); editingComponent.getParent().validate(); + validCachedPreferredSize = false; + tree.revalidate(); ((JTextField) editingComponent).requestFocusInWindow(false); editorTimer.start(); return true; @@ -1634,7 +1643,8 @@ public class BasicTreeUI protected void checkForClickInExpandControl(TreePath path, int mouseX, int mouseY) { - // FIXME: not implemented + if (isLocationInExpandControl(path, mouseX, mouseY)) + toggleExpandState(path); } /** @@ -1655,8 +1665,18 @@ public class BasicTreeUI protected boolean isLocationInExpandControl(TreePath path, int mouseX, int mouseY) { - // FIXME: not implemented - return false; + boolean cntlClick = false; + int row = getRowForPath(tree, path); + + if (!isLeaf(row)) + { + bounds = getPathBounds(tree, path); + + if (hasControlIcons() && (mouseX < bounds.x) + && (mouseX > (bounds.x - getCurrentControlIcon(path).getIconWidth() - gap))) + cntlClick = true; + } + return cntlClick; } /** @@ -1672,7 +1692,7 @@ public class BasicTreeUI */ protected void handleExpandControlClick(TreePath path, int mouseX, int mouseY) { - // FIXME: not implemented + toggleExpandState(path); } /** @@ -1686,7 +1706,11 @@ public class BasicTreeUI */ protected void toggleExpandState(TreePath path) { - // FIXME: not implemented + if (tree.isExpanded(path)) + tree.collapsePath(path); + else + tree.expandPath(path); + updateCurrentVisiblePath(); } /** @@ -1700,8 +1724,8 @@ public class BasicTreeUI */ protected boolean isToggleSelectionEvent(MouseEvent event) { - // FIXME: not implemented - return false; + return (tree.getSelectionModel().getSelectionMode() == + TreeSelectionModel.SINGLE_TREE_SELECTION); } /** @@ -1715,8 +1739,8 @@ public class BasicTreeUI */ protected boolean isMultiSelectEvent(MouseEvent event) { - // FIXME: not implemented - return false; + return (tree.getSelectionModel().getSelectionMode() == + TreeSelectionModel.CONTIGUOUS_TREE_SELECTION); } /** @@ -1731,8 +1755,7 @@ public class BasicTreeUI */ protected boolean isToggleEvent(MouseEvent event) { - // FIXME: not implemented - return false; + return true; } /** @@ -1749,7 +1772,29 @@ public class BasicTreeUI */ protected void selectPathForEvent(TreePath path, MouseEvent event) { - // FIXME: not implemented + if (isToggleSelectionEvent(event)) + { + if (tree.isPathSelected(path)) + tree.removeSelectionPath(path); + else + { + tree.addSelectionPath(path); + tree.setAnchorSelectionPath(path); + } + } + else if (isMultiSelectEvent(event)) + { + TreePath anchor = tree.getAnchorSelectionPath(); + if (anchor != null) + { + int aRow = getRowForPath(tree, anchor); + tree.addSelectionInterval(aRow, getRowForPath(tree, path)); + } + else + tree.addSelectionPath(path); + } + else + tree.addSelectionPath(path); } /** @@ -1766,7 +1811,7 @@ public class BasicTreeUI return true; Object node = pathForRow.getLastPathComponent(); - return tree.getModel().isLeaf(node); + return treeModel.isLeaf(node); } /** @@ -1800,9 +1845,9 @@ public class BasicTreeUI (new TreeTraverseAction(0, "")).actionPerformed(e); else if (e.getActionCommand().equals("selectAll")) { - TreePath[] paths = new TreePath[tree.getRowCount()]; + TreePath[] paths = new TreePath[tree.getVisibleRowCount()]; - Object curr = getNextVisibleNode(tree.getModel().getRoot()); + Object curr = getNextVisibleNode(treeModel.getRoot()); int i = 0; while (curr != null && i < paths.length) { @@ -1822,13 +1867,8 @@ public class BasicTreeUI { Object last = lead.getLastPathComponent(); TreePath path = new TreePath(getPathToRoot(last, 0)); - if (!tree.getModel().isLeaf(last)) - { - if (tree.isExpanded(path)) - tree.collapsePath(path); - else - tree.expandPath(path); - } + if (!treeModel.isLeaf(last)) + toggleExpandState(path); } } else if (e.getActionCommand().equals("clearSelection")) @@ -1920,8 +1960,7 @@ public class BasicTreeUI /** * Updates the preferred size when scrolling, if necessary. */ - public class ComponentHandler - extends ComponentAdapter + public class ComponentHandler extends ComponentAdapter implements ActionListener { /** @@ -1937,6 +1976,7 @@ public class BasicTreeUI */ public ComponentHandler() { + // Nothing to do here. } /** @@ -1947,6 +1987,7 @@ public class BasicTreeUI */ public void componentMoved(ComponentEvent e) { + // TODO: What should be done here, if anything? } /** @@ -1955,6 +1996,7 @@ public class BasicTreeUI */ protected void startTimer() { + // TODO: Implement this properly. } /** @@ -1976,21 +2018,22 @@ public class BasicTreeUI */ public void actionPerformed(ActionEvent ae) { + // TODO: Implement this properly. } - }// ComponentHandler + } /** * Listener responsible for getting cell editing events and updating the tree * accordingly. */ - public class CellEditorHandler - implements CellEditorListener + public class CellEditorHandler implements CellEditorListener { /** * Constructor */ public CellEditorHandler() { + // Nothing to do here. } /** @@ -2023,6 +2066,9 @@ public class BasicTreeUI isEditing = false; tree.requestFocusInWindow(false); editorTimer.stop(); + validCachedPreferredSize = false; + tree.revalidate(); + tree.repaint(); } /** @@ -2051,6 +2097,8 @@ public class BasicTreeUI tree.requestFocusInWindow(false); editorTimer.stop(); isEditing = false; + validCachedPreferredSize = false; + tree.revalidate(); tree.repaint(); } }// CellEditorHandler @@ -2066,6 +2114,7 @@ public class BasicTreeUI */ public FocusHandler() { + // Nothing to do here. } /** @@ -2077,6 +2126,7 @@ public class BasicTreeUI */ public void focusGained(FocusEvent e) { + // TODO: Implement this properly. } /** @@ -2088,8 +2138,9 @@ public class BasicTreeUI */ public void focusLost(FocusEvent e) { + // TODO: Implement this properly. } - }// FocusHandler + } /** * This is used to get multiple key down events to appropriately genereate @@ -2109,6 +2160,7 @@ public class BasicTreeUI */ public KeyHandler() { + // Nothing to do here. } /** @@ -2122,6 +2174,7 @@ public class BasicTreeUI */ public void keyTyped(KeyEvent e) { + // TODO: What should be done here, if anything? } /** @@ -2132,6 +2185,7 @@ public class BasicTreeUI */ public void keyPressed(KeyEvent e) { + // TODO: What should be done here, if anything? } /** @@ -2142,22 +2196,22 @@ public class BasicTreeUI */ public void keyReleased(KeyEvent e) { + // TODO: What should be done here, if anything? } - }// KeyHandler + } /** * MouseListener is responsible for updating the selection based on mouse * events. */ - public class MouseHandler - extends MouseAdapter - implements MouseMotionListener + public class MouseHandler extends MouseAdapter implements MouseMotionListener { /** * Constructor */ public MouseHandler() { + // Nothing to do here. } /** @@ -2168,6 +2222,57 @@ public class BasicTreeUI */ public void mousePressed(MouseEvent e) { + Point click = e.getPoint(); + TreePath path = getClosestPathForLocation(tree, click.x, click.y); + + if (path != null) + { + bounds = getPathBounds(tree, path); + int row = getRowForPath(tree, path); + boolean cntlClick = isLocationInExpandControl(path, click.x, click.y); + + boolean isLeaf = isLeaf(row); + + TreeCellRenderer tcr = getCellRenderer(); + Icon icon; + if (isLeaf) + icon = UIManager.getIcon("Tree.leafIcon"); + else if (tree.isExpanded(path)) + icon = UIManager.getIcon("Tree.openIcon"); + else + icon = UIManager.getIcon("Tree.closedIcon"); + + if (tcr instanceof DefaultTreeCellRenderer) + { + Icon tmp = ((DefaultTreeCellRenderer) tcr).getIcon(); + if (tmp != null) + icon = tmp; + } + + // add gap*2 for the space before and after the text + if (icon != null) + bounds.width += icon.getIconWidth() + gap*2; + + boolean inBounds = bounds.contains(click.x, click.y); + if ((inBounds || cntlClick) && tree.isVisible(path)) + { + if (inBounds) + { + selectPath(tree, path); + if (e.getClickCount() == 2 && !isLeaf(row)) + toggleExpandState(path); + } + + if (cntlClick) + { + handleExpandControlClick(path, click.x, click.y); + if (cellEditor != null) + cellEditor.cancelCellEditing(); + } + else if (tree.isEditable()) + startEditing(path, e); + } + } } /** @@ -2181,6 +2286,7 @@ public class BasicTreeUI */ public void mouseDragged(MouseEvent e) { + // TODO: What should be done here, if anything? } /** @@ -2192,6 +2298,7 @@ public class BasicTreeUI */ public void mouseMoved(MouseEvent e) { + // TODO: What should be done here, if anything? } /** @@ -2202,16 +2309,16 @@ public class BasicTreeUI */ public void mouseReleased(MouseEvent e) { + // TODO: What should be done here, if anything? } - }// 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 + public class MouseInputHandler implements MouseInputListener { /** Source that events are coming from */ protected Component source; @@ -2232,6 +2339,8 @@ public class BasicTreeUI public MouseInputHandler(Component source, Component destination, MouseEvent e) { + this.source = source; + this.destination = destination; } /** @@ -2243,6 +2352,7 @@ public class BasicTreeUI */ public void mouseClicked(MouseEvent e) { + // TODO: What should be done here, if anything? } /** @@ -2253,42 +2363,7 @@ public class BasicTreeUI */ public void mousePressed(MouseEvent e) { - Point click = e.getPoint(); - int row = Math.round(click.y / getRowHeight()); - TreePath path = getClosestPathForLocation(tree, click.x, click.y); - - if (path != null) - { - boolean inBounds = false; - boolean cntlClick = false; - Rectangle bounds = getPathBounds(tree, path); - - bounds.x -= rightChildIndent - 4; - bounds.width += rightChildIndent + 4; - - if (bounds.contains(click.x, click.y)) - inBounds = true; - else if (hasControlIcons() - && (click.x < (bounds.x - rightChildIndent + 5) && - click.x > (bounds.x - rightChildIndent - 5))) - cntlClick = true; - - if ((inBounds || cntlClick) && tree.isVisible(path)) - { - selectPath(tree, path); - - if ((e.getClickCount() == 2 || cntlClick) && !isLeaf(row)) - { - if (tree.isExpanded(path)) - tree.collapsePath(path); - else - tree.expandPath(path); - } - - if (!cntlClick && tree.isEditable()) - startEditing(path, e); - } - } + // TODO: What should be done here, if anything? } /** @@ -2299,6 +2374,7 @@ public class BasicTreeUI */ public void mouseReleased(MouseEvent e) { + // TODO: What should be done here, if anything? } /** @@ -2309,6 +2385,7 @@ public class BasicTreeUI */ public void mouseEntered(MouseEvent e) { + // TODO: What should be done here, if anything? } /** @@ -2319,6 +2396,7 @@ public class BasicTreeUI */ public void mouseExited(MouseEvent e) { + // TODO: What should be done here, if anything? } /** @@ -2332,6 +2410,7 @@ public class BasicTreeUI */ public void mouseDragged(MouseEvent e) { + // TODO: What should be done here, if anything? } /** @@ -2343,6 +2422,7 @@ public class BasicTreeUI */ public void mouseMoved(MouseEvent e) { + // TODO: What should be done here, if anything? } /** @@ -2350,8 +2430,9 @@ public class BasicTreeUI */ protected void removeFromSource() { + // TODO: Implement this properly. } - }// MouseInputHandler + } /** * Class responsible for getting size of node, method is forwarded to @@ -2366,6 +2447,7 @@ public class BasicTreeUI */ public NodeDimensionsHandler() { + // Nothing to do here. } /** @@ -2413,6 +2495,7 @@ public class BasicTreeUI */ public PropertyChangeHandler() { + // Nothing to do here. } /** @@ -2424,8 +2507,15 @@ public class BasicTreeUI */ public void propertyChange(PropertyChangeEvent event) { + if ((event.getPropertyName()).equals("rootVisible")) + { + validCachedPreferredSize = false; + updateCurrentVisiblePath(); + tree.revalidate(); + tree.repaint(); + } } - }// PropertyChangeHandler + } /** * Listener on the TreeSelectionModel, resets the row selection if any of the @@ -2440,6 +2530,7 @@ public class BasicTreeUI */ public SelectionModelPropertyChangeHandler() { + // Nothing to do here. } /** @@ -2451,8 +2542,9 @@ public class BasicTreeUI */ public void propertyChange(PropertyChangeEvent event) { + // TODO: What should be done here, if anything? } - }// SelectionModelPropertyChangeHandler + } /** * ActionListener that invokes cancelEditing when action performed. @@ -2464,8 +2556,9 @@ public class BasicTreeUI /** * Constructor */ - public TreeCancelEditingAction() + public TreeCancelEditingAction(String name) { + // TODO: Implement this properly. } /** @@ -2476,6 +2569,7 @@ public class BasicTreeUI */ public void actionPerformed(ActionEvent e) { + // TODO: Implement this properly. } /** @@ -2485,9 +2579,10 @@ public class BasicTreeUI */ public boolean isEnabled() { + // TODO: Implement this properly. return false; } - }// TreeCancelEditingAction + } /** * Updates the TreeState in response to nodes expanding/collapsing. @@ -2501,6 +2596,7 @@ public class BasicTreeUI */ public TreeExpansionHandler() { + // Nothing to do here. } /** @@ -2511,6 +2607,9 @@ public class BasicTreeUI */ public void treeExpanded(TreeExpansionEvent event) { + validCachedPreferredSize = false; + updateCurrentVisiblePath(); + tree.revalidate(); tree.repaint(); } @@ -2522,6 +2621,9 @@ public class BasicTreeUI */ public void treeCollapsed(TreeExpansionEvent event) { + validCachedPreferredSize = false; + updateCurrentVisiblePath(); + tree.revalidate(); tree.repaint(); } }// TreeExpansionHandler @@ -2547,6 +2649,7 @@ public class BasicTreeUI */ public TreeHomeAction(int direction, String name) { + // TODO: Implement this properly } /** @@ -2557,6 +2660,7 @@ public class BasicTreeUI */ public void actionPerformed(ActionEvent e) { + // TODO: Implement this properly } /** @@ -2566,9 +2670,10 @@ public class BasicTreeUI */ public boolean isEnabled() { + // TODO: Implement this properly return false; } - }// TreeHomeAction + } /** * TreeIncrementAction is used to handle up/down actions. Selection is moved @@ -2591,6 +2696,7 @@ public class BasicTreeUI */ public TreeIncrementAction(int direction, String name) { + // TODO: Implement this properly } /** @@ -2606,11 +2712,11 @@ public class BasicTreeUI if (e.getActionCommand().equals("selectPreviousChangeLead")) { Object prev = getPreviousVisibleNode(last); - + if (prev != null) { TreePath newPath = new TreePath(getPathToRoot(prev, 0)); - selectPath(tree, new TreePath(getPathToRoot(prev, 0))); + selectPath(tree, newPath); tree.setLeadSelectionPath(newPath); } } @@ -2627,15 +2733,17 @@ public class BasicTreeUI else if (e.getActionCommand().equals("selectPrevious")) { Object prev = getPreviousVisibleNode(last); + if (prev != null) { TreePath newPath = new TreePath(getPathToRoot(prev, 0)); - selectPath(tree, new TreePath(getPathToRoot(prev, 0))); + selectPath(tree, newPath); } } else if (e.getActionCommand().equals("selectNext")) { Object next = getNextVisibleNode(last); + if (next != null) { TreePath newPath = new TreePath(getPathToRoot(next, 0)); @@ -2671,21 +2779,22 @@ public class BasicTreeUI */ public boolean isEnabled() { + // TODO: Implement this properly return false; } - }// TreeIncrementAction + } /** * Forwards all TreeModel events to the TreeState. */ - public class TreeModelHandler - implements TreeModelListener + public class TreeModelHandler implements TreeModelListener { /** * Constructor */ public TreeModelHandler() { + // Nothing to do here. } /** @@ -2703,6 +2812,9 @@ public class BasicTreeUI */ public void treeNodesChanged(TreeModelEvent e) { + validCachedPreferredSize = false; + updateCurrentVisiblePath(); + tree.revalidate(); tree.repaint(); } @@ -2716,6 +2828,9 @@ public class BasicTreeUI */ public void treeNodesInserted(TreeModelEvent e) { + validCachedPreferredSize = false; + updateCurrentVisiblePath(); + tree.revalidate(); tree.repaint(); } @@ -2732,6 +2847,9 @@ public class BasicTreeUI */ public void treeNodesRemoved(TreeModelEvent e) { + validCachedPreferredSize = false; + updateCurrentVisiblePath(); + tree.revalidate(); tree.repaint(); } @@ -2747,6 +2865,12 @@ public class BasicTreeUI */ public void treeStructureChanged(TreeModelEvent e) { + if (e.getPath().length == 1 + && !e.getPath()[0].equals(treeModel.getRoot())) + tree.expandPath(new TreePath(treeModel.getRoot())); + updateCurrentVisiblePath(); + validCachedPreferredSize = false; + tree.revalidate(); tree.repaint(); } }// TreeModelHandler @@ -2754,8 +2878,7 @@ public class BasicTreeUI /** * TreePageAction handles page up and page down events. */ - public class TreePageAction - extends AbstractAction + public class TreePageAction extends AbstractAction { /** Specifies the direction to adjust the selection by. */ protected int direction; @@ -2770,6 +2893,7 @@ public class BasicTreeUI */ public TreePageAction(int direction, String name) { + this.direction = direction; } /** @@ -2780,6 +2904,7 @@ public class BasicTreeUI */ public void actionPerformed(ActionEvent e) { + // TODO: Implement this properly. } /** @@ -2797,14 +2922,14 @@ public class BasicTreeUI * Listens for changes in the selection model and updates the display * accordingly. */ - public class TreeSelectionHandler - implements TreeSelectionListener + public class TreeSelectionHandler implements TreeSelectionListener { /** * Constructor */ public TreeSelectionHandler() { + // Nothing to do here. } /** @@ -2824,8 +2949,7 @@ public class BasicTreeUI /** * For the first selected row expandedness will be toggled. */ - public class TreeToggleAction - extends AbstractAction + public class TreeToggleAction extends AbstractAction { /** * Constructor @@ -2835,6 +2959,7 @@ public class BasicTreeUI */ public TreeToggleAction(String name) { + // Nothing to do here. } /** @@ -2845,6 +2970,7 @@ public class BasicTreeUI */ public void actionPerformed(ActionEvent e) { + // TODO: Implement this properly. } /** @@ -2862,8 +2988,7 @@ public class BasicTreeUI * 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 + public class TreeTraverseAction extends AbstractAction { /** * Determines direction to traverse, 1 means expand, -1 means collapse. @@ -2880,6 +3005,7 @@ public class BasicTreeUI */ public TreeTraverseAction(int direction, String name) { + this.direction = direction; } /** @@ -2890,16 +3016,15 @@ public class BasicTreeUI */ public void actionPerformed(ActionEvent e) { - TreeModel mod = tree.getModel(); Object last = tree.getLeadSelectionPath().getLastPathComponent(); if (e.getActionCommand().equals("selectParent")) { TreePath path = new TreePath(getPathToRoot(last, 0)); - Object p = getParent(mod.getRoot(), last); + Object p = getParent(treeModel.getRoot(), last); - if (!mod.isLeaf(last) && tree.isExpanded(path)) - tree.collapsePath(path); + if (!treeModel.isLeaf(last)) + toggleExpandState(path); else if (p != null) selectPath(tree, new TreePath(getPathToRoot(p, 0))); } @@ -2907,8 +3032,8 @@ public class BasicTreeUI { TreePath path = new TreePath(getPathToRoot(last, 0)); - if (!mod.isLeaf(last) && tree.isCollapsed(path)) - tree.expandPath(path); + if (!treeModel.isLeaf(last)) + toggleExpandState(path); else { Object next = getNextVisibleNode(last); @@ -2926,9 +3051,10 @@ public class BasicTreeUI */ public boolean isEnabled() { + // TODO: Implement this properly return false; } - } // TreeTraverseAction + } /** * Returns the cell bounds for painting selected cells Package private for use @@ -2951,8 +3077,7 @@ public class BasicTreeUI FontMetrics fm = tree.getToolkit().getFontMetrics(f); if (s != null) - return new Rectangle(x, y, - SwingUtilities.computeStringWidth(fm, s) + 4, + return new Rectangle(x, y, SwingUtilities.computeStringWidth(fm, s), fm.getHeight()); } return new Rectangle(x, y, 0, 0); @@ -2982,80 +3107,19 @@ public class BasicTreeUI int rowHeight = getRowHeight(); if (startNode == null || startNode.equals(node)) { - if (!tree.isRootVisible() - && tree.isExpanded(new TreePath(mod.getRoot()))) - return new Point(x + ((getLevel(node)) * rightChildIndent), y); - - return new Point(x + ((getLevel(node) + 1) * rightChildIndent), y); - } - - if (!mod.isLeaf(startNode) - && tree.isExpanded(new TreePath(getPathToRoot(startNode, 0))) - && !mod.isLeaf(startNode) && mod.getChildCount(startNode) > 0) - { - Object child = mod.getChild(startNode, 0); - if (child != null) - return getCellLocation(x, y + rowHeight, tree, mod, node, child); + int level = getLevel(node); + if (level == 0) + return new Point(x, y); + if (!tree.isRootVisible() && + tree.isExpanded(new TreePath(mod.getRoot()))) + return new Point(x + ((level - 1) * rightChildIndent), y); + return new Point(x + (level * rightChildIndent), y); } - return getCellLocation(x, y + rowHeight, tree, mod, node, getNextVisibleNode(startNode)); } /** - * Paints a node in the tree Package private for use in inner classes. - * - * @param g - * the Graphics context in which to paint - * @param x - * the x location of the node - * @param y - * the y location of the node - * @param tree - * the tree to draw on - * @param node - * the object to draw - */ - void paintNode(Graphics g, int x, int y, JTree tree, Object node, - boolean isLeaf) - { - TreePath curr = new TreePath(getPathToRoot(node, 0)); - boolean selected = tree.isPathSelected(curr); - boolean expanded = false; - boolean hasIcons = false; - - if (tree.isVisible(curr)) - { - if (!isLeaf) - expanded = tree.isExpanded(curr); - - if (editingComponent != null && editingPath != null && isEditing(tree) - && node.equals(editingPath.getLastPathComponent())) - { - Rectangle bounds = getPathBounds(tree, editingPath); - rendererPane.paintComponent(g, editingComponent.getParent(), null, - new Rectangle(0, 0, bounds.width, - bounds.height)); - } - else - { - TreeCellRenderer dtcr = tree.getCellRenderer(); - if (dtcr == null) - dtcr = createDefaultCellRenderer(); - - int row = getRowForPath(tree, curr); - - Component c = dtcr.getTreeCellRendererComponent(tree, node, - selected, expanded, - isLeaf, row, false); - - rendererPane.paintComponent(g, c, c.getParent(), - getCellBounds(x, y, node)); - } - } - } - - /** * Recursively paints all elements of the tree Package private for use in * inner classes. * @@ -3065,8 +3129,6 @@ public class BasicTreeUI * 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 @@ -3077,71 +3139,79 @@ public class BasicTreeUI * is the current object to draw * @return int - current descent of the tree */ - int paintRecursive(Graphics g, int indentation, int descent, int childNumber, + int paintRecursive(Graphics g, int indentation, int descent, int depth, JTree tree, TreeModel mod, Object curr) { - Rectangle clip = g.getClipBounds(); + Rectangle clip = tree.getVisibleRect(); if (indentation > clip.x + clip.width + rightChildIndent || descent > clip.y + clip.height + getRowHeight()) return descent; + TreePath path = new TreePath(getPathToRoot(curr, 0)); int halfHeight = getRowHeight() / 2; int halfWidth = rightChildIndent / 2; int y0 = descent + halfHeight; int heightOfLine = descent + halfHeight; + int row = getRowForPath(tree, path); boolean isRootVisible = tree.isRootVisible(); - - if (mod.isLeaf(curr)) + boolean isExpanded = tree.isExpanded(path); + boolean isLeaf = mod.isLeaf(curr); + Rectangle bounds = getPathBounds(tree, path); + Object root = mod.getRoot(); + + if (isLeaf) { - paintNode(g, indentation + 4, descent, tree, curr, true); + paintRow(g, clip, null, bounds, path, row, true, false, true); descent += getRowHeight(); } else { if (depth > 0 || isRootVisible) { - paintNode(g, indentation + 4, descent, tree, curr, false); + paintRow(g, clip, null, bounds, path, row, isExpanded, false, false); descent += getRowHeight(); y0 += halfHeight; } - - int max = 0; - if (!mod.isLeaf(curr)) - max = mod.getChildCount(curr); - if (tree.isExpanded(new TreePath(getPathToRoot(curr, 0)))) + + if (isExpanded) { + int max = mod.getChildCount(curr); for (int i = 0; i < max; i++) { + Object child = mod.getChild(curr, i); + boolean childVis = tree.isVisible(new TreePath + (getPathToRoot(child, 0))); int indent = indentation + rightChildIndent; if (!isRootVisible && depth == 0) indent = 0; - else if ((!isRootVisible && !curr.equals(mod.getRoot())) - || isRootVisible) + else if (isRootVisible || + (!isRootVisible && !curr.equals(root)) && childVis) { g.setColor(getHashColor()); heightOfLine = descent + halfHeight; - g.drawLine(indentation + halfWidth, heightOfLine, - indentation + rightChildIndent, heightOfLine); + paintHorizontalLine(g, (JComponent) tree, heightOfLine, + indentation + halfWidth, indentation + rightChildIndent); } - descent = paintRecursive(g, indent, descent, i, depth + 1, - tree, mod, mod.getChild(curr, i)); + descent = paintRecursive(g, indent, descent, depth + 1, + tree, mod, child); } } } - if (tree.isExpanded(new TreePath(getPathToRoot(curr, 0)))) - if (y0 != heightOfLine && !mod.isLeaf(curr) - && mod.getChildCount(curr) > 0) + if (isExpanded) + if (y0 != heightOfLine + && (mod.getChildCount(curr) > 0 && + tree.isVisible(new TreePath(getPathToRoot(mod.getChild + (curr, 0), 0))))) { g.setColor(getHashColor()); - g.drawLine(indentation + halfWidth, y0, indentation + halfWidth, - heightOfLine); + paintVerticalLine(g, (JComponent) tree, indentation + halfWidth, y0, + heightOfLine); } - return descent; } - + /** * Recursively paints all the control icons on the tree. Package private for * use in inner classes. @@ -3152,76 +3222,99 @@ public class BasicTreeUI * 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 + * @param node * is the current object to draw - * @return int - current descent of the tree + * @return int current descent of the tree */ int paintControlIcons(Graphics g, int indentation, int descent, - int childNumber, int depth, JTree tree, TreeModel mod, + 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(); + TreePath path = new TreePath(getPathToRoot(node, 0)); + Icon icon = getCurrentControlIcon(path); + + Rectangle clip = tree.getVisibleRect(); if (indentation > clip.x + clip.width + rightChildIndent || descent > clip.y + clip.height + getRowHeight()) return descent; - + if (mod.isLeaf(node)) descent += rowHeight; else - { + { + if (!node.equals(mod.getRoot()) && + (tree.isRootVisible() || getLevel(node) != 1)) + { + int width = icon.getIconWidth(); + int height = icon.getIconHeight() + 2; + int posX = indentation - rightChildIndent; + int posY = descent; + if (width > rightChildIndent) + posX -= gap; + else posX += width/2; + + if (height < rowHeight) + posY += height/2; + + icon.paintIcon(tree, g, posX, posY); + } + if (depth > 0 || tree.isRootVisible()) descent += rowHeight; - - int max = 0; - if (!mod.isLeaf(node)) - max = mod.getChildCount(node); - if (tree.isExpanded(new TreePath(getPathToRoot(node, 0)))) + + if (tree.isExpanded(path)) { - if (!node.equals(mod.getRoot())) - ei.paintIcon(tree, g, indentation - rightChildIndent - 3, h); - + int max = 0; + if (!mod.isLeaf(node)) + max = mod.getChildCount(node); + for (int i = 0; i < max; i++) { int indent = indentation + rightChildIndent; + Object child = mod.getChild(node, i); if (depth == 0 && !tree.isRootVisible()) - indent = -1; - - descent = paintControlIcons(g, indent, descent, i, depth + 1, - tree, mod, mod.getChild(node, i)); + indent = 1; + if (tree.isVisible(new TreePath(getPathToRoot(child, 0)))) + descent = paintControlIcons(g, indent, descent, depth + 1, + tree, mod, child); } } - else if (!node.equals(mod.getRoot())) - ci.paintIcon(tree, g, indentation - rightChildIndent - 3, - descent - getRowHeight()); } - + return descent; } /** - * Returns true if the LookAndFeel implements the control icons Package + * Returns true if the LookAndFeel implements the control icons. Package * private for use in inner classes. * - * @return true if control icons are visible + * @returns true if there are control icons */ boolean hasControlIcons() { - if (UIManager.getLookAndFeelDefaults().getIcon("Tree.expandedIcon") == null - || UIManager.getLookAndFeelDefaults().getIcon("Tree.collapsedIcon") == null) - return false; - return true; + if (expandedIcon != null || collapsedIcon != null) + return true; + return false; + } + + /** + * Returns control icon. It is null if the LookAndFeel does not implements the + * control icons. Package private for use in inner classes. + * + * @return control icon if it exists. + */ + Icon getCurrentControlIcon(TreePath path) + { + if (tree.isExpanded(path)) + return expandedIcon; + return collapsedIcon; } /** @@ -3235,8 +3328,10 @@ public class BasicTreeUI */ Object getParent(Object root, Object node) { - if (root == null || node == null) + if (root == null || node == null || + root.equals(node)) return null; + if (node instanceof TreeNode) return ((TreeNode) node).getParent(); return findNode(root, node); @@ -3253,113 +3348,69 @@ public class BasicTreeUI */ private Object findNode(Object root, Object node) { - TreeModel mod = tree.getModel(); - int size = 0; - if (!mod.isLeaf(root)) - size = mod.getChildCount(root); - for (int i = 0; i < size; i++) - { - if (mod.getIndexOfChild(root, node) != -1) - return root; - - Object n = findNode(mod.getChild(root, i), node); - if (n != null) - return n; - } - return null; - } - - /** - * 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. - */ - Object getNextVisibleNode(Object node) - { - Object next = null; - TreePath current = null; - - if (node != null) - next = getNextNode(node); - - if (next != null) + if (!treeModel.isLeaf(root) && !root.equals(node)) { - current = new TreePath(getPathToRoot(next, 0)); - if (tree.isVisible(current)) - return next; - - while (next != null && !tree.isVisible(current)) + int size = treeModel.getChildCount(root); + for (int j = 0; j < size; j++) { - next = getNextNode(next); + Object child = treeModel.getChild(root, j); + if (node.equals(child)) + return root; - if (next != null) - current = new TreePath(getPathToRoot(next, 0)); + Object n = findNode(child, node); + if (n != null) + return n; } } - return next; + return null; } - + /** * Get previous visible node in the tree. Package private for use in inner * classes. * - * @param the + * @param node - * current node * @return the next visible node in the JTree. Return null if there are no * more. */ Object getPreviousVisibleNode(Object node) { - Object prev = null; - TreePath current = null; - - if (node != null) - prev = getPreviousNode(node); - - if (prev != null) + updateCurrentVisiblePath(); + if (currentVisiblePath != null) { - current = new TreePath(getPathToRoot(prev, 0)); - if (tree.isVisible(current)) - return prev; - - while (prev != null && !tree.isVisible(current)) - { - prev = getPreviousNode(prev); - - if (prev != null) - current = new TreePath(getPathToRoot(prev, 0)); - } + Object[] nodes = currentVisiblePath.getPath(); + int i = 0; + while (i < nodes.length && !node.equals(nodes[i])) + i++; + // return the next node + if (i-1 >= 0) + return nodes[i-1]; } - return prev; + return null; } /** * Returns the next node in the tree Package private for use in inner classes. * - * @param the + * @param curr - * current node * @return the next node in the tree */ Object getNextNode(Object curr) { - TreeModel mod = tree.getModel(); - if (!mod.isLeaf(curr) && mod.getChildCount(curr) > 0) - return mod.getChild(curr, 0); + if (!treeModel.isLeaf(curr) && treeModel.getChildCount(curr) > 0) + return treeModel.getChild(curr, 0); Object node = curr; Object sibling = null; - do { sibling = getNextSibling(node); - node = getParent(mod.getRoot(), node); + node = getParent(treeModel.getRoot(), node); } while (sibling == null && node != null); - + return sibling; } @@ -3367,14 +3418,13 @@ public class BasicTreeUI * Returns the previous node in the tree Package private for use in inner * classes. * - * @param the + * @param node * current node * @return the previous node in the tree */ Object getPreviousNode(Object node) { - TreeModel mod = tree.getModel(); - Object parent = getParent(mod.getRoot(), node); + Object parent = getParent(treeModel.getRoot(), node); if (parent == null) return null; @@ -3384,13 +3434,13 @@ public class BasicTreeUI return parent; int size = 0; - if (!mod.isLeaf(sibling)) - size = mod.getChildCount(sibling); + if (!treeModel.isLeaf(sibling)) + size = treeModel.getChildCount(sibling); while (size > 0) { - sibling = mod.getChild(sibling, size - 1); - if (!mod.isLeaf(sibling)) - size = mod.getChildCount(sibling); + sibling = treeModel.getChild(sibling, size - 1); + if (!treeModel.isLeaf(sibling)) + size = treeModel.getChildCount(sibling); else size = 0; } @@ -3402,52 +3452,50 @@ public class BasicTreeUI * Returns the next sibling in the tree Package private for use in inner * classes. * - * @param the + * @param node - * current node * @return the next sibling in the tree */ Object getNextSibling(Object node) { - TreeModel mod = tree.getModel(); - Object parent = getParent(mod.getRoot(), node); + Object parent = getParent(treeModel.getRoot(), node); if (parent == null) return null; - int index = mod.getIndexOfChild(parent, node) + 1; + int index = treeModel.getIndexOfChild(parent, node) + 1; int size = 0; - if (!mod.isLeaf(parent)) - size = mod.getChildCount(parent); + if (!treeModel.isLeaf(parent)) + size = treeModel.getChildCount(parent); if (index == 0 || index >= size) return null; - return mod.getChild(parent, index); + return treeModel.getChild(parent, index); } - + /** * Returns the previous sibling in the tree Package private for use in inner * classes. * - * @param the + * @param node - * current node * @return the previous sibling in the tree */ Object getPreviousSibling(Object node) { - TreeModel mod = tree.getModel(); - Object parent = getParent(mod.getRoot(), node); + Object parent = getParent(treeModel.getRoot(), node); if (parent == null) return null; - int index = mod.getIndexOfChild(parent, node) - 1; + int index = treeModel.getIndexOfChild(parent, node) - 1; int size = 0; - if (!mod.isLeaf(parent)) - size = mod.getChildCount(parent); + if (!treeModel.isLeaf(parent)) + size = treeModel.getChildCount(parent); if (index < 0 || index >= size) return null; - return mod.getChild(parent, index); + return treeModel.getChild(parent, index); } /** @@ -3463,22 +3511,24 @@ public class BasicTreeUI { if (path != null) { - if (tree.getSelectionModel().getSelectionMode() == TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION) + 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) + else if (tree.getSelectionModel().getSelectionMode() == + TreeSelectionModel.CONTIGUOUS_TREE_SELECTION) { // TODO } else { - tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); - - tree.getSelectionModel().clearSelection(); tree.addSelectionPath(path); tree.setLeadSelectionPath(path); + tree.getSelectionModel().setSelectionMode + (TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); } } } @@ -3495,7 +3545,6 @@ public class BasicTreeUI */ Object[] getPathToRoot(Object node, int depth) { - TreeModel mod = tree.getModel(); if (node == null) { if (depth == 0) @@ -3504,7 +3553,7 @@ public class BasicTreeUI return new Object[depth]; } - Object[] path = getPathToRoot(getParent(mod.getRoot(), node), depth + 1); + Object[] path = getPathToRoot(getParent(treeModel.getRoot(), node), depth + 1); path[path.length - depth - 1] = node; return path; } @@ -3512,22 +3561,23 @@ public class BasicTreeUI /** * Returns the level of the node in the tree. * - * @param the + * @param node - * current node * @return the number of the level */ int getLevel(Object node) { int count = -1; + Object current = node; do { - current = getParent(tree.getModel().getRoot(), current); + current = getParent(treeModel.getRoot(), current); count++; } while (current != null); - + return count; } @@ -3586,10 +3636,271 @@ public class BasicTreeUI * is the center position in y-direction FIXME what to do if x < * (icon.width / 2). Same with y */ - protected void drawCentered(JComponent c, Graphics g, Icon icon, int x, int y) + protected void drawCentered(Component c, Graphics g, Icon icon, int x, int y) { int beginPositionX = x - icon.getIconWidth() / 2; int beginPositionY = y - icon.getIconHeight() / 2; icon.paintIcon(c, g, beginPositionX, beginPositionY); } + + /** + * Draws a dashed horizontal line. + * + * @param g - the graphics configuration. + * @param y - the y location to start drawing at + * @param x1 - the x location to start drawing at + * @param x2 - the x location to finish drawing at + */ + protected void drawDashedHorizontalLine(Graphics g, int y, int x1, int x2) + { + for (int i = x1; i < x2; i += 2) + g.drawLine(i, y, i + 1, y); + } + + /** + * Draws a dashed vertical line. + * + * @param g - the graphics configuration. + * @param x - the x location to start drawing at + * @param y1 - the y location to start drawing at + * @param y2 - the y location to finish drawing at + */ + protected void drawDashedVerticalLine(Graphics g, int x, int y1, int y2) + { + for (int i = y1; i < y2; i += 2) + g.drawLine(x, i, x, i + 1); + } + + /** + * Paints the expand (toggle) part of a row. The receiver should NOT modify + * clipBounds, or insets. + * + * @param g - the graphics configuration + * @param clipBounds - + * @param insets - + * @param bounds - bounds of expand control + * @param path - path to draw control for + * @param row - row to draw control for + * @param isExpanded - is the row expanded + * @param hasBeenExpanded - has the row already been expanded + * @param isLeaf - is the path a leaf + */ + protected void paintExpandControl(Graphics g, Rectangle clipBounds, + Insets insets, Rectangle bounds, + TreePath path, int row, + boolean isExpanded, boolean hasBeenExpanded, + boolean isLeaf) + { + if (treeModel != null && hasControlIcons()) + paintControlIcons(g, 0, 0, 0, tree, treeModel, path.getLastPathComponent()); + } + + /** + * Paints the horizontal part of the leg. The receiver should NOT modify + * clipBounds, or insets. + * NOTE: parentRow can be -1 if the root is not visible. + * + * @param g - the graphics configuration + * @param clipBounds - + * @param insets - + * @param bounds - bounds of expand control + * @param path - path to draw control for + * @param row - row to draw control for + * @param isExpanded - is the row expanded + * @param hasBeenExpanded - has the row already been expanded + * @param isLeaf - is the path a leaf + */ + protected void paintHorizontalPartOfLeg(Graphics g, Rectangle clipBounds, + Insets insets, Rectangle bounds, + TreePath path, int row, + boolean isExpanded, boolean hasBeenExpanded, + boolean isLeaf) + { + // FIXME: not implemented + } + + /** + * Paints the vertical part of the leg. The receiver should NOT modify + * clipBounds, insets. + * + * @param g - the graphics configuration. + * @param clipBounds - + * @param insets - + * @param path - the path to draw the vertical part for. + */ + protected void paintVerticalPartOfLeg(Graphics g, Rectangle clipBounds, + Insets insets, TreePath path) + { + // FIXME: not implemented + } + + /** + * Paints the renderer part of a row. The receiver should NOT modify clipBounds, + * or insets. + * + * @param g - the graphics configuration + * @param clipBounds - + * @param insets - + * @param bounds - bounds of expand control + * @param path - path to draw control for + * @param row - row to draw control for + * @param isExpanded - is the row expanded + * @param hasBeenExpanded - has the row already been expanded + * @param isLeaf - is the path a leaf + */ + protected void paintRow(Graphics g, Rectangle clipBounds, + Insets insets, Rectangle bounds, + TreePath path, int row, + boolean isExpanded, boolean hasBeenExpanded, + boolean isLeaf) + { + boolean selected = tree.isPathSelected(path); + boolean hasIcons = false; + Object node = path.getLastPathComponent(); + + if (tree.isVisible(path)) + { + if (!validCachedPreferredSize) + updateCachedPreferredSize(); + bounds.x += gap; + bounds.width = preferredSize.width + bounds.x; + + if (editingComponent != null && editingPath != null && isEditing(tree) + && node.equals(editingPath.getLastPathComponent())) + { + rendererPane.paintComponent(g, editingComponent.getParent(), null, + bounds); + } + else + { + TreeCellRenderer dtcr = tree.getCellRenderer(); + if (dtcr == null) + dtcr = createDefaultCellRenderer(); + + Component c = dtcr.getTreeCellRendererComponent(tree, node, + selected, isExpanded, isLeaf, row, tree.hasFocus()); + rendererPane.paintComponent(g, c, c.getParent(), bounds); + } + } + } + + /** + * Prepares for the UI to uninstall. + */ + protected void prepareForUIUninstall() + { + // TODO: Implement this properly. + } + + /** + * Returns true if the expand (toggle) control should be drawn for the + * specified row. + * + * @param path - current path to check for. + * @param row - current row to check for. + * @param isExpanded - true if the path is expanded + * @param hasBeenExpanded - true if the path has been expanded already + * @param isLeaf - true if the row is a lead + */ + protected boolean shouldPaintExpandControl(TreePath path, int row, + boolean isExpanded, + boolean hasBeenExpanded, + boolean isLeaf) + { + Object node = path.getLastPathComponent(); + if (treeModel != null && (!isLeaf && !node.equals(treeModel.getRoot())) && + (tree.isRootVisible() || getLevel(node) != 1)) + return true; + return false; + } + + /** + * Updates the cached current TreePath of all visible + * nodes in the tree. + */ + void updateCurrentVisiblePath() + { + if (treeModel == null) + return; + + Object next = treeModel.getRoot(); + Rectangle bounds = getCellBounds(0, 0, next); + boolean rootVisible = isRootVisible(); + + // If root is not a valid size to be visible, or is + // not visible and the tree is expanded, then the next node acts + // as the root + if ((bounds.width == 0 && bounds.height == 0) || (!rootVisible + && tree.isExpanded(new TreePath(next)))) + next = getNextNode(next); + + Object root = next; + TreePath current = null; + while (next != null) + { + if (current == null) + current = new TreePath(next); + else + current = current.pathByAddingChild(next); + do + { + TreePath path = new TreePath(getPathToRoot(next, 0)); + if ((tree.isVisible(path) && tree.isExpanded(path)) + || treeModel.isLeaf(next)) + next = getNextNode(next); + else + { + Object pNext = next; + next = getNextSibling(pNext); + // if no next sibling, check parent's next sibling. + if (next == null) + { + Object parent = getParent(root, pNext); + while (next == null && parent != null) + { + next = getNextSibling(parent); + if (next == null) + parent = getParent(treeModel.getRoot(), next); + } + } + } + } + while (next != null && + !tree.isVisible(new TreePath(getPathToRoot(next, 0)))); + } + + currentVisiblePath = current; + if (currentVisiblePath != null) + tree.setVisibleRowCount(currentVisiblePath.getPathCount()); + else tree.setVisibleRowCount(0); + + if (tree.getSelectionModel() != null && tree.getSelectionCount() == 0 && + currentVisiblePath != null) + selectPath(tree, new TreePath(getPathToRoot(currentVisiblePath. + getPathComponent(0), 0))); + } + + /** + * Get next visible node in the currentVisiblePath. Package private for use in + * inner classes. + * + * @param node + * current node + * @return the next visible node in the JTree. Return null if there are no + * more. + */ + Object getNextVisibleNode(Object node) + { + if (currentVisiblePath != null) + { + Object[] nodes = currentVisiblePath.getPath(); + int i = 0; + while (i < nodes.length && !node.equals(nodes[i])) + i++; + // return the next node + if (i+1 < nodes.length) + return nodes[i+1]; + } + return null; + } } // BasicTreeUI diff --git a/libjava/classpath/javax/swing/plaf/basic/BasicViewportUI.java b/libjava/classpath/javax/swing/plaf/basic/BasicViewportUI.java index 0d46133..51b902d 100644 --- a/libjava/classpath/javax/swing/plaf/basic/BasicViewportUI.java +++ b/libjava/classpath/javax/swing/plaf/basic/BasicViewportUI.java @@ -38,61 +38,22 @@ 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.LookAndFeel; 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 + protected void installDefaults(JComponent c) { - public void stateChanged(ChangeEvent event) - { - JViewport v = (JViewport) event.getSource(); - v.repaint(); - } - } - - void installDefaults(JComponent c) - { c.setOpaque(true); + LookAndFeel.installColorsAndFont(c, "Viewport.background", + "Viewport.foreground", "Viewport.font"); } - - void uninstallDefaults(JComponent c) - { - } - - void installListeners(JComponent c) + protected void uninstallDefaults(JComponent c) { - ((JViewport)c).addChangeListener(changeListener); - } - - void uninstallListeners(JComponent c) - { - ((JViewport)c).removeChangeListener(changeListener); - } - - public BasicViewportUI() - { - changeListener = new ChangeHandler(); + // TODO: Implement this properly. } public static ComponentUI createUI(JComponent c) @@ -103,132 +64,12 @@ public class BasicViewportUI extends ViewportUI public void installUI(JComponent c) { super.installUI(c); - installListeners(c); + installDefaults(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(new Rectangle(0, 0, portBounds.width, portBounds.height)); - 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); + super.uninstallUI(c); + uninstallDefaults(c); } } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalBorders.java b/libjava/classpath/javax/swing/plaf/metal/MetalBorders.java index f555106..4fa3b36 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalBorders.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalBorders.java @@ -45,21 +45,29 @@ import java.awt.Insets; import javax.swing.AbstractButton; import javax.swing.ButtonModel; +import javax.swing.JButton; import javax.swing.JInternalFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JScrollPane; import javax.swing.JTextField; +import javax.swing.JToggleButton; +import javax.swing.JToolBar; +import javax.swing.SwingConstants; +import javax.swing.UIDefaults; +import javax.swing.UIManager; 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.BasicBorders; +import javax.swing.text.JTextComponent; /** - * This factory class creates borders for the different Swing components - * UI. + * A factory class that creates borders for the different Swing components. * * @author Roman Kennke (roman@kennke.org) */ @@ -69,12 +77,24 @@ public class MetalBorders /** The shared instance for getButtonBorder(). */ private static Border buttonBorder; + /** The shared instance for getToggleButtonBorder(). */ + private static Border toggleButtonBorder; + + /** The shared instance for getDesktopIconBorder(). */ + private static Border desktopIconBorder; + /** The shared instance for getRolloverButtonBorder(). */ private static Border toolbarButtonBorder; /** The shared instance for getTextFieldBorder(). */ private static Border textFieldBorder; + /** The shared instance for getTextBorder(). */ + private static Border textBorder; + + /** The shared instance for getRolloverBorder(). */ + private static Border rolloverBorder; + /** * A MarginBorder that gets shared by multiple components. * Created on demand by the private helper function {@link @@ -83,20 +103,19 @@ public class MetalBorders private static BasicBorders.MarginBorder marginBorder; /** - * The border that is drawn around Swing buttons. + * A border used for {@link JButton} components. */ - public static class ButtonBorder - extends AbstractBorder - implements UIResource + 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. + * Creates a new instance of <code>ButtonBorder</code>. */ public ButtonBorder() { + // Nothing to do here. } /** @@ -122,46 +141,55 @@ public class MetalBorders 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); + if (c.isEnabled()) + { + // draw dark border + g.setColor(darkShadow); + g.drawRect(x, y, 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); + if (!bmodel.isPressed()) + { + // draw light border + g.setColor(light); + g.drawRect(x + 1, y + 1, w - 2, h - 2); - // 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(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 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); + // 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); + } + } + else + { + // draw disabled border + g.setColor(MetalLookAndFeel.getInactiveControlTextColor()); + g.drawRect(x, y, w - 2, h - 2); } } /** - * Returns the insets of the ButtonBorder. + * Returns the insets of the <code>ButtonBorder</code>. * * @param c the component for which the border is used * - * @return the insets of the ButtonBorder + * @return The insets of the ButtonBorder */ public Insets getBorderInsets(Component c) { @@ -169,19 +197,20 @@ public class MetalBorders } /** - * Returns the insets of the ButtonBorder in the specified Insets object. + * Returns the insets of the <code>ButtonBorder</code> in the specified + * <code>newInsets</code> object. * * @param c the component for which the border is used - * @param newInsets the insets object where to put the values + * @param newInsets the insets object where to put the values (if + * <code>null</code>, a new instance is created). * - * @return the insets of the ButtonBorder + * @return The insets. */ 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; @@ -191,6 +220,71 @@ public class MetalBorders } /** + * A border used when painting {@link JInternalFrame} instances. + */ + static class DesktopIconBorder extends AbstractBorder + implements UIResource + { + /** + * Creates a new border instance. + */ + public DesktopIconBorder() + { + // Nothing to do here. + } + + /** + * Returns the border insets. + * + * @param c the component (ignored). + * + * @return The border insets. + */ + public Insets getBorderInsets(Component c) + { + return getBorderInsets(c, null); + } + + /** + * Returns the border insets. + * + * @param c the component (ignored). + * @return The border insets. + */ + public Insets getBorderInsets(Component c, Insets newInsets) + { + if (newInsets == null) + newInsets = new Insets(3, 3, 2, 3); + else + { + newInsets.top = 3; + newInsets.left = 3; + newInsets.bottom = 2; + newInsets.right = 3; + } + return newInsets; + } + + /** + * Paints the border for the specified component. + * + * @param c the component. + * @param g the graphics device. + * @param x the x-coordinate. + * @param y the y-coordinate. + * @param w the width. + * @param h the height. + */ + public void paintBorder(Component c, Graphics g, int x, int y, int w, + int h) + { + g.setColor(MetalLookAndFeel.getControlDarkShadow()); + g.drawRect(x, y, w - 1, h - 1); + } + + } + + /** * A simple 3D border. */ public static class Flush3DBorder extends AbstractBorder @@ -201,6 +295,7 @@ public class MetalBorders */ public Flush3DBorder() { + // Nothing to do here. } /** @@ -262,6 +357,88 @@ public class MetalBorders } /** + * A border used for a {@link JInternalFrame} when it is being used as a + * palette. + * + * @since 1.3 + */ + public static class PaletteBorder extends AbstractBorder + implements UIResource + { + /** + * Creates a new <code>PaletteBorder</code>. + */ + public PaletteBorder() + { + // Nothing to do here. + } + + /** + * Returns the border insets. + * + * @param c the component (ignored). + * + * @return The border insets. + */ + public Insets getBorderInsets(Component c) + { + return getBorderInsets(c, null); + } + + /** + * Returns the border insets. + * + * @param c the component (ignored). + * @param newInsets the insets object that, if non-<code>null</code>, will + * be populated with the result from this method. + * + * @return The border insets. + */ + public Insets getBorderInsets(Component c, Insets newInsets) + { + if (newInsets == null) + newInsets = new Insets(1, 1, 1, 1); + else + { + newInsets.top = 1; + newInsets.left = 1; + newInsets.bottom = 1; + newInsets.right = 1; + } + return newInsets; + } + + /** + * Paints the border for the specified component. + * + * @param c the component (ignored). + * @param g the graphics device. + * @param x the x-coordinate. + * @param y the y-coordinate. + * @param w the width. + * @param h the height. + */ + public void paintBorder(Component c, Graphics g, int x, int y, int w, + int h) + { + Color savedColor = g.getColor(); + + // draw the outline + g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow()); + g.drawRect(x, y, w - 1, h - 1); + + // put a dot in each corner + g.setColor(MetalLookAndFeel.getControl()); + g.fillRect(x, y, 1, 1); + g.fillRect(x + w - 1, y, 1, 1); + g.fillRect(x + w - 1, y + h - 1, 1, 1); + g.fillRect(x, y + h - 1, 1, 1); + g.setColor(savedColor); + } + + } + + /** * A border used for the {@link JTextField} component. */ public static class TextFieldBorder extends Flush3DBorder @@ -272,6 +449,7 @@ public class MetalBorders */ public TextFieldBorder() { + // Nothing to do here. } /** @@ -286,8 +464,17 @@ public class MetalBorders */ public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) - { - if (c.isEnabled()) + { + boolean enabledTextBorder; + if (c instanceof JTextComponent) + { + JTextComponent tc = (JTextComponent) c; + enabledTextBorder = tc.isEnabled() && tc.isEditable(); + } + else + enabledTextBorder = false; + + if (enabledTextBorder) super.paintBorder(c, g, x, y, w, h); else { @@ -301,7 +488,7 @@ public class MetalBorders } /** - * A border used when painting {@link JInternalFrame} instances. + * A border used for the {@link JInternalFrame} component. */ public static class InternalFrameBorder extends AbstractBorder implements UIResource @@ -311,6 +498,7 @@ public class MetalBorders */ public InternalFrameBorder() { + // Nothing to do here. } /** @@ -386,7 +574,10 @@ public class MetalBorders g.drawLine(x + w - 3, y + 14, x + w - 3, y + h - 15); // draw the line highlights - g.setColor(MetalLookAndFeel.getControl()); + if (f.isSelected()) + g.setColor(MetalLookAndFeel.getPrimaryControlShadow()); + else + g.setColor(MetalLookAndFeel.getControlShadow()); g.drawLine(x + 15, y + 3, x + w - 14, y + 3); g.drawLine(x + 15, y + h - 2, x + w - 14, y + h - 2); g.drawLine(x + 3, y + 15, x + 3, y + h - 14); @@ -396,24 +587,129 @@ public class MetalBorders } /** + * A border used for {@link JInternalFrame} components that are + * presented as dialogs (by the {@link JOptionPane} class). + */ + public static class OptionDialogBorder extends AbstractBorder + implements UIResource + { + + /** + * Creates a new border instance. + */ + public OptionDialogBorder() + { + // Nothing to do here. + } + + /** + * Returns the border insets. + * + * @param c the component (ignored). + * + * @return The border insets. + */ + public Insets getBorderInsets(Component c) + { + return getBorderInsets(c, null); + } + + /** + * Returns the border insets. + * + * @param c the component (ignored). + * @return The border insets. + */ + public Insets getBorderInsets(Component c, Insets newInsets) + { + if (newInsets == null) + newInsets = new Insets(3, 3, 3, 3); + else + { + newInsets.top = 3; + newInsets.left = 3; + newInsets.bottom = 3; + newInsets.right = 3; + } + return newInsets; + } + + /** + * Paints the border for the specified component. + * + * @param c the component. + * @param g the graphics device. + * @param x the x-coordinate. + * @param y the y-coordinate. + * @param w the width. + * @param h the height. + */ + public void paintBorder(Component c, Graphics g, int x, int y, int w, + int h) + { + + JInternalFrame f = (JInternalFrame) c; + g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow()); + if (f.getContentPane() instanceof JOptionPane) + { + JOptionPane pane = (JOptionPane) f.getContentPane(); + int type = pane.getMessageType(); + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + if (type == JOptionPane.QUESTION_MESSAGE) + { + Color bc = defaults.getColor( + "OptionPane.questionDialog.border.background"); + if (bc != null) + g.setColor(bc); + } + if (type == JOptionPane.WARNING_MESSAGE) + { + Color bc = defaults.getColor( + "OptionPane.warningDialog.border.background"); + if (bc != null) + g.setColor(bc); + } + else if (type == JOptionPane.ERROR_MESSAGE) + { + Color bc = defaults.getColor( + "OptionPane.errorDialog.border.background"); + if (bc != null) + g.setColor(bc); + } + } + + // fill the border background + g.fillRect(x, y, w, 3); + g.fillRect(x, y, 3, h); + g.fillRect(x + w - 3, y, 3, h); + g.fillRect(x, y + h - 3, w, 3); + + // draw a dot in each corner + g.setColor(MetalLookAndFeel.getControl()); + g.fillRect(x, y, 1, 1); + g.fillRect(x + w - 1, y, 1, 1); + g.fillRect(x + w - 1, y + h - 1, 1, 1); + g.fillRect(x, y + h - 1, 1, 1); + + } + + } + + /** * A border used for {@link JMenu} and {@link JMenuItem} components. */ - public static class MenuItemBorder - extends AbstractBorder - implements UIResource + public static class MenuItemBorder extends AbstractBorder + implements UIResource { /** The border insets. */ - protected static Insets borderInsets = new Insets(2, 2, 2, 2); - - // TODO: find where the real colors come from - private static Color borderColorDark = new Color(102, 102, 153); - private static Color borderColorLight = new Color(255, 255, 255); + protected static Insets borderInsets = new Insets(1, 1, 1, 1); /** * Creates a new border instance. */ public MenuItemBorder() { + // Nothing to do here. } /** @@ -430,15 +726,17 @@ public class MetalBorders public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { + Color dark = MetalLookAndFeel.getPrimaryControlDarkShadow(); + Color light = MetalLookAndFeel.getPrimaryControlHighlight(); if (c instanceof JMenu) { JMenu menu = (JMenu) c; if (menu.isSelected()) { - g.setColor(borderColorDark); + g.setColor(dark); g.drawLine(x, y, x, y + h); g.drawLine(x, y, x + w, y); g.drawLine(x + w - 2, y + 1, x + w - 2, y + h); - g.setColor(borderColorLight); + g.setColor(light); g.drawLine(x + w - 1, y + 1, x + w - 1, y + h); } } @@ -446,12 +744,18 @@ public class MetalBorders { JMenuItem item = (JMenuItem) c; if (item.isArmed()) - { - g.setColor(borderColorDark); - g.drawLine(x, y, x + w, y); - g.setColor(borderColorLight); - g.drawLine(x, y + h - 1, x + w, y + h - 1); - } + { + g.setColor(dark); + g.drawLine(x, y, x + w, y); + g.setColor(light); + g.drawLine(x, y + h - 1, x + w, y + h - 1); + } + else + { + // Normally we draw a light line on the left. + g.setColor(light); + g.drawLine(x, y, x, y + h); + } } } @@ -505,6 +809,7 @@ public class MetalBorders */ public MenuBarBorder() { + // Nothing to do here. } /** @@ -558,7 +863,7 @@ public class MetalBorders } /** - * A border for JScrollPanes. + * A border for {@link JScrollPane} components. */ public static class ScrollPaneBorder extends AbstractBorder @@ -572,6 +877,7 @@ public class MetalBorders */ public ScrollPaneBorder() { + // Nothing to do here. } /** @@ -634,6 +940,45 @@ public class MetalBorders } /** + * A button border that is only visible when the mouse pointer is within + * the button's bounds. + */ + public static class RolloverButtonBorder + extends MetalBorders.ButtonBorder + { + /** + * Creates a new border instance. + */ + public RolloverButtonBorder() + { + // Nothing to do here. + } + + /** + * Paints the border. + * + * @param c the component. + * @param g the graphics device. + * @param x the x-coordinate. + * @param y the y-coordinate. + * @param w the width. + * @param h the height. + */ + public void paintBorder(Component c, Graphics g, int x, int y, int w, + int h) + { + boolean mouseIsOver = false; + if (c instanceof AbstractButton) + { + ButtonModel bmodel = ((AbstractButton) c).getModel(); + mouseIsOver = bmodel.isRollover(); + } + if (mouseIsOver) + super.paintBorder(c, g, x, y, w, h); + } + } + + /** * This border is used in Toolbar buttons as inner border. */ static class RolloverMarginBorder extends AbstractBorder @@ -646,6 +991,7 @@ public class MetalBorders */ public RolloverMarginBorder() { + // Nothing to do here. } /** @@ -693,13 +1039,14 @@ public class MetalBorders { /** The border's insets. */ - protected static Insets borderInsets = new Insets(2, 2, 1, 1); + protected static Insets borderInsets = new Insets(3, 1, 2, 1); /** * Constructs a new PopupMenuBorder. */ public PopupMenuBorder() { + // Nothing to do here. } /** @@ -763,13 +1110,258 @@ public class MetalBorders // 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); } } /** + * A border used for the {@link JToggleButton} component. + * + * @since 1.3 + */ + public static class ToggleButtonBorder + extends ButtonBorder + { + /** + * Creates a new border instance. + */ + public ToggleButtonBorder() + { + // Nothing to do here. + } + + /** + * Paints the toggle 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(); + + if (c.isEnabled()) + { + // draw dark border + g.setColor(darkShadow); + g.drawRect(x, y, w - 2, h - 2); + + if (!bmodel.isArmed()) + { + // draw light border + g.setColor(light); + 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); + if (bmodel.isSelected()) + g.setColor(middle); + g.drawLine(x + 1, y + 1, x + w - 3, y + 1); + g.drawLine(x + 1, y + 1, x + 1, y + h - 3); + + // draw crossing pixels of both borders + g.setColor(shadow); + g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2); + g.drawLine(x + w - 2, y + 1, x + w - 2, y + 1); + } + 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(shadow); + 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.drawLine(x + 1, y + h - 2, x + 1, y + h - 2); + g.drawLine(x + w - 2, y + 1, x + w - 2, y + 1); + + } + // draw corners + g.setColor(middle); + g.drawLine(x, y + h - 1, x, y + h - 1); + g.drawLine(x + w - 1, y, x + w - 1, y); + } + else + { + // draw disabled border + g.setColor(MetalLookAndFeel.getControlDisabled()); + g.drawRect(x, y, w - 2, h - 2); + } + } + } + + /** + * A border used for the {@link JToolBar} component. + */ + public static class ToolBarBorder extends AbstractBorder + implements UIResource, SwingConstants + { + /** + * Creates a new border instance. + */ + public ToolBarBorder() + { + // Nothing to do here. + } + + /** + * Returns the border insets. + * + * @param c the component (ignored). + * + * @return The border insets. + */ + public Insets getBorderInsets(Component c) + { + return getBorderInsets(c, null); + } + + /** + * Returns the border insets. + * + * @param c the component (ignored). + * @return The border insets. + */ + public Insets getBorderInsets(Component c, Insets newInsets) + { + JToolBar tb = (JToolBar) c; + if (tb.getOrientation() == JToolBar.HORIZONTAL) + { + if (newInsets == null) + newInsets = new Insets(2, 16, 2, 2); + else + { + newInsets.top = 2; + newInsets.left = 16; + newInsets.bottom = 2; + newInsets.right = 2; + } + return newInsets; + } + else // assume JToolBar.VERTICAL + { + if (newInsets == null) + newInsets = new Insets(16, 2, 2, 2); + else + { + newInsets.top = 16; + newInsets.left = 2; + newInsets.bottom = 2; + newInsets.right = 2; + } + return newInsets; + } + + } + + /** + * Paints the border for the specified component. + * + * @param c the component. + * @param g the graphics device. + * @param x the x-coordinate. + * @param y the y-coordinate. + * @param w the width. + * @param h the height. + */ + public void paintBorder(Component c, Graphics g, int x, int y, int w, + int h) + { + + JToolBar tb = (JToolBar) c; + if (tb.getOrientation() == JToolBar.HORIZONTAL) + { + MetalUtils.fillMetalPattern(tb, g, x + 2, y + 2, x + 11, y + h - 5, + MetalLookAndFeel.getControlHighlight(), + MetalLookAndFeel.getControlDarkShadow()); + } + else + { + MetalUtils.fillMetalPattern(tb, g, x + 2, y + 2, x + w - 5, y + 11, + MetalLookAndFeel.getControlHighlight(), + MetalLookAndFeel.getControlDarkShadow()); + } + } + + } + + /** + * A border for table header cells. + * + * @since 1.3 + */ + public static class TableHeaderBorder extends AbstractBorder + { + /** + * The insets of this border. + */ + // TODO: According to tests that I have done, this is really the border + // that should be returned by getBorderInsets(). However, the name + // is very distracting. Is there any deeper meaning in it? + protected Insets editorBorderInsets; + + /** + * Creates a new instance of <code>TableHeaderBorder</code>. + */ + public TableHeaderBorder() + { + editorBorderInsets = new Insets(1, 1, 1, 1); + } + + /** + * Return the insets of this border. + * + * @return the insets of this border + */ + public Insets getBorderInsets(Component c) + { + return editorBorderInsets; + } + + /** + * Paints the border. + * + * @param c the component for which to paint the border + * @param g the graphics context to use + * @param x the x cooridinate of the border rectangle + * @param y the y cooridinate of the border rectangle + * @param w the width of the border rectangle + * @param h the height of the border rectangle + */ + public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) + { + Color dark = MetalLookAndFeel.getControlDarkShadow(); + Color light = MetalLookAndFeel.getWhite(); + Color old = g.getColor(); + g.setColor(light); + g.drawLine(x, y, x + w - 2, y); + g.drawLine(x, y, x, y + h - 2); + g.setColor(dark); + g.drawLine(x + w - 1, y, x + w - 1, y + h - 1); + g.drawLine(x + 1, y + h - 1, x + w - 1, y + h - 1); + g.setColor(old); + } + } + + /** * Returns a border for Swing buttons in the Metal Look & Feel. * * @return a border for Swing buttons in the Metal Look & Feel @@ -785,6 +1377,40 @@ public class MetalBorders } return buttonBorder; } + + /** + * Returns a border for use with {@link JToggleButton} components. + * + * @return A border. + * + * @since 1.3 + */ + public static Border getToggleButtonBorder() + { + if (toggleButtonBorder == null) + { + Border outer = new ToggleButtonBorder(); + Border inner = getMarginBorder(); + toggleButtonBorder = new BorderUIResource.CompoundBorderUIResource + (outer, inner); + } + return toggleButtonBorder; + } + + /** + * Returns a border instance that is used with a {@link JInternalFrame} when + * it is in the iconified state. + * + * @return A border. + * + * @since 1.3 + */ + public static Border getDesktopIconBorder() + { + if (desktopIconBorder == null) + desktopIconBorder = new DesktopIconBorder(); + return desktopIconBorder; + } /** * Returns a border for use by the {@link JTextField} component. @@ -796,11 +1422,36 @@ public class MetalBorders public static Border getTextFieldBorder() { if (textFieldBorder == null) - textFieldBorder = new TextFieldBorder(); + { + Border inner = getMarginBorder(); + Border outer = new TextFieldBorder(); + textFieldBorder = + new BorderUIResource.CompoundBorderUIResource(outer, inner); + } return textFieldBorder; } /** + * Returns the border that is used for text components (except text fields, + * which use {@link #getTextFieldBorder}. + * + * @return the border that is used for text components + * + * @since 1.3 + */ + public static Border getTextBorder() + { + if (textBorder == null) + { + Border inner = getMarginBorder(); + Border outer = new Flush3DBorder(); + textBorder = + new BorderUIResource.CompoundBorderUIResource(outer, inner); + } + return textBorder; + } + + /** * Returns a border for Toolbar buttons in the Metal Look & Feel. * * @return a border for Toolbar buttons in the Metal Look & Feel @@ -828,4 +1479,22 @@ public class MetalBorders marginBorder = new BasicBorders.MarginBorder(); return marginBorder; } + + /** + * Returns a shared instance of a compound border for rollover buttons. + * + * @return A shared border instance. + */ + static Border getRolloverBorder() + { + if (rolloverBorder == null) + { + Border outer = new MetalBorders.RolloverButtonBorder(); + Border inner = MetalBorders.getMarginBorder(); + rolloverBorder = new BorderUIResource.CompoundBorderUIResource(outer, + inner); + } + return rolloverBorder; + } + } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalButtonListener.java b/libjava/classpath/javax/swing/plaf/metal/MetalButtonListener.java new file mode 100644 index 0000000..e6fb22e --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalButtonListener.java @@ -0,0 +1,86 @@ +/* MetalButtonListener.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.beans.PropertyChangeEvent; + +import javax.swing.AbstractButton; +import javax.swing.plaf.UIResource; +import javax.swing.plaf.basic.BasicButtonListener; + +/** + * A listener for buttons under the {@link MetalLookAndFeel}. + * + * @see MetalButtonUI#createButtonListener + */ +class MetalButtonListener extends BasicButtonListener +{ + + /** + * Creates a new instance. + * + * @param button the button. + */ + public MetalButtonListener(AbstractButton button) + { + super(button); + } + + /** + * Handles property change events. + * + * @param e the event. + */ + public void propertyChange(PropertyChangeEvent e) + { + super.propertyChange(e); + if (e.getPropertyName().equals( + AbstractButton.ROLLOVER_ENABLED_CHANGED_PROPERTY)) + { + AbstractButton b = (AbstractButton) e.getSource(); + if (b.getBorder() instanceof UIResource) + { + if (Boolean.TRUE.equals(e.getNewValue())) + b.setBorder(MetalBorders.getRolloverBorder()); + else if (Boolean.FALSE.equals(e.getNewValue())) + b.setBorder(MetalBorders.getButtonBorder()); + } + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalButtonUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalButtonUI.java index 0dac5ec..02c39c1 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalButtonUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalButtonUI.java @@ -39,18 +39,23 @@ exception statement from your version. */ package javax.swing.plaf.metal; import java.awt.Color; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Rectangle; import javax.swing.AbstractButton; +import javax.swing.JButton; 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.UIResource; +import javax.swing.plaf.basic.BasicButtonListener; import javax.swing.plaf.basic.BasicButtonUI; /** - * The Metal Look & Feel implementation for - * {@link javax.swing.AbstractButton}s. + * A UI delegate for the {@link JButton} component. * * @author Roman Kennke (roman@kennke.org) */ @@ -58,27 +63,25 @@ public class MetalButtonUI extends BasicButtonUI { - /** The cached MetalButtonUI instance. */ - private static MetalButtonUI instance = null; - - /** The color for the focus border. */ + /** The color used to draw the focus rectangle around the text and/or icon. */ protected Color focusColor; - - /** The color that indicates a selected button. */ + + /** The background color for the button when it is pressed. */ protected Color selectColor; /** The color for disabled button labels. */ protected Color disabledTextColor; /** - * Creates a new instance of MetalButtonUI. + * Creates a new instance. */ public MetalButtonUI() { super(); - focusColor = getFocusColor(); - selectColor = getSelectColor(); - disabledTextColor = getDisabledTextColor(); + UIDefaults def = UIManager.getLookAndFeelDefaults(); + focusColor = def.getColor(getPropertyPrefix() + "focus"); + selectColor = def.getColor(getPropertyPrefix() + "select"); + disabledTextColor = def.getColor(getPropertyPrefix() + "disabledText"); } /** @@ -88,8 +91,7 @@ public class MetalButtonUI */ protected Color getFocusColor() { - UIDefaults def = UIManager.getLookAndFeelDefaults(); - return def.getColor(getPropertyPrefix() + ".focus"); + return focusColor; } /** @@ -99,8 +101,7 @@ public class MetalButtonUI */ protected Color getSelectColor() { - UIDefaults def = UIManager.getLookAndFeelDefaults(); - return def.getColor(getPropertyPrefix() + ".select"); + return selectColor; } /** @@ -110,36 +111,123 @@ public class MetalButtonUI */ protected Color getDisabledTextColor() { - UIDefaults def = UIManager.getLookAndFeelDefaults(); - return def.getColor(getPropertyPrefix() + ".disabledText"); + return disabledTextColor; } /** - * Returns an instance of MetalButtonUI. - * - * @param component a button for which a UI instance should be returned + * Returns a UI delegate for the specified component. + * + * @param c the component (should be a subclass of {@link AbstractButton}). + * + * @return A new instance of <code>MetalButtonUI</code>. */ - public static ComponentUI createUI(JComponent component) - { - if (instance == null) - instance = new MetalButtonUI(); - return instance; + public static ComponentUI createUI(JComponent c) { + return new MetalButtonUI(); } /** - * Install the Look & Feel defaults for Buttons. - * - * @param button the button for which to install the Look & Feel + * Installs the default settings for the specified button. + * + * @param button the button. + * + * @see #uninstallDefaults(AbstractButton) */ public void installDefaults(AbstractButton button) { super.installDefaults(button); + if (button.isRolloverEnabled()) + { + if (button.getBorder() instanceof UIResource) + button.setBorder(MetalBorders.getRolloverBorder()); + } + } + + /** + * Removes the defaults added by {@link #installDefaults(AbstractButton)}. + */ + public void uninstallDefaults(AbstractButton button) + { + super.uninstallDefaults(button); + if (button.getBorder() instanceof UIResource) + button.setBorder(null); + } - UIDefaults defaults = UIManager.getLookAndFeelDefaults(); - button.setFont(defaults.getFont("Button.font")); + /** + * Returns a button listener for the specified button. + * + * @param button the button. + * + * @return A button listener. + */ + protected BasicButtonListener createButtonListener(AbstractButton button) + { + return new MetalButtonListener(button); + } - if (button.getParent() instanceof JToolBar) - button.setBorder(MetalBorders.getToolbarButtonBorder()); + /** + * Paints the background of the button to indicate that it is in the "pressed" + * state. + * + * @param g the graphics context. + * @param b the button. + */ + protected void paintButtonPressed(Graphics g, AbstractButton b) + { + if (b.isContentAreaFilled()) + { + Rectangle area = b.getVisibleRect(); + g.setColor(selectColor); + g.fillRect(area.x, area.y, area.width, area.height); + } + } + + /** + * Paints the focus rectangle around the button text and/or icon. + * + * @param g the graphics context. + * @param b the button. + * @param viewRect the button bounds. + * @param textRect the text bounds. + * @param iconRect the icon bounds. + */ + protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect, + Rectangle textRect, Rectangle iconRect) { + if (b.isEnabled() && b.hasFocus() && b.isFocusPainted()) + { + Color savedColor = g.getColor(); + g.setColor(getFocusColor()); + Rectangle focusRect = iconRect.union(textRect); + g.drawRect(focusRect.x - 1, focusRect.y, + focusRect.width + 1, focusRect.height); + g.setColor(savedColor); + } + } + + /** + * Paints the button text. + * + * @param g the graphics context. + * @param c the button. + * @param textRect the text bounds. + * @param text the text to display. + */ + protected void paintText(Graphics g, JComponent c, Rectangle textRect, + String text) + { + AbstractButton b = (AbstractButton) c; + 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(getDisabledTextColor()); + g.drawString(text, textRect.x, textRect.y + fm.getAscent()); + } } - } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxIcon.java b/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxIcon.java index 3f3c9ce..6b9f31b 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxIcon.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxIcon.java @@ -38,10 +38,8 @@ 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; @@ -49,8 +47,7 @@ import javax.swing.JCheckBox; import javax.swing.plaf.UIResource; /** - * An {@link Icon} implementation for {@link JCheckBox}es in the - * Metal Look & Feel. + * An {@link Icon} used by the {@link MetalCheckBoxUI} class. * * @author Roman Kennke (roman@kennke.org) */ @@ -79,7 +76,10 @@ public class MetalCheckBoxIcon */ protected void drawCheck(Component c, Graphics g, int x, int y) { - g.setColor(Color.BLACK); + if (c.isEnabled()) + g.setColor(MetalLookAndFeel.getBlack()); + else + g.setColor(MetalLookAndFeel.getControlDisabled()); g.drawLine(3 + x, 5 + y, 3 + x, 9 + y); g.drawLine(4 + x, 5 + y, 4 + x, 9 + y); g.drawLine(5 + x, 7 + y, 9 + x, 3 + y); diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxUI.java index c46cb5f..b4f6f0a 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalCheckBoxUI.java @@ -44,8 +44,7 @@ import javax.swing.UIDefaults; import javax.swing.plaf.ComponentUI; /** - * A UI delegate for the {@link JCheckBox} component under the - * {@link MetalLookAndFeel}. + * A UI delegate for the {@link JCheckBox} component. */ public class MetalCheckBoxUI extends MetalRadioButtonUI @@ -64,11 +63,11 @@ public class MetalCheckBoxUI } /** - * Returns an instance of MetalCheckBoxUI. + * Returns a shared instance of <code>MetalCheckBoxUI</code>. * * @param component the component for which we return an UI instance * - * @return an instance of MetalCheckBoxUI + * @return A shared instance of <code>MetalCheckBoxUI</code>. */ public static ComponentUI createUI(JComponent component) { diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxButton.java b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxButton.java new file mode 100644 index 0000000..6993e18 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxButton.java @@ -0,0 +1,241 @@ +/* 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.Component; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Rectangle; + +import javax.swing.CellRendererPane; +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JList; +import javax.swing.SwingUtilities; + +/** + * A button used by the {@link MetalComboBoxUI} class. + */ +public class MetalComboBoxButton extends JButton { + + /** A reference to the JComboBox that the button belongs to. */ + protected JComboBox comboBox; + + /** A reference to the JList. */ + protected JList listBox; + + /** ??? */ + protected CellRendererPane rendererPane; + + /** The button icon. */ + protected Icon comboIcon; + + /** Display just the icon, or the icon plus the label. */ + protected boolean iconOnly; + + /** + * Creates a new button. + * + * @param cb the combo that the button is used for (<code>null</code> not + * permitted). + * @param i the icon displayed on the button. + * @param pane the rendering pane. + * @param list the list. + */ + public MetalComboBoxButton(JComboBox cb, Icon i, CellRendererPane pane, + JList list) + { + this(cb, i, cb.isEditable(), pane, list); + } + + /** + * Creates a new button. + * + * @param cb the combo that the button is used for (<code>null</code> not + * permitted). + * @param i the icon displayed on the button. + * @parma onlyIcon a flag that specifies whether the button displays only an + * icon, or text as well. + * @param pane the rendering pane. + * @param list the list. + */ + public MetalComboBoxButton(JComboBox cb, Icon i, boolean onlyIcon, + CellRendererPane pane, JList list) + { + super(); + if (cb == null) + throw new NullPointerException("Null 'cb' argument"); + comboBox = cb; + comboIcon = i; + iconOnly = onlyIcon; + listBox = list; + rendererPane = pane; + } + + /** + * Returns the combo box that the button is used with. + * + * @return The combo box. + */ + public final JComboBox getComboBox() + { + return comboBox; + } + + /** + * Sets the combo box that the button is used with. + * + * @param cb the combo box. + */ + public final void setComboBox(JComboBox cb) + { + comboBox = cb; + } + + /** + * Returns the icon displayed by the button. By default, this will be an + * instance of {@link MetalComboBoxIcon}. + * + * @return The icon displayed by the button. + */ + public final Icon getComboIcon() + { + return comboIcon; + } + + /** + * Sets the icon displayed by the button. + * + * @param i the icon. + */ + public final void setComboIcon(Icon i) + { + comboIcon = i; + } + + /** + * Returns a flag that controls whether the button displays an icon only, + * or text as well. + * + * @return A boolean. + */ + public final boolean isIconOnly() + { + return iconOnly; + } + + /** + * Sets the flag that controls whether the button displays an icon only, + * or text as well. + * + * @param isIconOnly the flag. + */ + public final void setIconOnly(boolean isIconOnly) + { + iconOnly = isIconOnly; + } + + /** + * Returns <code>false</code>, to indicate that this component is not part + * of the focus traversal group. + * + * @return <code>false</code> + */ + public boolean isFocusTraversable() + { + return false; + } + + /** + * Enables or disables the button. + * + * @param enabled the new status. + */ + public void setEnabled(boolean enabled) + { + super.setEnabled(enabled); + // TODO: figure out what this might need to be used for + // perhaps it has something to do with the button's icon and/or border? + } + + /** + * Paints the component. + * + * @param g the graphics device. + */ + public void paintComponent(Graphics g) + { + super.paintComponent(g); + if (iconOnly) + { + Rectangle bounds = getBounds(); + int x = (bounds.width - comboIcon.getIconWidth()) / 2; + int y = (bounds.height - comboIcon.getIconHeight()) / 2; + comboIcon.paintIcon(comboBox, g, x, y); + } + else + { + Object selected = comboBox.getModel().getSelectedItem(); + if (selected == null) + selected = ""; + Rectangle bounds = comboBox.getBounds(); + Rectangle innerArea = SwingUtilities.calculateInnerArea(this, null); + Insets insets = comboBox.getInsets(); + Rectangle renderArea = new Rectangle(innerArea.x, innerArea.y, + innerArea.width - comboIcon.getIconWidth() - 4, innerArea.height); + Component cellRenderer + = comboBox.getRenderer().getListCellRendererComponent(this.listBox, + selected, comboBox.getSelectedIndex(), false, false); + cellRenderer.setBackground(comboBox.getBackground()); + cellRenderer.setEnabled(comboBox.isEnabled()); + rendererPane.paintComponent(g, cellRenderer, this, renderArea); + if (comboBox.hasFocus()) + { + g.setColor(MetalLookAndFeel.getFocusColor()); + g.drawRect(innerArea.x, innerArea.y - 1, innerArea.width - 1, + innerArea.height); + } + int iconX = bounds.width - insets.right - comboIcon.getIconWidth() - 7; + int iconY = insets.top + + (bounds.height - comboIcon.getIconHeight()) / 2; + comboIcon.paintIcon(comboBox, g, iconX, iconY); + } + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxEditor.java b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxEditor.java new file mode 100644 index 0000000..a531079 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxEditor.java @@ -0,0 +1,143 @@ +/* MetalComboBoxEditor.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.JTextField; +import javax.swing.plaf.basic.BasicComboBoxEditor; +import javax.swing.plaf.metal.MetalLookAndFeel; +import javax.swing.plaf.metal.MetalBorders.Flush3DBorder; + +/** + * An editor used by the {@link MetalComboBoxUI} class. + */ +public class MetalComboBoxEditor extends BasicComboBoxEditor +{ + /** + * A border used for the {@link JTextField} component. + */ + static class MetalComboBoxEditorBorder extends Flush3DBorder + { + /** + * Creates a new border instance. + */ + public MetalComboBoxEditorBorder() + { + // Nothing to do here. + } + + /** + * Paints the border for the specified component. + * + * @param c the component (ignored). + * @param g the graphics device. + * @param x the x-coordinate. + * @param y the y-coordinate. + * @param w the width. + * @param h the height. + */ + public void paintBorder(Component c, Graphics g, int x, int y, int w, + int h) + { + Color savedColor = g.getColor(); + if (c.isEnabled()) + g.setColor(MetalLookAndFeel.getControlDarkShadow()); + else + g.setColor(MetalLookAndFeel.getControlShadow()); + g.drawLine(x, y, x + w - 1, y); + g.drawLine(x, y, x, y + h - 2); + g.drawLine(x + 2, y + h - 2, x + w - 1, y + h - 2); + g.setColor(MetalLookAndFeel.getControl()); + g.drawLine(x + 1, y + h - 2, x + 1, y + h - 2); + g.setColor(MetalLookAndFeel.getWhite()); + g.drawLine(x, y + h - 1, x + w - 1, y + h - 1); + g.setColor(savedColor); + } + + /** + * 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, which is zero + * for the default implementation provided by AbstractButton. + * + * @see #getBorderInsets(java.awt.Component, java.awt.Insets) + */ + public Insets getBorderInsets(Component c) + { + return editorBorderInsets; + } + } + + /** + * A subclass of {@link MetalComboBoxEditor} that implements the + * {@link javax.swing.plaf.UIResource} interface. + */ + public static class UIResource extends MetalComboBoxEditor + implements javax.swing.plaf.UIResource + { + /** + * Creates a new instance. + */ + public UIResource() + { + // Nothing to do here. + } + } + + /** The editor's border insets. */ + protected static Insets editorBorderInsets = new Insets(4, 2, 4, 0); + + /** + * Creates a new editor. + */ + public MetalComboBoxEditor() + { + super(); + editor.setBorder(new MetalComboBoxEditorBorder()); + } + +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxIcon.java b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxIcon.java index ce4fa7d..f21c5af 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxIcon.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxIcon.java @@ -1,4 +1,4 @@ -/* MetalComboBoxButton.java +/* MetalComboBoxIcon.java Copyright (C) 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -88,10 +88,11 @@ public class MetalComboBoxIcon implements Icon, Serializable { */ 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); + if (c.isEnabled()) + g.setColor(MetalLookAndFeel.getBlack()); + else + g.setColor(MetalLookAndFeel.getControlDisabled()); 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 index 28c279d..a43ee3c 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalComboBoxUI.java @@ -38,20 +38,134 @@ exception statement from your version. */ package javax.swing.plaf.metal; -import java.util.HashMap; +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.MouseEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import javax.swing.CellRendererPane; +import javax.swing.ComboBoxEditor; +import javax.swing.Icon; +import javax.swing.JButton; +import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicComboBoxUI; +import javax.swing.plaf.basic.BasicComboPopup; +import javax.swing.plaf.basic.ComboPopup; -public class MetalComboBoxUI - extends BasicComboBoxUI -{ - /** The UI instances for JComboBoxes. */ - private static HashMap instances = null; +/** + * A UI delegate for the {@link JComboBox} component. + */ +public class MetalComboBoxUI extends BasicComboBoxUI +{ + /** + * A layout manager that arranges the editor component (if active) and the + * button that make up the combo box. + */ + public class MetalComboBoxLayoutManager + extends BasicComboBoxUI.ComboBoxLayoutManager + { + /** + * Creates a new instance of the layout manager. + */ + public MetalComboBoxLayoutManager() + { + // Nothing to do here. + } + + /** + * Arranges the editor (if visible) and button that comprise the combo + * box. + * + * @param parent the parent. + */ + public void layoutContainer(Container parent) + { + JComboBox cb = (JComboBox) parent; + if (!cb.isEditable()) + { + Rectangle bounds = parent.getBounds(); + arrowButton.setBounds(0, 0, bounds.width, bounds.height); + } + else + superLayout(parent); + } + + /** + * Calls the <code>layoutContainer(Container)</code> method in the super + * class. + * + * @param parent the container. + */ + public void superLayout(Container parent) + { + super.layoutContainer(parent); + } + } + + /** + * A listener used to handle property changes in the {@link JComboBox} + * component, to ensure that the UI delegate accurately reflects the current + * state in the rendering onscreen. + */ + public class MetalPropertyChangeListener + extends BasicComboBoxUI.PropertyChangeHandler + { + /** + * Creates a new listener. + */ + public MetalPropertyChangeListener() + { + // Nothing to do here. + } + + /** + * Handles a property change event, updating the UI components as + * appropriate. + * + * @param e the event. + */ + public void propertyChange(PropertyChangeEvent e) + { + if (e.getPropertyName().equals("editable")) + editablePropertyChanged(e); + super.propertyChange(e); + } + } /** + * A popup menu for the combo-box. + * + * @see #createPopup() + * + * @deprecated 1.4 + */ + public class MetalComboPopup extends BasicComboPopup + { + /** + * Creates a new popup. + * + * @param cBox the combo box. + */ + public MetalComboPopup(JComboBox cBox) + { + super(cBox); + } + + public void delegateFocus(MouseEvent e) + { + super.delegateFocus(e); + } + } + + /** * Constructs a new instance of MetalComboBoxUI. */ public MetalComboBoxUI() @@ -68,19 +182,135 @@ public class MetalComboBoxUI */ public static ComponentUI createUI(JComponent component) { - if (instances == null) - instances = new HashMap(); - - Object o = instances.get(component); - MetalComboBoxUI instance; - if (o == null) + return new MetalComboBoxUI(); + } + + /** + * Creates an editor for the combo box. + * + * @return An editor. + */ + protected ComboBoxEditor createEditor() + { + return new MetalComboBoxEditor.UIResource(); + } + + /** + * Creates a popup for the combo box. + * + * @return A popup. + */ + protected ComboPopup createPopup() + { + return new MetalComboPopup(comboBox); + } + + /** + * Creates a new button for use in rendering the JComboBox. + * + * @return A button. + */ + protected JButton createArrowButton() + { + JButton button = new MetalComboBoxButton(comboBox, new MetalComboBoxIcon(), + new CellRendererPane(), listBox); + button.setMargin(new Insets(0, 1, 1, 3)); + return button; + } + + /** + * Creates a new property change listener. + * + * @return A new property change listener. + */ + public PropertyChangeListener createPropertyChangeListener() + { + return new MetalPropertyChangeListener(); + } + + public void paint(Graphics g, JComponent c) + { + // do nothing, the button and text field are painted elsewhere + } + + /** + * Updates the button and text field to reflect a change in the 'editable' + * property. + * + * @param e the event. + * + * @deprecated 1.4 + */ + protected void editablePropertyChanged(PropertyChangeEvent e) + { + if (arrowButton instanceof MetalComboBoxButton) + { + MetalComboBoxButton b = (MetalComboBoxButton) arrowButton; + b.setIconOnly(comboBox.isEditable()); + } + if (comboBox.isEditable()) { - instance = new MetalComboBoxUI(); - instances.put(component, instance); + arrowButton.setText(null); + if (editor != null) + editor.setVisible(true); } else - instance = (MetalComboBoxUI) o; - - return instance; + { + String text = ""; + Object selected = comboBox.getSelectedItem(); + if (selected != null) + text = selected.toString(); + arrowButton.setText(text); + if (editor != null) + editor.setVisible(true); + } + } + + /** + * Creates a new layout manager for the UI delegate. + * + * @return A new layout manager. + */ + protected LayoutManager createLayoutManager() + { + return new MetalComboBoxLayoutManager(); + } + + /** + * Not used in Classpath. + * + * @deprecated 1.4 + */ + protected void removeListeners() + { + // no longer used in JDK 1.4 + } + + /** + * Returns the minimum size for the combo. + * + * @param c the component + * + * @return The minimum size for the combo box. + */ + public Dimension getMinimumSize(JComponent c) + { + Dimension d = getDisplaySize(); + MetalComboBoxButton b = (MetalComboBoxButton) arrowButton; + Insets insets = b.getInsets(); + int insetsH = insets.top + insets.bottom; + int insetsW = insets.left + insets.right; + if (!comboBox.isEditable()) + { + Icon icon = b.getComboIcon(); + int iconWidth = icon.getIconWidth() + 6; + return new Dimension(d.width + insetsW + iconWidth, d.height + insetsH); + } + else + // FIXME: the following dimensions pass most of the Mauve tests, but + // I don't yet understand the logic behind this...it is probably wrong + return new Dimension(d.width + insetsW + (d.height + insetsH) - 4, + d.height + insetsH + 1); } + } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalDesktopIconUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalDesktopIconUI.java index 0087054..ecbb76e 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalDesktopIconUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalDesktopIconUI.java @@ -39,9 +39,13 @@ exception statement from your version. */ package javax.swing.plaf.metal; import javax.swing.JComponent; +import javax.swing.JInternalFrame; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicDesktopIconUI; +/** + * A UI delegate for the {@link JInternalFrame.JDesktopIcon} component. + */ public class MetalDesktopIconUI extends BasicDesktopIconUI { @@ -51,7 +55,7 @@ public class MetalDesktopIconUI private static MetalDesktopIconUI instance = null; /** - * Constructs a new instance of MetalDesktopIconUI. + * Constructs a new instance of <code>MetalDesktopIconUI</code>. */ public MetalDesktopIconUI() { @@ -59,11 +63,11 @@ public class MetalDesktopIconUI } /** - * Returns an instance of MetalDesktopIconUI. + * Returns a shared instance of <code>MetalDesktopIconUI</code>. * * @param component the component for which we return an UI instance * - * @return an instance of MetalDesktopIconUI + * @return A shared instance of <code>MetalDesktopIconUI</code>. */ public static ComponentUI createUI(JComponent component) { diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalFileChooserUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalFileChooserUI.java new file mode 100644 index 0000000..3a2e1c1 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalFileChooserUI.java @@ -0,0 +1,430 @@ +/* MetalFileChooserUI.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.Component; +import java.awt.event.ActionEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.File; +import java.util.List; + +import javax.swing.AbstractAction; +import javax.swing.AbstractListModel; +import javax.swing.ComboBoxModel; +import javax.swing.DefaultListCellRenderer; +import javax.swing.JComponent; +import javax.swing.JFileChooser; +import javax.swing.JList; +import javax.swing.UIManager; +import javax.swing.filechooser.FileFilter; +import javax.swing.filechooser.FileSystemView; +import javax.swing.filechooser.FileView; +import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicFileChooserUI; + + +/** + * A UI delegate for the {@link JFileChooser} component. This class is only + * partially implemented and is not usable yet. + */ +public class MetalFileChooserUI extends BasicFileChooserUI +{ + /** + * A combo box model containing the selected directory and all its parent + * directories. + */ + protected class DirectoryComboBoxModel extends AbstractListModel + implements ComboBoxModel + { + /** Storage for the items in the model. */ + private List items; + + /** The index of the selected item. */ + private int selectedIndex; + + /** + * Creates a new model. + */ + public DirectoryComboBoxModel() + { + items = new java.util.ArrayList(); + selectedIndex = -1; + } + + /** + * Returns the number of items in the model. + * + * @return The number of items in the model. + */ + public int getSize() + { + return items.size(); + } + + /** + * Returns the item at the specified index. + * + * @param index the item index. + * + * @return The item. + */ + public Object getElementAt(int index) + { + return items.get(index); + } + + /** + * Returns the depth of the item at the given <code>index</code>. + * + * @param index the item index. + * + * @return The depth. + */ + public int getDepth(int index) + { + return Math.max(index, 0); + } + + /** + * Returns the selected item, or <code>null</code> if no item is selected. + * + * @return The selected item, or <code>null</code>. + */ + public Object getSelectedItem() + { + if (selectedIndex >= 0) + return items.get(selectedIndex); + else + return null; + } + + /** + * Sets the selected item. This clears all the directories from the + * existing list, and repopulates it with the new selected directory + * and all its parent directories. + * + * @param selectedDirectory the selected directory. + */ + public void setSelectedItem(Object selectedDirectory) + { + items.clear(); + FileSystemView fsv = getFileChooser().getFileSystemView(); + File parent = (File) selectedDirectory; + while (parent != null) + { + items.add(0, parent); + parent = fsv.getParentDirectory(parent); + } + selectedIndex = items.indexOf(selectedDirectory); + fireContentsChanged(this, 0, items.size() - 1); + } + + } + + /** + * Handles changes to the selection in the directory combo box. + */ + protected class DirectoryComboBoxAction extends AbstractAction + { + /** + * Creates a new action. + */ + protected DirectoryComboBoxAction() + { + // Nothing to do here. + } + + /** + * Handles the action event. + * + * @param e the event. + */ + public void actionPerformed(ActionEvent e) + { + JFileChooser fc = getFileChooser(); + fc.setCurrentDirectory((File) directoryModel.getSelectedItem()); + } + } + + /** + * A renderer for the files and directories in the file chooser. + */ + protected class FileRenderer extends DefaultListCellRenderer + { + + /** + * Creates a new renderer. + */ + protected FileRenderer() + { + // Nothing to do here. + } + + /** + * Returns a component that can render the specified value. + * + * @param list the list. + * @param value the value (a {@link File}). + * @param index the index. + * @param isSelected is the item selected? + * @param cellHasFocus does the item have the focus? + * + * @return The renderer. + */ + public Component getListCellRendererComponent(JList list, Object value, + int index, boolean isSelected, boolean cellHasFocus) + { + FileView v = getFileView(getFileChooser()); + File f = (File) value; + setText(v.getName(f)); + setIcon(v.getIcon(f)); + if (isSelected) + { + setBackground(list.getSelectionBackground()); + setForeground(list.getSelectionForeground()); + } + else + { + setBackground(list.getBackground()); + setForeground(list.getForeground()); + } + + setEnabled(list.isEnabled()); + setFont(list.getFont()); + + if (cellHasFocus) + setBorder(UIManager.getBorder("List.focusCellHighlightBorder")); + else + setBorder(noFocusBorder); + return this; + } + } + + /** + * A combo box model for the file selection filters. + */ + protected class FilterComboBoxModel + extends AbstractListModel + implements ComboBoxModel, PropertyChangeListener + { + + /** Storage for the filters in the model. */ + protected FileFilter[] filters; + + /** The index of the selected file filter. */ + private int selectedIndex; + + /** + * Creates a new model. + */ + protected FilterComboBoxModel() + { + filters = new FileFilter[1]; + filters[0] = getAcceptAllFileFilter(getFileChooser()); + selectedIndex = 0; + } + + /** + * Handles property changes. + * + * @param e the property change event. + */ + public void propertyChange(PropertyChangeEvent e) + { + if (e.getPropertyName().equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY)) + { + selectedIndex = -1; + FileFilter selected = (FileFilter) e.getNewValue(); + for (int i = 0; i < filters.length; i++) + if (filters[i].equals(selected)) + selectedIndex = i; + fireContentsChanged(this, -1, -1); + } + else if (e.getPropertyName().equals( + JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY)) + { + // repopulate list + JFileChooser fc = getFileChooser(); + FileFilter[] choosableFilters = fc.getChoosableFileFilters(); + filters = choosableFilters; + fireContentsChanged(this, 0, filters.length); + } + } + + /** + * Sets the selected filter. + * + * @param filter the filter. + */ + public void setSelectedItem(Object filter) + { + // change the filter in the file chooser and let the property change + // event trigger the change to the selected item + getFileChooser().setFileFilter((FileFilter) filter); + } + + /** + * Returns the selected file filter. + * + * @return The selected file filter. + */ + public Object getSelectedItem() + { + if (selectedIndex >= 0) + return filters[selectedIndex]; + return null; + } + + /** + * Returns the number of items in the model. + * + * @return The number of items in the model. + */ + public int getSize() + { + return filters.length; + } + + /** + * Returns the item at the specified index. + * + * @param index the item index. + * + * @return The item at the specified index. + */ + public Object getElementAt(int index) + { + return filters[index]; + } + + } + + /** + * A renderer for the items in the file filter combo box. + */ + public class FilterComboBoxRenderer extends DefaultListCellRenderer + { + /** + * Creates a new renderer. + */ + public FilterComboBoxRenderer() + { + // Nothing to do here. + } + + /** + * Returns a component that can be used to paint the given value within + * the list. + * + * @param list the list. + * @param value the value (a {@link FileFilter}). + * @param index the item index. + * @param isSelected is the item selected? + * @param cellHasFocus does the list cell have focus? + * + * @return A component. + */ + public Component getListCellRendererComponent(JList list, Object value, + int index, boolean isSelected, boolean cellHasFocus) + { + FileFilter filter = (FileFilter) value; + return super.getListCellRendererComponent(list, filter.getDescription(), + index, isSelected, cellHasFocus); + } + } + + /** The model for the directory combo box. */ + DirectoryComboBoxModel directoryModel; + + /** + * A factory method that returns a UI delegate for the specified + * component. + * + * @param c the component (which should be a {@link JFileChooser}). + */ + public static ComponentUI createUI(JComponent c) + { + JFileChooser chooser = (JFileChooser) c; + return new MetalFileChooserUI(chooser); + } + + /** + * Creates a new instance of this UI delegate. + * + * @param filechooser the file chooser component. + */ + public MetalFileChooserUI(JFileChooser filechooser) + { + super(filechooser); + } + + /** + * Creates and returns a new instance of {@link DirectoryComboBoxModel}. + * + * @return A new instance of {@link DirectoryComboBoxModel}. + */ + protected MetalFileChooserUI.DirectoryComboBoxModel + createDirectoryComboBoxModel(JFileChooser fc) + { + return new DirectoryComboBoxModel(); + } + + /** + * Creates and returns a new instance of {@link FilterComboBoxModel}. + * + * @return A new instance of {@link FilterComboBoxModel}. + */ + protected FilterComboBoxModel createFilterComboBoxModel() + { + return new FilterComboBoxModel(); + } + + /** + * Creates and returns a new instance of {@link FilterComboBoxRenderer}. + * + * @return A new instance of {@link FilterComboBoxRenderer}. + */ + protected MetalFileChooserUI.FilterComboBoxRenderer + createFilterComboBoxRenderer() + { + return new FilterComboBoxRenderer(); + } + +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalIconFactory.java b/libjava/classpath/javax/swing/plaf/metal/MetalIconFactory.java index d8c7743..6f4feccf 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalIconFactory.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalIconFactory.java @@ -43,9 +43,11 @@ import java.awt.Component; import java.awt.Graphics; import java.io.Serializable; +import javax.swing.AbstractButton; import javax.swing.Icon; import javax.swing.JCheckBox; import javax.swing.JCheckBoxMenuItem; +import javax.swing.JFileChooser; import javax.swing.JInternalFrame; import javax.swing.JRadioButton; import javax.swing.JRadioButtonMenuItem; @@ -75,6 +77,7 @@ public class MetalIconFactory implements Serializable */ public CheckBoxMenuItemIcon() { + // Nothing to do here. } /** @@ -137,6 +140,385 @@ public class MetalIconFactory implements Serializable } /** + * An icon used for the "detail view" button on a {@link JFileChooser} under + * the {@link MetalLookAndFeel}. + * + * @see MetalIconFactory#getFileChooserDetailViewIcon() + */ + private static class FileChooserDetailViewIcon implements Icon, Serializable + { + + /** + * Creates a new icon. + */ + public FileChooserDetailViewIcon() + { + // Nothing to do here. + } + + /** + * 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 using colors from the {@link MetalLookAndFeel}. + * + * @param c the component (ignored). + * @param g the graphics device. + * @param x the x-coordinate for the top-left of the icon. + * @param y the y-coordinate for the top-left of the icon. + */ + public void paintIcon(Component c, Graphics g, int x, int y) + { + Color savedColor = g.getColor(); + g.setColor(MetalLookAndFeel.getBlack()); + + // file 1 outline + g.drawLine(x + 2, y + 2, x + 5, y + 2); + g.drawLine(x + 6, y + 3, x + 6, y + 7); + g.drawLine(x + 2, y + 7, x + 6, y + 7); + g.drawLine(x + 2, y + 2, x + 2, y + 7); + + // file 2 outline + g.drawLine(x + 2, y + 10, x + 5, y + 10); + g.drawLine(x + 6, y + 11, x + 6, y + 15); + g.drawLine(x + 2, y + 15, x + 6, y + 15); + g.drawLine(x + 2, y + 10, x + 2, y + 15); + + // detail lines + g.drawLine(x + 8, y + 5, x + 15, y + 5); + g.drawLine(x + 8, y + 13, x + 15, y + 13); + + // fill files + g.setColor(MetalLookAndFeel.getPrimaryControl()); + g.fillRect(x + 3, y + 3, 3, 4); + g.fillRect(x + 3, y + 11, 3, 4); + + // highlight files + g.setColor(MetalLookAndFeel.getPrimaryControlHighlight()); + g.drawLine(x + 4, y + 4, x + 4, y + 5); + g.drawLine(x + 4, y + 12, x + 4, y + 13); + + g.setColor(savedColor); + } + } + + /** + * An icon used for the "home folder" button on a {@link JFileChooser} under + * the {@link MetalLookAndFeel}. + * + * @see MetalIconFactory#getFileChooserHomeFolderIcon() + */ + private static class FileChooserHomeFolderIcon implements Icon, Serializable + { + + /** + * Creates a new icon. + */ + public FileChooserHomeFolderIcon() + { + // Nothing to do here. + } + + /** + * 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 using colors from the {@link MetalLookAndFeel}. + * + * @param c the component (ignored). + * @param g the graphics device. + * @param x the x-coordinate for the top-left of the icon. + * @param y the y-coordinate for the top-left of the icon. + */ + public void paintIcon(Component c, Graphics g, int x, int y) + { + Color savedColor = g.getColor(); + g.setColor(MetalLookAndFeel.getBlack()); + + // roof + g.drawLine(x + 1, y + 8, x + 8, y + 1); + g.drawLine(x + 8, y + 1, x + 15, y + 8); + + // base of house + g.drawLine(x + 3, y + 6, x + 3, y + 15); + g.drawLine(x + 3, y + 15, x + 13, y + 15); + g.drawLine(x + 13, y + 6, x + 13, y + 15); + + // door frame + g.drawLine(x + 6, y + 9, x + 6, y + 15); + g.drawLine(x + 6, y + 9, x + 10, y + 9); + g.drawLine(x + 10, y + 9, x + 10, y + 15); + + // chimney + g.drawLine(x + 11, y + 2, x + 11, y + 4); + g.drawLine(x + 12, y + 2, x + 12, y + 5); + + g.setColor(MetalLookAndFeel.getControlDarkShadow()); + + // roof paint + int xx = x + 8; + for (int i = 0; i < 4; i++) + g.drawLine(xx - i, y + 2 + i, xx + i, y + 2 + i); + g.fillRect(x + 4, y + 6, 9, 2); + + // door knob + g.drawLine(x + 9, y + 12, x + 9, y + 12); + + // house paint + g.setColor(MetalLookAndFeel.getPrimaryControl()); + g.drawLine(x + 4, y + 8, x + 12, y + 8); + g.fillRect(x + 4, y + 9, 2, 6); + g.fillRect(x + 11, y + 9, 2, 6); + + g.setColor(savedColor); + } + } + + /** + * An icon used for the "list view" button on a {@link JFileChooser} under + * the {@link MetalLookAndFeel}. + * + * @see MetalIconFactory#getFileChooserListViewIcon() + */ + private static class FileChooserListViewIcon implements Icon, Serializable + { + /** + * Creates a new icon. + */ + public FileChooserListViewIcon() + { + // Nothing to do here. + } + + /** + * 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 using colors from the {@link MetalLookAndFeel}. + * + * @param c the component (ignored). + * @param g the graphics device. + * @param x the x-coordinate for the top-left of the icon. + * @param y the y-coordinate for the top-left of the icon. + */ + public void paintIcon(Component c, Graphics g, int x, int y) + { + Color savedColor = g.getColor(); + g.setColor(MetalLookAndFeel.getBlack()); + + // file 1 outline + g.drawLine(x + 2, y + 2, x + 5, y + 2); + g.drawLine(x + 6, y + 3, x + 6, y + 7); + g.drawLine(x + 2, y + 7, x + 6, y + 7); + g.drawLine(x + 2, y + 2, x + 2, y + 7); + + // file 2 outline + g.drawLine(x + 2, y + 10, x + 5, y + 10); + g.drawLine(x + 6, y + 11, x + 6, y + 15); + g.drawLine(x + 2, y + 15, x + 6, y + 15); + g.drawLine(x + 2, y + 10, x + 2, y + 15); + + // file 3 outline + g.drawLine(x + 10, y + 2, x + 13, y + 2); + g.drawLine(x + 14, y + 3, x + 14, y + 7); + g.drawLine(x + 10, y + 7, x + 14, y + 7); + g.drawLine(x + 10, y + 2, x + 10, y + 7); + + // file 4 outline + g.drawLine(x + 10, y + 10, x + 13, y + 10); + g.drawLine(x + 14, y + 11, x + 14, y + 15); + g.drawLine(x + 10, y + 15, x + 14, y + 15); + g.drawLine(x + 10, y + 10, x + 10, y + 15); + + g.drawLine(x + 8, y + 5, x + 8, y + 5); + g.drawLine(x + 8, y + 13, x + 8, y + 13); + g.drawLine(x + 16, y + 5, x + 16, y + 5); + g.drawLine(x + 16, y + 13, x + 16, y + 13); + + // fill files + g.setColor(MetalLookAndFeel.getPrimaryControl()); + g.fillRect(x + 3, y + 3, 3, 4); + g.fillRect(x + 3, y + 11, 3, 4); + g.fillRect(x + 11, y + 3, 3, 4); + g.fillRect(x + 11, y + 11, 3, 4); + + // highlight files + g.setColor(MetalLookAndFeel.getPrimaryControlHighlight()); + g.drawLine(x + 4, y + 4, x + 4, y + 5); + g.drawLine(x + 4, y + 12, x + 4, y + 13); + g.drawLine(x + 12, y + 4, x + 12, y + 5); + g.drawLine(x + 12, y + 12, x + 12, y + 13); + + g.setColor(savedColor); + } + } + + /** + * An icon used for the "new folder" button on a {@link JFileChooser} under + * the {@link MetalLookAndFeel}. + * + * @see MetalIconFactory#getFileChooserNewFolderIcon() + */ + private static class FileChooserNewFolderIcon implements Icon, Serializable + { + /** + * Creates a new icon. + */ + public FileChooserNewFolderIcon() + { + // Nothing to do here. + } + + /** + * 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 using colors from the {@link MetalLookAndFeel}. + * + * @param c the component (ignored). + * @param g the graphics device. + * @param x the x-coordinate for the top-left of the icon. + * @param y the y-coordinate for the top-left of the icon. + */ + public void paintIcon(Component c, Graphics g, int x, int y) + { + Color savedColor = g.getColor(); + g.setColor(MetalLookAndFeel.getBlack()); + + g.drawLine(x + 2, y + 5, x + 9, y + 5); + g.drawLine(x + 10, y + 6, x + 15, y + 6); + g.drawLine(x + 15, y + 5, x + 15, y + 14); + g.drawLine(x + 2, y + 14, x + 15, y + 14); + g.drawLine(x + 1, y + 6, x + 1, y + 14); + + g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow()); + g.drawLine(x + 11, y + 3, x + 15, y + 3); + g.drawLine(x + 10, y + 4, x + 15, y + 4); + + g.setColor(MetalLookAndFeel.getPrimaryControl()); + g.fillRect(x + 3, y + 7, 7, 7); + g.fillRect(x + 10, y + 8, 5, 6); + g.drawLine(x + 10, y + 5, x + 14, y + 5); + + g.setColor(MetalLookAndFeel.getPrimaryControlHighlight()); + g.drawLine(x + 10, y + 7, x + 14, y + 7); + g.drawLine(x + 2, y + 6, x + 9, y + 6); + g.drawLine(x + 2, y + 6, x + 2, y + 13); + g.setColor(savedColor); + } + } + + /** + * An icon used for the "up folder" button on a {@link JFileChooser} under + * the {@link MetalLookAndFeel}. + * + * @see MetalIconFactory#getFileChooserNewFolderIcon() + */ + private static class FileChooserUpFolderIcon extends FileChooserNewFolderIcon + implements Icon, Serializable + { + /** + * Creates a new icon. + */ + public FileChooserUpFolderIcon() + { + // Nothing to do here. + } + + /** + * Paints the icon using colors from the {@link MetalLookAndFeel}. + * + * @param c the component (ignored). + * @param g the graphics device. + * @param x the x-coordinate for the top-left of the icon. + * @param y the y-coordinate for the top-left of the icon. + */ + public void paintIcon(Component c, Graphics g, int x, int y) + { + Color savedColor = g.getColor(); + + // draw the folder + super.paintIcon(c, g, x, y); + + // now draw the up arrow + g.setColor(MetalLookAndFeel.getBlack()); + g.drawLine(x + 8, y + 9, x + 8, y + 16); + int xx = x + 8; + for (int i = 0; i < 4; i++) + g.drawLine(xx - i, y + 9 + i, xx + i, y + 9 + i); + g.setColor(savedColor); + } + } + + /** * An icon representing a file (drawn as a piece of paper with the top-right * corner turned down). */ @@ -153,13 +535,15 @@ public class MetalIconFactory implements Serializable } /** - * Returns the height of the icon, in pixels. + * Returns the height of the icon, in pixels. The height returned is + * <code>16</code> plus the value returned by + * {@link #getAdditionalHeight()}. * * @return The height of the icon. */ public int getIconHeight() { - return 16; + return 16 + getAdditionalHeight(); } /** @@ -192,9 +576,11 @@ public class MetalIconFactory implements Serializable } /** - * Returns the additional height (???). + * Returns the additional height for the icon. The + * {@link #getIconHeight()} method adds this value to the icon height it + * returns. Subclasses can override this method to adjust the icon height. * - * @return The additional height. + * @return The additional height (<code>0</code> unless overridden). */ public int getAdditionalHeight() { @@ -228,13 +614,15 @@ public class MetalIconFactory implements Serializable } /** - * Returns the height of the icon, in pixels. + * Returns the height of the icon, in pixels. The height returned is + * <code>16</code> plus the value returned by + * {@link #getAdditionalHeight()}. * * @return The height of the icon. */ public int getIconHeight() { - return 16; + return 16 + getAdditionalHeight(); } /** @@ -265,9 +653,11 @@ public class MetalIconFactory implements Serializable } /** - * Returns the additional height (???). + * Returns the additional height for the icon. The + * {@link #getIconHeight()} method adds this value to the icon height it + * returns. Subclasses can override this method to adjust the icon height. * - * @return The additional height. + * @return The additional height (<code>0</code> unless overridden). */ public int getAdditionalHeight() { @@ -285,29 +675,77 @@ public class MetalIconFactory implements Serializable } } - + /** - * An {@link Icon} implementation for {@link JCheckBox}es in the - * Metal Look & Feel. - * - * @author Roman Kennke (roman@kennke.org) + * An icon used by the {@link MetalInternalFrameUI} class when the frame + * is displayed as a palette. + * + * @since 1.3 */ - static class RadioButtonIcon - implements Icon, UIResource, Serializable + public static class PaletteCloseIcon + implements Icon, Serializable, UIResource { /** - * Draws the check in the RadioButton. - * - * @param c the component to draw on - * @param g the Graphics context to draw with + * Returns the width of the icon, in pixels. + * + * @return The width of the icon. */ - protected void drawCheck(Component c, Graphics g) + public int getIconWidth() { - g.setColor(MetalLookAndFeel.getBlack()); - g.fillRect(4, 3, 4, 6); - g.drawLine(3, 4, 3, 7); - g.drawLine(8, 4, 8, 7); + return 7; } + + /** + * Returns the height of the icon, in pixels. + * + * @return The height of the icon. + */ + public int getIconHeight() + { + return 7; + } + + /** + * Paints the icon using colors from the {@link MetalLookAndFeel}. + * + * @param c the component (ignored). + * @param g the graphics device. + * @param x the x-coordinate for the top-left of the icon. + * @param y the y-coordinate for the top-left of the icon. + */ + public void paintIcon(Component c, Graphics g, int x, int y) + { + Color savedColor = g.getColor(); + AbstractButton button = (AbstractButton) c; + if (button.getModel().isPressed()) + g.setColor(MetalLookAndFeel.getBlack()); + else + g.setColor(MetalLookAndFeel.getControlDarkShadow()); + g.fillRect(x + 2, y + 2, 3, 3); + g.drawLine(x + 1, y, x + 1, y + 2); + g.drawLine(x, y + 1, x + 2, y + 1); + g.drawLine(x + 5, y, x + 5, y + 2); + g.drawLine(x + 4, y + 1, x + 6, y + 1); + g.drawLine(x + 1, y + 4, x + 1, y + 6); + g.drawLine(x, y + 5, x + 2, y + 5); + g.drawLine(x + 5, y + 4, x + 5, y + 6); + g.drawLine(x + 4, y + 5, x + 6, y + 5); + g.setColor(MetalLookAndFeel.getControlHighlight()); + g.drawLine(x + 2, y + 6, x + 3, y + 5); + g.drawLine(x + 5, y + 3, x + 6, y + 2); + g.drawLine(x + 6, y + 6, x + 6, y + 6); + g.setColor(savedColor); + } + } + + /** + * An {@link Icon} implementation for {@link JCheckBox}es in the + * Metal Look & Feel. + * + * @author Roman Kennke (roman@kennke.org) + */ + static class RadioButtonIcon implements Icon, UIResource, Serializable + { /** * Returns the width of the icon in pixels. @@ -330,70 +768,104 @@ public class MetalIconFactory implements Serializable } /** - * Paints the icon. This first paints the border of the RadioButton and - * if the CheckBox is selected it calls {@link #drawCheck} to draw - * the check. + * Paints the icon, taking into account whether or not the component is + * enabled, selected and/or armed. * - * @param c the Component to draw on (gets casted to JCheckBox) + * @param c the Component to draw on (must be an instance of + * {@link JRadioButton}) * @param g the Graphics context to draw with * @param x the X position * @param y the Y position */ - public void paintIcon(Component c, Graphics g, int x, int y) - { - Color dark = MetalLookAndFeel.getControlDarkShadow(); - Color light = MetalLookAndFeel.getWhite(); - g.translate(x, y); - - // The light 'circle' - g.setColor(light); - g.drawLine(4, 1, 10, 1); - g.drawLine(2, 2, 3, 2); - g.drawLine(8, 2, 11, 2); - g.drawLine(2, 3, 2, 3); - g.drawLine(11, 2, 11, 9); - g.drawLine(1, 4, 1, 7); - g.drawLine(12, 4, 12, 7); - g.drawLine(2, 8, 2, 11); - g.drawLine(11, 8, 11, 9); - g.drawLine(10, 10, 10, 10); - g.drawLine(2, 11, 9, 11); - g.drawLine(4, 12, 7, 12); - - // The dark 'circle' - g.setColor(dark); - g.drawLine(4, 0, 7, 0); - g.drawLine(2, 1, 3, 1); - g.drawLine(8, 1, 9, 1); - g.drawLine(1, 2, 1, 3); - g.drawLine(10, 2, 10, 3); - g.drawLine(0, 4, 0, 7); - g.drawLine(11, 4, 11, 7); - g.drawLine(1, 8, 1, 9); - g.drawLine(10, 8, 10, 9); - g.drawLine(2, 10, 3, 10); - g.drawLine(8, 10, 9, 10); - g.drawLine(4, 11, 7, 11); - - JRadioButton rb = (JRadioButton) c; - if (rb.isSelected()) - drawCheck(c, g); - - g.translate(-x, -y); - } + public void paintIcon(Component c, Graphics g, int x, int y) + { + Color savedColor = g.getColor(); + JRadioButton b = (JRadioButton) c; + + // draw outer circle + if (b.isEnabled()) + g.setColor(MetalLookAndFeel.getControlDarkShadow()); + else + g.setColor(MetalLookAndFeel.getControlDisabled()); + g.drawLine(x + 2, y + 1, x + 3, y + 1); + g.drawLine(x + 4, y, x + 7, y); + g.drawLine(x + 8, y + 1, x + 9, y + 1); + g.drawLine(x + 10, y + 2, x + 10, y + 3); + g.drawLine(x + 11, y + 4, x + 11, y + 7); + g.drawLine(x + 10, y + 8, x + 10, y + 9); + g.drawLine(x + 8, y + 10, x + 9, y + 10); + g.drawLine(x + 4, y + 11, x + 7, y + 11); + g.drawLine(x + 2, y + 10, x + 3, y + 10); + g.drawLine(x + 1, y + 9, x + 1, y + 8); + g.drawLine(x, y + 7, x, y + 4); + g.drawLine(x + 1, y + 2, x + 1, y + 3); + + if (b.getModel().isArmed()) + { + g.setColor(MetalLookAndFeel.getControlShadow()); + g.drawLine(x + 4, y + 1, x + 7, y + 1); + g.drawLine(x + 4, y + 10, x + 7, y + 10); + g.drawLine(x + 1, y + 4, x + 1, y + 7); + g.drawLine(x + 10, y + 4, x + 10, y + 7); + g.fillRect(x + 2, y + 2, 8, 8); + } + else + { + // only draw inner highlight if not filled + if (b.isEnabled()) + { + g.setColor(MetalLookAndFeel.getWhite()); + + g.drawLine(x + 2, y + 8, x + 2, y + 9); + g.drawLine(x + 1, y + 4, x + 1, y + 7); + g.drawLine(x + 2, y + 2, x + 2, y + 3); + g.drawLine(x + 3, y + 2, x + 3, y + 2); + g.drawLine(x + 4, y + 1, x + 7, y + 1); + g.drawLine(x + 8, y + 2, x + 9, y + 2); + } + } + + // draw outer highlight + if (b.isEnabled()) + { + g.setColor(MetalLookAndFeel.getWhite()); + + // outer + g.drawLine(x + 10, y + 1, x + 10, y + 1); + g.drawLine(x + 11, y + 2, x + 11, y + 3); + g.drawLine(x + 12, y + 4, x + 12, y + 7); + g.drawLine(x + 11, y + 8, x + 11, y + 9); + g.drawLine(x + 10, y + 10, x + 10, y + 10); + g.drawLine(x + 8, y + 11, x + 9, y + 11); + g.drawLine(x + 4, y + 12, x + 7, y + 12); + g.drawLine(x + 2, y + 11, x + 3, y + 11); + } + + if (b.isSelected()) + { + if (b.isEnabled()) + g.setColor(MetalLookAndFeel.getBlack()); + else + g.setColor(MetalLookAndFeel.getControlDisabled()); + g.drawLine(x + 4, y + 3, x + 7, y + 3); + g.fillRect(x + 3, y + 4, 6, 4); + g.drawLine(x + 4, y + 8, x + 7, y + 8); + } + g.setColor(savedColor); + } } /** * An icon displayed for {@link JRadioButtonMenuItem} components. */ - private static class RadioButtonMenuItemIcon - implements Icon, Serializable + private static class RadioButtonMenuItemIcon implements Icon, Serializable { /** * Creates a new icon instance. */ public RadioButtonMenuItemIcon() - { + { + // Nothing to do here. } /** @@ -463,8 +935,7 @@ public class MetalIconFactory implements Serializable * The icon used to display the thumb control on a horizontally oriented * {@link JSlider} component. */ - private static class HorizontalSliderThumbIcon - implements Icon, Serializable + private static class HorizontalSliderThumbIcon implements Icon, Serializable { /** @@ -472,6 +943,7 @@ public class MetalIconFactory implements Serializable */ public HorizontalSliderThumbIcon() { + // Nothing to do here. } /** @@ -505,13 +977,19 @@ public class MetalIconFactory implements Serializable */ public void paintIcon(Component c, Graphics g, int x, int y) { + boolean enabled = false; boolean focus = false; - if (c != null) - focus = c.hasFocus(); - // TODO: pick up the colors from the look and feel + if (c != null) + { + enabled = c.isEnabled(); + focus = c.hasFocus(); + } // draw the outline - g.setColor(Color.black); + if (enabled) + g.setColor(MetalLookAndFeel.getBlack()); + else + g.setColor(MetalLookAndFeel.getControlDarkShadow()); 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); @@ -519,8 +997,11 @@ public class MetalIconFactory implements Serializable 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); + if (focus) + g.setColor(MetalLookAndFeel.getPrimaryControlShadow()); + else + g.setColor(MetalLookAndFeel.getControl()); + g.fillRect(x + 1, y + 2, 13, 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); @@ -528,33 +1009,42 @@ public class MetalIconFactory implements Serializable 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); + // if the slider is enabled, draw dots and highlights + if (c.isEnabled()) + { + if (focus) + g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow()); + else + g.setColor(MetalLookAndFeel.getBlack()); + 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 + 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); + g.drawLine(x + 5, y + 5, x + 5, y + 5); + g.drawLine(x + 9, y + 5, x + 9, y + 5); - // 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 + 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); - g.drawLine(x + 5, y + 5, x + 5, y + 5); - g.drawLine(x + 9, y + 5, x + 9, y + 5); + // draw highlights + if (focus) + g.setColor(MetalLookAndFeel.getPrimaryControl()); + else + g.setColor(MetalLookAndFeel.getWhite()); + 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 + 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); + 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); + } } } @@ -563,7 +1053,7 @@ public class MetalIconFactory implements Serializable * An icon used for the 'close' button in the title frame of a * {@link JInternalFrame}. */ - private static class InternalFrameCloseIcon implements Icon, Serializable + private static class InternalFrameCloseIcon implements Icon, Serializable { /** The icon size in pixels. */ private int size; @@ -601,25 +1091,53 @@ public class MetalIconFactory implements Serializable /** * Paints the icon. * - * @param c the component. + * @param c the component (an {@link JInternalFrame} is expected). * @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) { - // draw the gray areas first - g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow()); + Color savedColor = g.getColor(); + AbstractButton b = (AbstractButton) c; + + // fill the interior + if (b.getModel().isPressed()) + // FIXME: also need to take into account whether the internal frame is + // selected + g.setColor(MetalLookAndFeel.getPrimaryControlShadow()); + else + g.setColor(MetalLookAndFeel.getPrimaryControl()); + g.fillRect(x + 2, y + 2, 10, 10); + + // draw the outline box and the cross + if (b.getModel().isPressed()) + g.setColor(MetalLookAndFeel.getBlack()); + else + { + // FIXME: also need to take into account whether the internal frame is + // selected + boolean selected = true; + if (selected) + g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow()); + else + g.setColor(MetalLookAndFeel.getControlDarkShadow()); + } g.drawLine(x + 1, y + 1, x + 13, y + 1); g.drawLine(x + 1, y + 2, x + 1, y + 12); g.drawLine(x + 1, y + 13, x + 13, y + 13); g.drawLine(x + 13, y + 2, x + 13, y + 12); + g.drawLine(x + 2, y + 12, x + 2, y + 12); + g.drawLine(x + 12, y + 2, x + 12, y + 2); g.fillRect(x + 4, y + 4, 2, 2); - g.fillRect(x + 4, y + 9, 2, 2); - g.fillRect(x + 9, y + 4, 2, 2); - g.fillRect(x + 9, y + 9, 2, 2); - g.fillRect(x + 5, y + 5, 5, 5); + g.fillRect(x + 5, y + 5, 4, 4); + g.drawLine(x + 9, y + 4, x + 10, y + 4); + g.drawLine(x + 9, y + 4, x + 9, y + 5); + g.drawLine(x + 4, y + 9, x + 4, y + 10); + g.drawLine(x + 4, y + 9, x + 5, y + 9); + g.drawLine(x + 9, y + 8, x + 9, y + 10); + g.drawLine(x + 8, y + 9, x + 10, y + 9); g.setColor(MetalLookAndFeel.getBlack()); g.drawLine(x, y, x + 13, y); @@ -635,20 +1153,24 @@ public class MetalIconFactory implements Serializable g.drawLine(x + 1, y + 14, x + 14, y + 14); g.drawLine(x + 14, y + 1, x + 14, y + 14); - g.drawLine(x + 5, y + 10, x + 5, y + 10); - g.drawLine(x + 6, y + 9, x + 7, y + 9); - g.drawLine(x + 10, y + 5, x + 10, y + 5); - g.drawLine(x + 9, y + 6, x + 9, y + 7); - g.drawLine(x + 10, y + 10, x + 11, y + 10); - g.drawLine(x + 10, y + 11, x + 10, y + 11); + if (!b.getModel().isPressed()) + { + g.drawLine(x + 5, y + 10, x + 5, y + 10); + g.drawLine(x + 6, y + 9, x + 7, y + 9); + g.drawLine(x + 10, y + 5, x + 10, y + 5); + g.drawLine(x + 9, y + 6, x + 9, y + 7); + g.drawLine(x + 10, y + 10, x + 11, y + 10); + g.drawLine(x + 10, y + 11, x + 10, y + 11); + } + g.setColor(savedColor); } } /** * The icon displayed at the top-left corner of a {@link JInternalFrame}. */ - private static class InternalFrameDefaultMenuIcon - implements Icon, Serializable + private static class InternalFrameDefaultMenuIcon + implements Icon, Serializable { /** @@ -656,6 +1178,7 @@ public class MetalIconFactory implements Serializable */ public InternalFrameDefaultMenuIcon() { + // Nothing to do here. } /** @@ -718,8 +1241,8 @@ public class MetalIconFactory implements Serializable * maximise an internal frame, this icon will replace the 'maximise' icon to * provide a 'restore' option. */ - private static class InternalFrameAltMaximizeIcon - implements Icon, Serializable + private static class InternalFrameAltMaximizeIcon + implements Icon, Serializable { /** The icon size in pixels. */ private int size; @@ -764,14 +1287,23 @@ public class MetalIconFactory implements Serializable */ public void paintIcon(Component c, Graphics g, int x, int y) { - Color color = MetalLookAndFeel.getControlDarkShadow(); - if (c instanceof JInternalFrame) - { - JInternalFrame f = (JInternalFrame) c; - if (f.isSelected()) - color = MetalLookAndFeel.getPrimaryControlShadow(); - } - g.setColor(color); + Color savedColor = g.getColor(); + + AbstractButton b = (AbstractButton) c; + + // fill the small box interior + if (b.getModel().isPressed()) + g.setColor(MetalLookAndFeel.getPrimaryControlShadow()); + else + g.setColor(MetalLookAndFeel.getPrimaryControl()); + g.fillRect(x + 2, y + 6, 7, 7); + + + if (b.getModel().isPressed()) + g.setColor(MetalLookAndFeel.getBlack()); + else + g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow()); + g.drawLine(x + 12, y + 1, x + 13, y + 1); g.drawLine(x + 11, y + 2, x + 12, y + 2); g.drawLine(x + 10, y + 3, x + 11, y + 3); @@ -803,10 +1335,16 @@ public class MetalIconFactory implements Serializable g.drawLine(x + 13, y + 6, x + 13, y + 6); g.drawLine(x + 8, y + 7, x + 13, y + 7); g.drawLine(x + 6, y + 5, x + 6, y + 5); - g.drawLine(x + 2, y + 6, x + 6, y + 6); - g.drawLine(x + 2, y + 6, x + 2, y + 11); g.drawLine(x + 10, y + 8, x + 10, y + 13); g.drawLine(x + 1, y + 14, x + 10, y + 14); + + if (!b.getModel().isPressed()) + { + g.drawLine(x + 2, y + 6, x + 6, y + 6); + g.drawLine(x + 2, y + 6, x + 2, y + 11); + } + + g.setColor(savedColor); } } @@ -814,8 +1352,7 @@ public class MetalIconFactory implements Serializable * An icon used for the 'maximize' button in the title frame of a * {@link JInternalFrame}. */ - private static class InternalFrameMaximizeIcon - implements Icon, Serializable + private static class InternalFrameMaximizeIcon implements Icon, Serializable { /** @@ -823,6 +1360,7 @@ public class MetalIconFactory implements Serializable */ public InternalFrameMaximizeIcon() { + // Nothing to do here. } /** @@ -855,14 +1393,22 @@ public class MetalIconFactory implements Serializable */ public void paintIcon(Component c, Graphics g, int x, int y) { - Color color = MetalLookAndFeel.getControlDarkShadow(); - if (c instanceof JInternalFrame) - { - JInternalFrame f = (JInternalFrame) c; - if (f.isSelected()) - color = MetalLookAndFeel.getPrimaryControlShadow(); - } - g.setColor(color); + Color savedColor = g.getColor(); + + AbstractButton b = (AbstractButton) c; + + // fill the interior + if (b.getModel().isPressed()) + g.setColor(MetalLookAndFeel.getPrimaryControlShadow()); + else + g.setColor(MetalLookAndFeel.getPrimaryControl()); + g.fillRect(x + 2, y + 6, 7, 7); + + if (b.getModel().isPressed()) + g.setColor(MetalLookAndFeel.getBlack()); + else + g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow()); + g.drawLine(x + 9, y + 1, x + 10, y + 1); g.fillRect(x + 11, y + 1, 3, 3); g.fillRect(x + 12, y + 4, 2, 2); @@ -897,9 +1443,12 @@ public class MetalIconFactory implements Serializable // draw white g.setColor(MetalLookAndFeel.getWhite()); - g.drawLine(x + 2, y + 6, x + 5, y + 6); - g.drawLine(x + 2, y + 7, x + 2, y + 9); - g.drawLine(x + 4, y + 11, x + 7, y + 8); + if (!b.getModel().isPressed()) + { + g.drawLine(x + 2, y + 6, x + 5, y + 6); + g.drawLine(x + 2, y + 7, x + 2, y + 9); + g.drawLine(x + 4, y + 11, x + 7, y + 8); + } g.drawLine(x + 1, y + 14, x + 10, y + 14); g.drawLine(x + 10, y + 5, x + 10, y + 13); @@ -908,14 +1457,14 @@ public class MetalIconFactory implements Serializable g.drawLine(x + 11, y + 4, x + 11, y + 5); g.drawLine(x + 13, y + 6, x + 14, y + 6); g.drawLine(x + 14, y + 1, x + 14, y + 5); + g.setColor(savedColor); } } /** * An icon used in the title frame of a {@link JInternalFrame}. */ - private static class InternalFrameMinimizeIcon - implements Icon, Serializable + private static class InternalFrameMinimizeIcon implements Icon, Serializable { /** @@ -923,6 +1472,7 @@ public class MetalIconFactory implements Serializable */ public InternalFrameMinimizeIcon() { + // Nothing to do here. } /** @@ -955,14 +1505,17 @@ public class MetalIconFactory implements Serializable */ public void paintIcon(Component c, Graphics g, int x, int y) { - Color color = MetalLookAndFeel.getControlDarkShadow(); - if (c instanceof JInternalFrame) - { - JInternalFrame f = (JInternalFrame) c; - if (f.isSelected()) - color = MetalLookAndFeel.getPrimaryControlShadow(); - } - g.setColor(color); + Color savedColor = g.getColor(); + + AbstractButton b = (AbstractButton) c; + + if (b.getModel().isPressed()) + g.setColor(MetalLookAndFeel.getBlack()); + else + // FIXME: here the color depends on whether or not the internal frame + // is selected + g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow()); + g.drawLine(x + 12, y + 1, x + 13, y + 1); g.drawLine(x + 11, y + 2, x + 12, y + 2); g.drawLine(x + 10, y + 3, x + 11, y + 3); @@ -993,10 +1546,21 @@ public class MetalIconFactory implements Serializable g.drawLine(x + 11, y + 4, x + 13, y + 2); g.drawLine(x + 13, y + 6, x + 13, y + 6); g.drawLine(x + 8, y + 7, x + 13, y + 7); - g.drawLine(x + 2, y + 9, x + 4, y + 9); - g.drawLine(x + 2, y + 10, x + 2, y + 11); g.drawLine(x + 7, y + 9, x + 7, y + 13); g.drawLine(x + 1, y + 14, x + 7, y + 14); + + if (b.getModel().isPressed()) + { + g.setColor(MetalLookAndFeel.getPrimaryControlShadow()); + g.fillRect(x + 2, y + 9, 3, 3); + } + else + { + g.drawLine(x + 2, y + 9, x + 4, y + 9); + g.drawLine(x + 2, y + 10, x + 2, y + 11); + } + + g.setColor(savedColor); } } @@ -1004,13 +1568,14 @@ public class MetalIconFactory implements Serializable * The icon used to display the thumb control on a horizontally oriented * {@link JSlider} component. */ - private static class VerticalSliderThumbIcon implements Icon, Serializable + private static class VerticalSliderThumbIcon implements Icon, Serializable { /** * Creates a new instance. */ public VerticalSliderThumbIcon() { + // Nothing to do here. } /** @@ -1045,13 +1610,19 @@ public class MetalIconFactory implements Serializable */ public void paintIcon(Component c, Graphics g, int x, int y) { + boolean enabled = false; boolean focus = false; - if (c != null) - focus = c.hasFocus(); - // TODO: pick up the colors from the look and feel + if (c != null) + { + enabled = c.isEnabled(); + focus = c.hasFocus(); + } // draw the outline - g.setColor(Color.black); + if (enabled) + g.setColor(MetalLookAndFeel.getBlack()); + else + g.setColor(MetalLookAndFeel.getControlDarkShadow()); 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); @@ -1059,8 +1630,11 @@ public class MetalIconFactory implements Serializable 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); + if (focus) + g.setColor(MetalLookAndFeel.getPrimaryControlShadow()); + else + g.setColor(MetalLookAndFeel.getControl()); + g.fillRect(x + 2, y + 1, 7, 13); 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); @@ -1068,41 +1642,51 @@ public class MetalIconFactory implements Serializable 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); + // if the slider is enabled, draw dots and highlights + if (enabled) + { + if (focus) + g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow()); + else + g.setColor(MetalLookAndFeel.getBlack()); + 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 + 4, y + 4, x + 4, y + 4); - g.drawLine(x + 4, y + 8, x + 4, y + 8); + g.drawLine(x + 5, y + 5, x + 5, y + 5); + g.drawLine(x + 5, y + 9, x + 5, y + 9); - 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); + 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); - // 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); + // draw highlights + if (focus) + g.setColor(MetalLookAndFeel.getPrimaryControl()); + else + g.setColor(MetalLookAndFeel.getWhite()); + 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 + 5, y + 5, x + 5, y + 5); - g.drawLine(x + 5, y + 9, x + 5, y + 9); + g.drawLine(x + 4, y + 4, x + 4, y + 4); + g.drawLine(x + 4, y + 8, x + 4, y + 8); - 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); + 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); + + } } } - + /** * A tree control icon. This icon can be in one of two states: expanded and * collapsed. */ - public static class TreeControlIcon implements Icon, Serializable + public static class TreeControlIcon implements Icon, Serializable { /** ???. */ @@ -1235,19 +1819,21 @@ public class MetalIconFactory implements Serializable /** * A tree folder icon. */ - public static class TreeFolderIcon extends FolderIcon16 + public static class TreeFolderIcon extends FolderIcon16 { /** * Creates a new instance. */ public TreeFolderIcon() - { + { + // Nothing to do here. } /** - * Returns the additional height (???). + * Returns the additional height for this icon, in this case <code>2</code> + * pixels. * - * @return The additional height. + * @return <code>2</code>. */ public int getAdditionalHeight() { @@ -1268,19 +1854,21 @@ public class MetalIconFactory implements Serializable /** * A tree leaf icon. */ - public static class TreeLeafIcon extends FileIcon16 + public static class TreeLeafIcon extends FileIcon16 { /** * Creates a new instance. */ public TreeLeafIcon() { + // Nothing to do here. } /** - * Returns the additional height (???). + * Returns the additional height for this icon, in this case <code>4</code> + * pixels. * - * @return The additional height. + * @return <code>4</code>. */ public int getAdditionalHeight() { @@ -1297,16 +1885,310 @@ public class MetalIconFactory implements Serializable return 2; } } + + /** + * An icon representing a hard disk. + * + * @see MetalIconFactory#getTreeHardDriveIcon() + */ + private static class TreeHardDriveIcon implements Icon, Serializable + { + + /** + * Creates a new icon instance. + */ + public TreeHardDriveIcon() + { + // Nothing to do here. + } + + /** + * Returns the width of the icon, in pixels. + * + * @return <code>16</code>. + */ + public int getIconWidth() + { + return 16; + } + + /** + * Returns the height of the icon, in pixels. + * + * @return <code>16</code>. + */ + public int getIconHeight() + { + return 16; + } + + /** + * Paints the icon at the specified location, using colors from the + * current theme. + * + * @param c the component (ignored). + * @param g the graphics device. + * @param x the x-coordinate for the top-left of the icon. + * @param y the y-coordinate for the top-left of the icon. + */ + public void paintIcon(Component c, Graphics g, int x, int y) + { + Color saved = g.getColor(); + g.setColor(MetalLookAndFeel.getBlack()); + g.drawLine(x + 1, y + 4, x + 1, y + 5); + g.drawLine(x + 14, y + 4, x + 14, y + 5); + g.drawLine(x + 1, y + 7, x + 1, y + 8); + g.drawLine(x + 14, y + 7, x + 14, y + 8); + g.drawLine(x + 1, y + 10, x + 1, y + 11); + g.drawLine(x + 14, y + 10, x + 14, y + 11); + + g.drawLine(x + 2, y + 3, x + 3, y + 3); + g.drawLine(x + 12, y + 3, x + 13, y + 3); + g.drawLine(x + 2, y + 6, x + 3, y + 6); + g.drawLine(x + 12, y + 6, x + 13, y + 6); + g.drawLine(x + 2, y + 9, x + 3, y + 9); + g.drawLine(x + 12, y + 9, x + 13, y + 9); + g.drawLine(x + 2, y + 12, x + 3, y + 12); + g.drawLine(x + 12, y + 12, x + 13, y + 12); + + g.drawLine(x + 4, y + 2, x + 11, y + 2); + g.drawLine(x + 4, y + 7, x + 11, y + 7); + g.drawLine(x + 4, y + 10, x + 11, y + 10); + g.drawLine(x + 4, y + 13, x + 11, y + 13); + + g.setColor(MetalLookAndFeel.getWhite()); + g.fillRect(x + 4, y + 3, 2, 2); + g.drawLine(x + 6, y + 4, x + 6, y + 4); + g.drawLine(x + 7, y + 3, x + 9, y + 3); + g.drawLine(x + 8, y + 4, x + 8, y + 4); + g.drawLine(x + 11, y + 3, x + 11, y + 3); + g.fillRect(x + 2, y + 4, 2, 2); + g.fillRect(x + 2, y + 7, 2, 2); + g.fillRect(x + 2, y + 10, 2, 2); + g.drawLine(x + 4, y + 6, x + 4, y + 6); + g.drawLine(x + 4, y + 9, x + 4, y + 9); + g.drawLine(x + 4, y + 12, x + 4, y + 12); + + g.setColor(MetalLookAndFeel.getControlShadow()); + g.drawLine(x + 13, y + 4, x + 13, y + 4); + g.drawLine(x + 12, y + 5, x + 13, y + 5); + g.drawLine(x + 13, y + 7, x + 13, y + 7); + g.drawLine(x + 12, y + 8, x + 13, y + 8); + g.drawLine(x + 13, y + 10, x + 13, y + 10); + g.drawLine(x + 12, y + 11, x + 13, y + 11); + + g.drawLine(x + 10, y + 5, x + 10, y + 5); + g.drawLine(x + 7, y + 6, x + 7, y + 6); + g.drawLine(x + 9, y + 6, x + 9, y + 6); + g.drawLine(x + 11, y + 6, x + 11, y + 6); + + g.drawLine(x + 10, y + 8, x + 10, y + 8); + g.drawLine(x + 7, y + 9, x + 7, y + 9); + g.drawLine(x + 9, y + 9, x + 9, y + 9); + g.drawLine(x + 11, y + 9, x + 11, y + 9); + + g.drawLine(x + 10, y + 11, x + 10, y + 11); + g.drawLine(x + 7, y + 12, x + 7, y + 12); + g.drawLine(x + 9, y + 12, x + 9, y + 12); + g.drawLine(x + 11, y + 12, x + 11, y + 12); + + g.setColor(saved); + } + } + + /** + * An icon representing a floppy disk. + * + * @see MetalIconFactory#getTreeFloppyDriveIcon() + */ + private static class TreeFloppyDriveIcon implements Icon, Serializable + { + + /** + * Creates a new icon instance. + */ + public TreeFloppyDriveIcon() + { + // Nothing to do here. + } + + /** + * Returns the width of the icon, in pixels. + * + * @return <code>16</code>. + */ + public int getIconWidth() + { + return 16; + } + + /** + * Returns the height of the icon, in pixels. + * + * @return <code>16</code>. + */ + public int getIconHeight() + { + return 16; + } + + /** + * Paints the icon at the specified location, using colors from the + * current theme. + * + * @param c the component (ignored). + * @param g the graphics device. + * @param x the x-coordinate for the top-left of the icon. + * @param y the y-coordinate for the top-left of the icon. + */ + public void paintIcon(Component c, Graphics g, int x, int y) + { + Color saved = g.getColor(); + + g.setColor(MetalLookAndFeel.getBlack()); + g.drawLine(x + 1, y + 1, x + 13, y + 1); + g.drawLine(x + 1, y + 1, x + 1, y + 14); + g.drawLine(x + 1, y + 14, x + 14, y + 14); + g.drawLine(x + 14, y + 2, x + 14, y + 14); + + g.setColor(MetalLookAndFeel.getPrimaryControl()); + g.fillRect(x + 2, y + 2, 12, 12); + + g.setColor(MetalLookAndFeel.getControlShadow()); + g.fillRect(x + 5, y + 2, 6, 5); + g.drawLine(x + 4, y + 8, x + 11, y + 8); + g.drawLine(x + 3, y + 9, x + 3, y + 13); + g.drawLine(x + 12, y + 9, x + 12, y + 13); + + g.setColor(MetalLookAndFeel.getWhite()); + g.fillRect(x + 8, y + 3, 2, 3); + g.fillRect(x + 4, y + 9, 8, 5); + + g.setColor(MetalLookAndFeel.getPrimaryControlShadow()); + g.drawLine(x + 5, y + 10, x + 9, y + 10); + g.drawLine(x + 5, y + 12, x + 8, y + 12); + + g.setColor(saved); + } + } + + /** + * An icon representing a computer. + * + * @see MetalIconFactory#getTreeComputerIcon() + */ + private static class TreeComputerIcon implements Icon, Serializable + { + + /** + * Creates a new icon instance. + */ + public TreeComputerIcon() + { + // Nothing to do here. + } + + /** + * Returns the width of the icon, in pixels. + * + * @return <code>16</code>. + */ + public int getIconWidth() + { + return 16; + } + + /** + * Returns the height of the icon, in pixels. + * + * @return <code>16</code>. + */ + public int getIconHeight() + { + return 16; + } + + /** + * Paints the icon at the specified location, using colors from the + * current theme. + * + * @param c the component (ignored). + * @param g the graphics device. + * @param x the x-coordinate for the top-left of the icon. + * @param y the y-coordinate for the top-left of the icon. + */ + public void paintIcon(Component c, Graphics g, int x, int y) + { + Color saved = g.getColor(); + + g.setColor(MetalLookAndFeel.getBlack()); + g.drawLine(x + 3, y + 1, x + 12, y + 1); + g.drawLine(x + 2, y + 2, x + 2, y + 8); + g.drawLine(x + 13, y + 2, x + 13, y + 8); + g.drawLine(x + 3, y + 9, x + 3, y + 9); + g.drawLine(x + 12, y + 9, x + 12, y + 9); + g.drawRect(x + 1, y + 10, 13, 4); + g.drawLine(x + 5, y + 3, x + 10, y + 3); + g.drawLine(x + 5, y + 8, x + 10, y + 8); + g.drawLine(x + 4, y + 4, x + 4, y + 7); + g.drawLine(x + 11, y + 4, x + 11, y + 7); + + g.setColor(MetalLookAndFeel.getPrimaryControl()); + g.fillRect(x + 5, y + 4, 6, 4); + + g.setColor(MetalLookAndFeel.getControlShadow()); + g.drawLine(x + 6, y + 12, x + 8, y + 12); + g.drawLine(x + 10, y + 12, x + 12, y + 12); + g.setColor(saved); + } + } + /** The icon returned by {@link #getCheckBoxIcon()}. */ + private static Icon checkBoxIcon; + + /** The icon returned by {@link #getCheckBoxMenuItemIcon()}. */ + private static Icon checkBoxMenuItemIcon; + + /** The icon returned by {@link #getFileChooserDetailViewIcon()}. */ + private static Icon fileChooserDetailViewIcon; + + /** The icon returned by {@link #getFileChooserHomeFolderIcon()}. */ + private static Icon fileChooserHomeFolderIcon; + + /** The icon returned by {@link #getFileChooserListViewIcon()}. */ + private static Icon fileChooserListViewIcon; + + /** The icon returned by {@link #getFileChooserNewFolderIcon()}. */ + private static Icon fileChooserNewFolderIcon; + + /** The icon returned by {@link #getFileChooserUpFolderIcon()}. */ + private static Icon fileChooserUpFolderIcon; + /** The cached RadioButtonIcon instance. */ private static RadioButtonIcon radioButtonIcon; + /** The icon returned by {@link #getRadioButtonMenuItemIcon()}. */ + private static Icon radioButtonMenuItemIcon; + + /** The icon returned by {@link #getInternalFrameDefaultMenuIcon()}. */ + private static Icon internalFrameDefaultMenuIcon; + + /** The icon returned by {@link #getTreeComputerIcon()}. */ + private static Icon treeComputerIcon; + + /** The icon instance returned by {@link #getTreeFloppyDriveIcon()}. */ + private static Icon treeFloppyDriveIcon; + + /** The icon instance returned by {@link #getTreeHardDriveIcon()}. */ + private static Icon treeHardDriveIcon; + /** * Creates a new instance. All the methods are static, so creating an * instance isn't necessary. */ public MetalIconFactory() - { + { + // Nothing to do here. } /** @@ -1318,7 +2200,9 @@ public class MetalIconFactory implements Serializable */ public static Icon getCheckBoxIcon() { - return new MetalCheckBoxIcon(); + if (checkBoxIcon == null) + checkBoxIcon = new MetalCheckBoxIcon(); + return checkBoxIcon; } /** @@ -1329,7 +2213,69 @@ public class MetalIconFactory implements Serializable */ public static Icon getCheckBoxMenuItemIcon() { - return new CheckBoxMenuItemIcon(); + if (checkBoxMenuItemIcon == null) + checkBoxMenuItemIcon = new CheckBoxMenuItemIcon(); + return checkBoxMenuItemIcon; + } + + /** + * Returns an icon for use by the {@link JFileChooser} component. + * + * @return An icon. + */ + public static Icon getFileChooserDetailViewIcon() + { + if (fileChooserDetailViewIcon == null) + fileChooserDetailViewIcon = new FileChooserDetailViewIcon(); + return fileChooserDetailViewIcon; + } + + /** + * Returns an icon for use by the {@link JFileChooser} component. + * + * @return An icon. + */ + public static Icon getFileChooserHomeFolderIcon() + { + if (fileChooserHomeFolderIcon == null) + fileChooserHomeFolderIcon = new FileChooserHomeFolderIcon(); + return fileChooserHomeFolderIcon; + } + + /** + * Returns an icon for use by the {@link JFileChooser} component. + * + * @return An icon. + */ + public static Icon getFileChooserListViewIcon() + { + if (fileChooserListViewIcon == null) + fileChooserListViewIcon = new FileChooserListViewIcon(); + return fileChooserListViewIcon; + } + + /** + * Returns an icon for use by the {@link JFileChooser} component. + * + * @return An icon. + */ + public static Icon getFileChooserNewFolderIcon() + { + if (fileChooserNewFolderIcon == null) + fileChooserNewFolderIcon = new FileChooserNewFolderIcon(); + return fileChooserNewFolderIcon; + } + + /** + * Returns an icon for use by the {@link JFileChooser} component. + * + * @return An icon. + */ + public static Icon getFileChooserUpFolderIcon() + { + if (fileChooserUpFolderIcon == null) + fileChooserUpFolderIcon = new FileChooserUpFolderIcon(); + return fileChooserUpFolderIcon; } /** @@ -1351,7 +2297,9 @@ public class MetalIconFactory implements Serializable */ public static Icon getRadioButtonMenuItemIcon() { - return new RadioButtonMenuItemIcon(); + if (radioButtonMenuItemIcon == null) + radioButtonMenuItemIcon = new RadioButtonMenuItemIcon(); + return radioButtonMenuItemIcon; } /** @@ -1386,7 +2334,9 @@ public class MetalIconFactory implements Serializable */ public static Icon getInternalFrameDefaultMenuIcon() { - return new InternalFrameDefaultMenuIcon(); + if (internalFrameDefaultMenuIcon == null) + internalFrameDefaultMenuIcon = new InternalFrameDefaultMenuIcon(); + return internalFrameDefaultMenuIcon; } /** @@ -1475,4 +2425,40 @@ public class MetalIconFactory implements Serializable return new TreeControlIcon(isCollapsed); } + /** + * Returns a <code>16x16</code> icon representing a computer. + * + * @return The icon. + */ + public static Icon getTreeComputerIcon() + { + if (treeComputerIcon == null) + treeComputerIcon = new TreeComputerIcon(); + return treeComputerIcon; + } + + /** + * Returns a <code>16x16</code> icon representing a floppy disk. + * + * @return The icon. + */ + public static Icon getTreeFloppyDriveIcon() + { + if (treeFloppyDriveIcon == null) + treeFloppyDriveIcon = new TreeFloppyDriveIcon(); + return treeFloppyDriveIcon; + } + + /** + * Returns a <code>16x16</code> icon representing a hard disk. + * + * @return The icon. + */ + public static Icon getTreeHardDriveIcon() + { + if (treeHardDriveIcon == null) + treeHardDriveIcon = new TreeHardDriveIcon(); + return treeHardDriveIcon; + } + } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameTitlePane.java b/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameTitlePane.java index 20526eb..33eb349 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameTitlePane.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameTitlePane.java @@ -38,30 +38,208 @@ exception statement from your version. */ package javax.swing.plaf.metal; +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.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import javax.swing.Icon; import javax.swing.JInternalFrame; +import javax.swing.JLabel; import javax.swing.JMenu; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.UIDefaults; +import javax.swing.UIManager; import javax.swing.plaf.basic.BasicInternalFrameTitlePane; + /** - * The title pane for a {@link JInternalFrame}. + * The title pane for a {@link JInternalFrame} (see + * {@link MetalInternalFrameUI#createNorthPane(JInternalFrame)}). This can + * be displayed in two styles: one for regular internal frames, and the other + * for "palette" style internal frames. */ public class MetalInternalFrameTitlePane extends BasicInternalFrameTitlePane { + /** + * A property change handler that listens for changes to the + * <code>JInternalFrame.isPalette</code> property and updates the title + * pane as appropriate. + */ + class MetalInternalFrameTitlePanePropertyChangeHandler + extends PropertyChangeHandler + { + /** + * Creates a new handler. + */ + public MetalInternalFrameTitlePanePropertyChangeHandler() + { + super(); + } + + /** + * Handles <code>JInternalFrame.isPalette</code> property changes, with all + * other property changes being passed to the superclass. + * + * @param e the event. + */ + public void propertyChange(PropertyChangeEvent e) + { + String propName = e.getPropertyName(); + if (propName.equals("JInternalFrame.isPalette")) + { + if (e.getNewValue().equals(Boolean.TRUE)) + setPalette(true); + else + setPalette(false); + } + else + super.propertyChange(e); + } + } + + /** + * A layout manager for the title pane. + * + * @see #createLayout() + */ + private class MetalTitlePaneLayout implements LayoutManager + { + /** + * Creates a new <code>TitlePaneLayout</code> object. + */ + public MetalTitlePaneLayout() + { + // Do nothing. + } + + /** + * Adds 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; + + + int loc = width - insets.right - 1; + int top = insets.top + 2; + int buttonHeight = height - 4; + if (closeButton.isVisible()) + { + int buttonWidth = closeIcon.getIconWidth(); + loc -= buttonWidth + 2; + closeButton.setBounds(loc, top, buttonWidth, buttonHeight); + loc -= 6; + } + + if (maxButton.isVisible()) + { + int buttonWidth = maxIcon.getIconWidth(); + loc -= buttonWidth + 4; + maxButton.setBounds(loc, top, buttonWidth, buttonHeight); + } + + if (iconButton.isVisible()) + { + int buttonWidth = minIcon.getIconWidth(); + loc -= buttonWidth + 4; + iconButton.setBounds(loc, top, buttonWidth, buttonHeight); + loc -= 2; + } + + Dimension titlePreferredSize = title.getPreferredSize(); + title.setBounds(insets.left + 5, insets.top, + Math.min(titlePreferredSize.width, loc - insets.left - 10), + 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); + } + + /** + * 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) + { + if (isPalette) + return new Dimension(paletteTitleHeight, paletteTitleHeight); + else + return new Dimension(22, 22); + } + + /** + * Removes a Component from the Container. + * + * @param c The Component to remove. + */ + public void removeLayoutComponent(Component c) + { + // Nothing to do here. + } + } + + /** A flag indicating whether the title pane uses the palette style. */ protected boolean isPalette; - protected Icon paletteCloseIcon = MetalIconFactory.getInternalFrameCloseIcon(16); + /** + * The icon used for the close button - this is fetched from the look and + * feel defaults using the key <code>InternalFrame.paletteCloseIcon</code>. + */ + protected Icon paletteCloseIcon; + + /** + * The height of the title pane when <code>isPalette</code> is + * <code>true</code>. This value is fetched from the look and feel defaults + * using the key <code>InternalFrame.paletteTitleHeight</code>. + */ + protected int paletteTitleHeight; + + /** The label used to display the title for the internal frame. */ + JLabel title; - protected int paletteTitleHeight = 12; - /** - * Creates a new title pane. + * Creates a new title pane for the specified frame. * * @param f the internal frame. */ @@ -81,6 +259,15 @@ public class MetalInternalFrameTitlePane extends BasicInternalFrameTitlePane selectedTitleColor = MetalLookAndFeel.getWindowTitleBackground(); notSelectedTextColor = MetalLookAndFeel.getInactiveControlTextColor(); notSelectedTitleColor = MetalLookAndFeel.getWindowTitleInactiveBackground(); + + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + paletteTitleHeight = defaults.getInt("InternalFrame.paletteTitleHeight"); + paletteCloseIcon = defaults.getIcon("InternalFrame.paletteCloseIcon"); + minIcon = MetalIconFactory.getInternalFrameAltMaximizeIcon(16); + + title = new JLabel(frame.getTitle(), + MetalIconFactory.getInternalFrameDefaultMenuIcon(), + SwingConstants.LEFT); } /** @@ -93,6 +280,9 @@ public class MetalInternalFrameTitlePane extends BasicInternalFrameTitlePane selectedTitleColor = null; notSelectedTextColor = null; notSelectedTitleColor = null; + paletteCloseIcon = null; + minIcon = null; + title = null; } /** @@ -128,44 +318,123 @@ public class MetalInternalFrameTitlePane extends BasicInternalFrameTitlePane } /** - * Creates a layout manager for the components in the title pane. + * Adds the sub components of the title pane. + */ + protected void addSubComponents() + { + // FIXME: this method is probably overridden to only add the required + // buttons + add(title); + add(closeButton); + add(iconButton); + add(maxButton); + } + + /** + * Creates a new instance of {@link MetalTitlePaneLayout}. * - * @return A layout manager. - */ + * @return A new instance of {@link MetalTitlePaneLayout}. + */ protected LayoutManager createLayout() { - return new TitlePaneLayout() - { - public Dimension preferredLayoutSize(Container c) - { - return new Dimension(24, 24); - } - }; + return new MetalTitlePaneLayout(); } + /** + * Draws the title pane in the palette style. + * + * @param g the graphics device. + * + * @see #paintComponent(Graphics) + */ public void paintPalette(Graphics g) { - // FIXME: needs implementing - // most likely this is equivalent to paintComponent(g) when the isPalette - // flag is true + Color savedColor = g.getColor(); + Rectangle b = SwingUtilities.getLocalBounds(this); + g.setColor(MetalLookAndFeel.getPrimaryControlShadow()); + g.fillRect(b.x, b.y, b.width, b.height); + MetalUtils.fillMetalPattern(this, g, b.x + 4, b.y + 2, b.width + - paletteCloseIcon.getIconWidth() - 13, b.height - 5, + MetalLookAndFeel.getPrimaryControlHighlight(), + MetalLookAndFeel.getBlack()); + + // draw a line separating the title pane from the frame content + Dimension d = getSize(); + g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow()); + g.drawLine(0, d.height - 1, d.width - 1, d.height - 1); + + g.setColor(savedColor); } - + + /** + * Paints a representation of the current state of the internal frame. + * + * @param g the graphics device. + */ public void paintComponent(Graphics g) { - // probably need to check the isPalette flag here, if true pass over to - // paintPalette(Graphics) - super.paintComponent(g); - Dimension d = getSize(); - if (frame.isSelected()) - g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow()); + Color savedColor = g.getColor(); + if (isPalette) + paintPalette(g); else - g.setColor(MetalLookAndFeel.getControlDarkShadow()); - g.drawLine(0, d.height - 1, d.width - 1, d.height - 1); + { + paintTitleBackground(g); + paintChildren(g); + Dimension d = getSize(); + if (frame.isSelected()) + g.setColor(MetalLookAndFeel.getPrimaryControlDarkShadow()); + else + g.setColor(MetalLookAndFeel.getControlDarkShadow()); + + // put a dot in each of the top corners + g.drawLine(0, 0, 0, 0); + g.drawLine(d.width - 1, 0, d.width - 1, 0); + + g.drawLine(0, d.height - 1, d.width - 1, d.height - 1); + + // draw the metal pattern + Rectangle b = title.getBounds(); + int startX = b.x + b.width + 5; + int endX = startX; + if (iconButton.isVisible()) + endX = Math.max(iconButton.getX(), endX); + else if (maxButton.isVisible()) + endX = Math.max(maxButton.getX(), endX); + else if (closeButton.isVisible()) + endX = Math.max(closeButton.getX(), endX); + endX -= 7; + if (endX > startX) + MetalUtils.fillMetalPattern(this, g, startX, 3, endX - startX, getHeight() - 6, Color.white, Color.gray); + } + g.setColor(savedColor); } + /** + * Sets the flag that controls whether the title pane is drawn in the + * palette style or the regular style. + * + * @param b the new value of the flag. + */ public void setPalette(boolean b) { - isPalette = b; + isPalette = b; + title.setVisible(!isPalette); + iconButton.setVisible(!isPalette && frame.isIconifiable()); + maxButton.setVisible(!isPalette && frame.isMaximizable()); + if (isPalette) + closeButton.setIcon(paletteCloseIcon); + else + closeButton.setIcon(closeIcon); + } + + /** + * Creates and returns a property change handler for the title pane. + * + * @return The property change handler. + */ + protected PropertyChangeListener createPropertyChangeListener() + { + return new MetalInternalFrameTitlePanePropertyChangeHandler(); } } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameUI.java index 7c7cb92..6be573f 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalInternalFrameUI.java @@ -38,24 +38,31 @@ exception statement from your version. */ package javax.swing.plaf.metal; -import java.util.HashMap; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; import javax.swing.JComponent; import javax.swing.JInternalFrame; -import javax.swing.border.EmptyBorder; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicInternalFrameUI; - +/** + * A UI delegate for the {@link JInternalFrame} component. + */ public class MetalInternalFrameUI extends BasicInternalFrameUI { - - /** The instances of MetalInternalFrameUI*/ - private static HashMap instances; + /** + * The key (<code>JInternalFrame.isPalette</code>) for the client property + * that controls whether the internal frame is displayed using the palette + * style. + */ + protected static String IS_PALETTE = "JInternalFrame.isPalette"; /** - * Constructs a new instance of MetalInternalFrameUI. + * Constructs a new instance of <code>MetalInternalFrameUI</code>. + * + * @param frame the frame. */ public MetalInternalFrameUI(JInternalFrame frame) { @@ -63,37 +70,96 @@ public class MetalInternalFrameUI } /** - * Returns an instance of MetalInternalFrameUI. + * Returns an instance of <code>MetalInternalFrameUI</code>. * - * @param component the component for which we return an UI instance + * @param component the internal frame. * - * @return an instance of MetalInternalFrameUI + * @return an instance of <code>MetalInternalFrameUI</code>. */ 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; + return new MetalInternalFrameUI((JInternalFrame) component); } + /** + * Sets the fields and properties for the component. + * + * @param c the component. + */ + public void installUI(JComponent c) + { + super.installUI(c); + JInternalFrame f = (JInternalFrame) c; + boolean isPalette = false; + Boolean p = (Boolean) f.getClientProperty(IS_PALETTE); + if (p != null) + isPalette = p.booleanValue(); + setPalette(isPalette); + } + + /** + * Creates and returns the component that will be used for the north pane + * of the {@link JInternalFrame}. + * + * @param w the internal frame. + * + * @return A new instance of {@link MetalInternalFrameTitlePane}. + */ protected JComponent createNorthPane(JInternalFrame w) { titlePane = new MetalInternalFrameTitlePane(w); - titlePane.setBorder(new EmptyBorder(2, 2, 2, 2)); return titlePane; } - + /** + * Sets the state of the {@link JInternalFrame} to reflect whether or not + * it is using the palette style. When a frame is displayed as a palette, + * it uses a different border and the title pane is drawn differently. + * + * @param isPalette use the palette style? + */ + public void setPalette(boolean isPalette) + { + MetalInternalFrameTitlePane title = (MetalInternalFrameTitlePane) northPane; + title.setPalette(isPalette); + if (isPalette) + frame.setBorder(new MetalBorders.PaletteBorder()); + else + frame.setBorder(new MetalBorders.InternalFrameBorder()); + } + + /** A listener that is used to handle IS_PALETTE property changes. */ + private PropertyChangeListener paletteListener; + + /** + * Adds the required listeners. + */ + protected void installListeners() + { + super.installListeners(); + paletteListener = new PropertyChangeListener() + { + public void propertyChange(PropertyChangeEvent e) + { + if (e.getPropertyName().equals(IS_PALETTE)) + { + if (Boolean.TRUE.equals(e.getNewValue())) + setPalette(true); + else + setPalette(false); + } + } + }; + frame.addPropertyChangeListener(paletteListener); + } + + /** + * Removes the listeners used. + */ + protected void uninstallListeners() + { + super.uninstallListeners(); + frame.removePropertyChangeListener(IS_PALETTE, paletteListener); + paletteListener = null; + } } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalLabelUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalLabelUI.java index fe8a9e4..e4eaa71 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalLabelUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalLabelUI.java @@ -50,17 +50,17 @@ import javax.swing.plaf.basic.BasicGraphicsUtils; import javax.swing.plaf.basic.BasicLabelUI; /** - * A UI delegate used for {@link JLabel}s in the {@link MetalLookAndFeel}. + * A UI delegate for the {@link JLabel} component. */ public class MetalLabelUI extends BasicLabelUI { - /** The shared UI instance for JLabels. */ + /** The shared instance of the UI delegate. */ protected static MetalLabelUI metalLabelUI; /** - * Constructs a new instance of MetalLabelUI. + * Constructs a new instance of <code>MetalLabelUI</code>. */ public MetalLabelUI() { @@ -68,11 +68,11 @@ public class MetalLabelUI } /** - * Returns an instance of MetalLabelUI. + * Returns a shared instance of <code>MetalLabelUI</code>. * * @param component the component for which we return an UI instance * - * @return an instance of MetalLabelUI + * @return A shared instance of <code>MetalLabelUI</code>. */ public static ComponentUI createUI(JComponent component) { diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java b/libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java index d9cf7c6..ec8014b 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalLookAndFeel.java @@ -42,11 +42,14 @@ import java.awt.Color; import java.awt.Font; import java.awt.Insets; +import javax.swing.LookAndFeel; import javax.swing.UIDefaults; +import javax.swing.UIManager; import javax.swing.plaf.BorderUIResource; import javax.swing.plaf.ColorUIResource; import javax.swing.plaf.FontUIResource; import javax.swing.plaf.InsetsUIResource; +import javax.swing.plaf.BorderUIResource.LineBorderUIResource; import javax.swing.plaf.basic.BasicLookAndFeel; @@ -69,7 +72,8 @@ public class MetalLookAndFeel extends BasicLookAndFeel */ public MetalLookAndFeel() { - createDefaultTheme(); + if (theme == null) + createDefaultTheme(); } /** @@ -601,12 +605,21 @@ public class MetalLookAndFeel extends BasicLookAndFeel } /** - * Sets the current theme for the look and feel. + * Sets the current theme for the look and feel. Note that the theme must be + * set <em>before</em> the look and feel is installed. To change the theme + * for an already running application that is using the + * {@link MetalLookAndFeel}, first set the theme with this method, then + * create a new instance of {@link MetalLookAndFeel} and install it in the + * usual way (see {@link UIManager#setLookAndFeel(LookAndFeel)}). * - * @param theme the theme. + * @param theme the theme (<code>null</code> not permitted). + * + * @throws NullPointerException if <code>theme</code> is <code>null</code>. */ public static void setCurrentTheme(MetalTheme theme) { + if (theme == null) + throw new NullPointerException("Null 'theme' not permitted."); MetalLookAndFeel.theme = theme; } @@ -759,62 +772,206 @@ public class MetalLookAndFeel extends BasicLookAndFeel { super.initComponentDefaults(defaults); Object[] myDefaults = new Object[] { - "Button.background", new ColorUIResource(getControl()), + "Button.background", getControl(), "Button.border", MetalBorders.getButtonBorder(), - "Button.darkShadow", new ColorUIResource(getControlDarkShadow()), - "Button.disabledText", new ColorUIResource(getControlDisabled()), - "Button.focus", new ColorUIResource(getFocusColor()), + "Button.darkShadow", getControlDarkShadow(), + "Button.disabledText", getInactiveControlTextColor(), + "Button.focus", 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()), + "Button.foreground", getControlTextColor(), + "Button.highlight", getControlHighlight(), + "Button.light", getControlHighlight(), + "Button.margin", new InsetsUIResource(2, 14, 2, 14), + "Button.select", getControlShadow(), + "Button.shadow", getControlShadow(), + + "CheckBox.background", getControl(), "CheckBox.border", MetalBorders.getButtonBorder(), + "CheckBox.disabledText", getInactiveControlTextColor(), + "CheckBox.focus", getFocusColor(), + "CheckBox.font", new FontUIResource("Dialog", Font.BOLD, 12), + "CheckBox.foreground", getControlTextColor(), "CheckBox.icon", new UIDefaults.ProxyLazyValue ("javax.swing.plaf.metal.MetalCheckBoxIcon"), "CheckBox.checkIcon", new UIDefaults.ProxyLazyValue ("javax.swing.plaf.metal.MetalCheckBoxIcon"), - "CheckBoxMenuItem.background", new ColorUIResource(getControl()), + "Checkbox.select", getControlShadow(), + + "CheckBoxMenuItem.acceleratorFont", new FontUIResource("Dialog", Font.PLAIN, 10), + "CheckBoxMenuItem.acceleratorForeground", getAcceleratorForeground(), + "CheckBoxMenuItem.acceleratorSelectionForeground", getAcceleratorSelectedForeground(), + "CheckBoxMenuItem.background", getMenuBackground(), + "CheckBoxMenuItem.borderPainted", new Boolean(true), + "CheckBoxMenuItem.commandSound", "sounds/MenuItemCommand.wav", "CheckBoxMenuItem.checkIcon", MetalIconFactory.getCheckBoxMenuItemIcon(), - "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()), + "CheckBoxMenuItem.disabledForeground", getMenuDisabledForeground(), + "CheckBoxMenuItem.font", new FontUIResource("Dialog", Font.BOLD, 12), + "CheckBoxMenuItem.foreground", getMenuForeground(), + "CheckBoxMenuItem.selectionBackground", getMenuSelectedBackground(), + "CheckBoxMenuItem.selectionForeground", getMenuSelectedForeground(), + + "ColorChooser.background", getControl(), + "ColorChooser.foreground", getControlTextColor(), + "ColorChooser.rgbBlueMnemonic", new Integer(0), + "ColorChooser.rgbGreenMnemonic", new Integer(0), + "ColorChooser.rgbRedMnemonic", new Integer(0), + "ColorChooser.swatchesDefaultRecentColor", getControl(), + + "ComboBox.background", getControl(), + "ComboBox.buttonBackground", getControl(), + "ComboBox.buttonDarkShadow", getControlDarkShadow(), + "ComboBox.buttonHighlight", getControlHighlight(), + "ComboBox.buttonShadow", getControlShadow(), + "ComboBox.disabledBackground", getControl(), + "ComboBox.disabledForeground", getInactiveSystemTextColor(), + "ComboBox.font", new FontUIResource("Dialog", Font.BOLD, 12), + "ComboBox.foreground", getControlTextColor(), + "ComboBox.selectionBackground", getPrimaryControlShadow(), + "ComboBox.selectionForeground", getControlTextColor(), + + "Desktop.background", getDesktopColor(), + + "DesktopIcon.background", getControl(), + "DesktopIcon.foreground", getControlTextColor(), + "DesktopIcon.width", new Integer(160), + "DesktopIcon.border", MetalBorders.getDesktopIconBorder(), + + "EditorPane.background", getWindowBackground(), + "EditorPane.caretForeground", getUserTextColor(), + "EditorPane.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "EditorPane.foreground", getUserTextColor(), + "EditorPane.inactiveForeground", getInactiveSystemTextColor(), + "EditorPane.selectionBackground", getTextHighlightColor(), + "EditorPane.selectionForeground", getHighlightedTextColor(), + + "FormattedTextField.background", getWindowBackground(), + "FormattedTextField.border", + new BorderUIResource(MetalBorders.getTextFieldBorder()), + "FormattedTextField.caretForeground", getUserTextColor(), + "FormattedTextField.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "FormattedTextField.foreground", getUserTextColor(), + "FormattedTextField.inactiveBackground", getControl(), + "FormattedTextField.inactiveForeground", getInactiveSystemTextColor(), + "FormattedTextField.selectionBackground", getTextHighlightColor(), + "FormattedTextField.selectionForeground", getHighlightedTextColor(), + + "FileView.computerIcon", MetalIconFactory.getTreeComputerIcon(), + "FileView.directoryIcon", MetalIconFactory.getTreeFolderIcon(), + "FileView.fileIcon", MetalIconFactory.getTreeLeafIcon(), + "FileView.floppyDriveIcon", MetalIconFactory.getTreeFloppyDriveIcon(), + "FileView.hardDriveIcon", MetalIconFactory.getTreeHardDriveIcon(), + + "InternalFrame.activeTitleBackground", getWindowTitleBackground(), + "InternalFrame.activeTitleForeground", getWindowTitleForeground(), "InternalFrame.border", new MetalBorders.InternalFrameBorder(), + "InternalFrame.borderColor", getControl(), + "InternalFrame.borderDarkShadow", getControlDarkShadow(), + "InternalFrame.borderHighlight", getControlHighlight(), + "InternalFrame.borderLight", getControlHighlight(), + "InternalFrame.borderShadow", getControlShadow(), "InternalFrame.icon", MetalIconFactory.getInternalFrameDefaultMenuIcon(), "InternalFrame.closeIcon", MetalIconFactory.getInternalFrameCloseIcon(16), + "InternalFrame.inactiveTitleBackground", getWindowTitleInactiveBackground(), + "InternalFrame.inactiveTitleForeground", getWindowTitleInactiveForeground(), "InternalFrame.maximizeIcon", MetalIconFactory.getInternalFrameMaximizeIcon(16), "InternalFrame.iconifyIcon", MetalIconFactory.getInternalFrameMinimizeIcon(16), - "Label.background", new ColorUIResource(getControl()), + "InternalFrame.paletteBorder", new MetalBorders.PaletteBorder(), + "InternalFrame.paletteCloseIcon", new MetalIconFactory.PaletteCloseIcon(), + "InternalFrame.paletteTitleHeight", new Integer(11), + + "Label.background", getControl(), + "Label.disabledForeground", getInactiveSystemTextColor(), + "Label.disabledShadow", getControlShadow(), "Label.font", getControlTextFont(), - "Label.disabledForeground", new ColorUIResource(getInactiveControlTextColor()), - "Label.foreground", new ColorUIResource(getControlTextColor()), - "Menu.background", new ColorUIResource(getControl()), + "Label.foreground", getSystemTextColor(), + + "List.font", getControlTextFont(), + "List.background", getWindowBackground(), + "List.foreground", getUserTextColor(), + "List.selectionBackground", getTextHighlightColor(), + "List.selectionForeground", getHighlightedTextColor(), + "List.focusCellHighlightBorder", + new LineBorderUIResource(MetalLookAndFeel.getFocusColor()), + + "Menu.acceleratorFont", new FontUIResource("Dialog", Font.PLAIN, 10), + "Menu.acceleratorForeground", getAcceleratorForeground(), + "Menu.acceleratorSelectionForeground", getAcceleratorSelectedForeground(), + "Menu.background", getMenuBackground(), "Menu.border", new MetalBorders.MenuItemBorder(), "Menu.borderPainted", Boolean.TRUE, + "Menu.disabledForeground", getMenuDisabledForeground(), "Menu.font", getControlTextFont(), + "Menu.foreground", getMenuForeground(), "Menu.selectionBackground", getMenuSelectedBackground(), "Menu.selectionForeground", getMenuSelectedForeground(), - "MenuBar.background", new ColorUIResource(getControl()), + + "MenuBar.background", getMenuBackground(), "MenuBar.border", new MetalBorders.MenuBarBorder(), "MenuBar.font", getControlTextFont(), - "MenuItem.background", new ColorUIResource(getControl()), + "MenuBar.foreground", getMenuForeground(), + "MenuBar.highlight", getControlHighlight(), + "MenuBar.shadow", getControlShadow(), + + "MenuItem.acceleratorFont", new FontUIResource("Dialog", Font.PLAIN, 10), + "MenuItem.acceleratorForeground", getAcceleratorForeground(), + "MenuItem.acceleratorSelectionForeground", getAcceleratorSelectedForeground(), + "MenuItem.background", getMenuBackground(), "MenuItem.border", new MetalBorders.MenuItemBorder(), + "MenuItem.disabledForeground", getMenuDisabledForeground(), "MenuItem.font", getControlTextFont(), + "MenuItem.foreground", getMenuForeground(), "MenuItem.selectionBackground", getMenuSelectedBackground(), "MenuItem.selectionForeground", getMenuSelectedForeground(), - "Panel.background", new ColorUIResource(getControl()), + + "OptionPane.background", getControl(), + "OptionPane.errorDialog.border.background", new ColorUIResource(153, 51, 51), + "OptionPane.errorDialog.titlePane.background", new ColorUIResource(255, 153, 153), + "OptionPane.errorDialog.titlePane.foreground", new ColorUIResource(51, 0, 0), + "OptionPane.errorDialog.titlePane.shadow", new ColorUIResource(204, 102, 102), + "OptionPane.foreground", getControlTextColor(), + "OptionPane.messageForeground", getControlTextColor(), + "OptionPane.questionDialog.border.background", new ColorUIResource(51, 102, 51), + "OptionPane.questionDialog.titlePane.background", new ColorUIResource(153, 204, 153), + "OptionPane.questionDialog.titlePane.foreground", new ColorUIResource(0, 51, 0), + "OptionPane.questionDialog.titlePane.shadow", new ColorUIResource(102, 153, 102), + "OptionPane.warningDialog.border.background", new ColorUIResource(153, 102, 51), + "OptionPane.warningDialog.titlePane.background", new ColorUIResource(255, 204, 153), + "OptionPane.warningDialog.titlePane.foreground", new ColorUIResource(102, 51, 0), + "OptionPane.warningDialog.titlePane.shadow", new ColorUIResource(204, 153, 102), + + "Panel.background", getControl(), + "Panel.foreground", getUserTextColor(), + + "PasswordField.background", getWindowBackground(), + "PasswordField.border", + new BorderUIResource(MetalBorders.getTextFieldBorder()), + "PasswordField.caretForeground", getUserTextColor(), + "PasswordField.foreground", getUserTextColor(), + "PasswordField.inactiveBackground", getControl(), + "PasswordField.inactiveForeground", getInactiveSystemTextColor(), + "PasswordField.selectionBackground", getTextHighlightColor(), + "PasswordField.selectionForeground", getHighlightedTextColor(), + + "PopupMenu.background", getMenuBackground(), + "PopupMenu.border", new MetalBorders.PopupMenuBorder(), + "PopupMenu.font", new FontUIResource("Dialog", Font.BOLD, 12), + "PopupMenu.foreground", getMenuForeground(), + + "ProgressBar.background", getControl(), + "ProgressBar.border", new BorderUIResource.LineBorderUIResource(getControlDarkShadow(), 1), + "ProgressBar.font", new FontUIResource("Dialog", Font.BOLD, 12), + "ProgressBar.foreground", getPrimaryControlShadow(), + "ProgressBar.selectionBackground", getPrimaryControlDarkShadow(), + "ProgressBar.selectionForeground", getControl(), + + "RadioButton.background", getControl(), + "RadioButton.darkShadow", getControlDarkShadow(), + "RadioButton.disabledText", getInactiveControlTextColor(), "RadioButton.icon", new UIDefaults.LazyValue() { @@ -823,80 +980,199 @@ public class MetalLookAndFeel extends BasicLookAndFeel return MetalIconFactory.getRadioButtonIcon(); } }, - + "RadioButton.focus", MetalLookAndFeel.getFocusColor(), + "RadioButton.font", MetalLookAndFeel.getControlTextFont(), + "RadioButton.foreground", getControlTextColor(), + "RadioButton.highlight", getControlHighlight(), + "RadioButton.light", getControlHighlight(), + "RadioButton.select", getControlShadow(), + "RadioButton.shadow", getControlShadow(), + + "RadioButtonMenuItem.acceleratorFont", new Font("Dialog", Font.PLAIN, 10), + "RadioButtonMenuItem.acceleratorForeground", getAcceleratorForeground(), + "RadioButtonMenuItem.acceleratorSelectionForeground", getAcceleratorSelectedForeground(), + "RadioButtonMenuItem.background", getMenuBackground(), "RadioButtonMenuItem.border", new MetalBorders.MenuItemBorder(), "RadioButtonMenuItem.borderPainted", Boolean.TRUE, "RadioButtonMenuItem.checkIcon", MetalIconFactory.getRadioButtonMenuItemIcon(), + "RadioButtonMenuItem.disabledForeground", getMenuDisabledForeground(), "RadioButtonMenuItem.font", MetalLookAndFeel.getControlTextFont(), + "RadioButtonMenuItem.foreground", getMenuForeground(), "RadioButtonMenuItem.margin", new InsetsUIResource(2, 2, 2, 2), "RadioButtonMenuItem.selectionBackground", MetalLookAndFeel.getMenuSelectedBackground(), "RadioButtonMenuItem.selectionForeground", MetalLookAndFeel.getMenuSelectedForeground(), - "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()), + "ScrollBar.background", getControl(), + "ScrollBar.darkShadow", getControlDarkShadow(), + "ScrollBar.foreground", getControl(), + "ScrollBar.highlight", getControlHighlight(), + "ScrollBar.shadow", getControlShadow(), + "ScrollBar.thumb", getPrimaryControlShadow(), + "ScrollBar.thumbDarkShadow", getControlDarkShadow(), + "ScrollBar.thumbHighlight", getPrimaryControl(), + "ScrollBar.thumbShadow", getPrimaryControlDarkShadow(), + "ScrollBar.track", getControl(), + "ScrollBar.trackHighlight", getControlDarkShadow(), + "ScrollBar.width", new Integer(17), + + "ScrollPane.background", getControl(), + "ScrollPane.border", new MetalBorders.ScrollPaneBorder(), + "ScrollPane.foreground", getControlTextColor(), - "SplitPane.darkShadow", - new ColorUIResource(getControlDarkShadow()), - "SplitPane.highlight", - new ColorUIResource(getControlHighlight()), + "Separator.background", getSeparatorBackground(), + "Separator.foreground", getSeparatorForeground(), + "Separator.highlight", getControlHighlight(), + "Separator.shadow", getControlShadow(), + "Slider.background", getControl(), + "Slider.focus", getFocusColor(), "Slider.focusInsets", new InsetsUIResource(0, 0, 0, 0), + "Slider.foreground", getPrimaryControlShadow(), + "Slider.highlight", getControlHighlight(), "Slider.horizontalThumbIcon", MetalIconFactory.getHorizontalSliderThumbIcon(), + "Slider.majorTickLength", new Integer(6), + "Slider.shadow", getControlShadow(), + "Slider.trackWidth", new Integer(7), "Slider.verticalThumbIcon", MetalIconFactory.getVerticalSliderThumbIcon(), - "Slider.trackWidth", new Integer(7), - "Slider.majorTickLength", new Integer(6), - + + "Spinner.background", getControl(), + "Spinner.font", new FontUIResource("Dialog", Font.BOLD, 12), + "Spinner.foreground", getControl(), + + "SplitPane.background", getControl(), + "SplitPane.darkShadow", getControlDarkShadow(), + "SplitPane.dividerFocusColor", getPrimaryControl(), + "SplitPane.highlight", getControlHighlight(), + "SplitPane.shadow", getControlShadow(), + + "SplitPaneDivider.draggingColor", Color.DARK_GRAY, + + "TabbedPane.background", getControlShadow(), + "TabbedPane.darkShadow", getControlDarkShadow(), + "TabbedPane.focus", getPrimaryControlDarkShadow(), "TabbedPane.font", new FontUIResource("Dialog", Font.BOLD, 12), - "TabbedPane.tabInsets", new InsetsUIResource(0, 9, 1, 9), + "TabbedPane.foreground", getControlTextColor(), + "TabbedPane.highlight", getControlHighlight(), + "TabbedPane.light", getControl(), + "TabbedPane.selected", getControl(), + "TabbedPane.selectHighlight", getControlHighlight(), "TabbedPane.selectedTabPadInsets", new InsetsUIResource(2, 2, 2, 1), + "TabbedPane.shadow", getControlShadow(), + "TabbedPane.tabAreaBackground", getControl(), "TabbedPane.tabAreaInsets", new InsetsUIResource(4, 2, 0, 6), - - "ToggleButton.background", new ColorUIResource(getControl()), - "ToggleButton.border", MetalBorders.getButtonBorder(), - "ToggleButton.darkShadow", new ColorUIResource(getControlDarkShadow()), - "ToggleButton.disabledText", new ColorUIResource(getControlDisabled()), - "ToggleButton.focus", new ColorUIResource(getFocusColor()), + "TabbedPane.tabInsets", new InsetsUIResource(0, 9, 1, 9), + + "Table.background", getWindowBackground(), + "Table.focusCellBackground", getWindowBackground(), + "Table.focusCellForeground", getControlTextColor(), + "Table.foreground", getControlTextColor(), + "Table.focusCellHighlightBorder", + new BorderUIResource.LineBorderUIResource(getControlShadow()), + "Table.focusCellBackground", getWindowBackground(), + "Table.gridColor", getControlDarkShadow(), + "Table.selectionBackground", new ColorUIResource(204, 204, 255), + "Table.selectionForeground", new ColorUIResource(0, 0, 0), + + "TableHeader.background", getControl(), + "TableHeader.cellBorder", new MetalBorders.TableHeaderBorder(), + "TableHeader.foreground", getControlTextColor(), + + "TextArea.background", getWindowBackground(), + "TextArea.caretForeground", getUserTextColor(), + "TextArea.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "TextArea.foreground", getUserTextColor(), + "TextArea.inactiveForeground", getInactiveSystemTextColor(), + "TextArea.selectionBackground", getTextHighlightColor(), + "TextArea.selectionForeground", getHighlightedTextColor(), + + "TextField.background", getWindowBackground(), + "TextField.border", + new BorderUIResource(MetalBorders.getTextFieldBorder()), + "TextField.caretForeground", getUserTextColor(), + "TextField.darkShadow", getControlDarkShadow(), + "TextField.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "TextField.foreground", getUserTextColor(), + "TextField.highlight", getControlHighlight(), + "TextField.inactiveBackground", getControl(), + "TextField.inactiveForeground", getInactiveSystemTextColor(), + "TextField.light", getControlHighlight(), + "TextField.selectionBackground", getTextHighlightColor(), + "TextField.selectionForeground", getHighlightedTextColor(), + "TextField.shadow", getControlShadow(), + + "TextPane.background", getWindowBackground(), + "TextPane.caretForeground", getUserTextColor(), + "TextPane.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "TextPane.foreground", getUserTextColor(), + "TextPane.inactiveForeground", getInactiveSystemTextColor(), + "TextPane.selectionBackground", getTextHighlightColor(), + "TextPane.selectionForeground", getHighlightedTextColor(), + + "TitledBorder.font", new FontUIResource("Dialog", Font.BOLD, 12), + "TitledBorder.titleColor", getSystemTextColor(), + + "ToggleButton.background", getControl(), + "ToggleButton.border", MetalBorders.getToggleButtonBorder(), + "ToggleButton.darkShadow", getControlDarkShadow(), + "ToggleButton.disabledText", getInactiveControlTextColor(), + "ToggleButton.focus", getFocusColor(), "ToggleButton.font", getControlTextFont(), - "ToggleButton.foreground", new ColorUIResource(getSystemTextColor()), - "ToggleButton.highlight", new ColorUIResource(getControlHighlight()), - "ToggleButton.light", new ColorUIResource(getControlHighlight()), - "ToggleButton.margin", new Insets(2, 14, 2, 14), - "ToggleButton.select", new ColorUIResource(getPrimaryControlShadow()), - "ToggleButton.shadow", new ColorUIResource(getPrimaryControlShadow()), - - "Tree.openIcon", MetalIconFactory.getTreeFolderIcon(), + "ToggleButton.foreground", getControlTextColor(), + "ToggleButton.highlight", getControlHighlight(), + "ToggleButton.light", getControlHighlight(), + "ToggleButton.margin", new InsetsUIResource(2, 14, 2, 14), + "ToggleButton.select", getControlShadow(), + "ToggleButton.shadow", getControlShadow(), + + "ToolBar.background", getMenuBackground(), + "ToolBar.darkShadow", getControlDarkShadow(), + "ToolBar.dockingBackground", getMenuBackground(), + "ToolBar.dockingForeground", getPrimaryControlDarkShadow(), + "ToolBar.floatingBackground", getMenuBackground(), + "ToolBar.floatingForeground", getPrimaryControl(), + "ToolBar.font", new FontUIResource("Dialog", Font.BOLD, 12), + "ToolBar.foreground", getMenuForeground(), + "ToolBar.highlight", getControlHighlight(), + "ToolBar.light", getControlHighlight(), + "ToolBar.shadow", getControlShadow(), + "ToolBar.border", new MetalBorders.ToolBarBorder(), + + "ToolTip.background", getPrimaryControl(), + "ToolTip.backgroundInactive", getControl(), + "ToolTip.border", new BorderUIResource.LineBorderUIResource(getPrimaryControlDarkShadow(), 1), + "ToolTip.borderInactive", new BorderUIResource.LineBorderUIResource(getControlDarkShadow(), 1), + "ToolTip.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "ToolTip.foreground", getPrimaryControlInfo(), + "ToolTip.foregroundInactive", getControlDarkShadow(), + + "Tree.background", getWindowBackground(), "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.font", new FontUIResource("Dialog", Font.PLAIN, 12), + "Tree.foreground", getUserTextColor(), + "Tree.hash", getPrimaryControl(), + "Tree.leafIcon", MetalIconFactory.getTreeLeafIcon(), "Tree.leftChildIndent", new Integer(7), + "Tree.line", getPrimaryControl(), + "Tree.openIcon", MetalIconFactory.getTreeFolderIcon(), "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.selectionBackground", getTextHighlightColor(), "Tree.selectionBorder", new BorderUIResource.LineBorderUIResource(new Color(102, 102, 153)), - "Tree.nonSelectionBorder", new BorderUIResource.LineBorderUIResource(Color.white), - "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() + "Tree.selectionBorderColor", getFocusColor(), + "Tree.selectionForeground", getHighlightedTextColor(), + "Tree.textBackground", getWindowBackground(), + "Tree.textForeground", getUserTextColor(), + + "Viewport.background", getControl(), + "Viewport.foreground", getUserTextColor() }; defaults.putDefaults(myDefaults); } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalPopupMenuSeparatorUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalPopupMenuSeparatorUI.java index ec9bf2b..44a2d3bc 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalPopupMenuSeparatorUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalPopupMenuSeparatorUI.java @@ -39,8 +39,12 @@ exception statement from your version. */ package javax.swing.plaf.metal; import javax.swing.JComponent; +import javax.swing.JPopupMenu; import javax.swing.plaf.ComponentUI; +/** + * A UI delegate for the {@link JPopupMenu.Separator} component. + */ public class MetalPopupMenuSeparatorUI extends MetalSeparatorUI { @@ -50,7 +54,7 @@ public class MetalPopupMenuSeparatorUI private static MetalPopupMenuSeparatorUI instance = null; /** - * Constructs a new instance of MetalPopupMenuSeparatorUI. + * Constructs a new instance of <code>MetalPopupMenuSeparatorUI</code>. */ public MetalPopupMenuSeparatorUI() { @@ -58,11 +62,11 @@ public class MetalPopupMenuSeparatorUI } /** - * Returns an instance of MetalPopupMenuSeparatorUI. + * Returns a shared instance of <code>MetalPopupMenuSeparatorUI</code>. * * @param component the component for which we return an UI instance * - * @return an instance of MetalPopupMenuSeparatorUI + * @return A shared instance of <code>MetalPopupMenuSeparatorUI</code>. */ public static ComponentUI createUI(JComponent component) { diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalProgressBarUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalProgressBarUI.java index 96d1988..0f28818 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalProgressBarUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalProgressBarUI.java @@ -38,20 +38,22 @@ exception statement from your version. */ package javax.swing.plaf.metal; +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Insets; + import javax.swing.JComponent; +import javax.swing.JProgressBar; 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; - +/** + * A UI delegate for the {@link JProgressBar} component. + */ +public class MetalProgressBarUI extends BasicProgressBarUI +{ /** - * Constructs a new instance of MetalProgressBarUI. + * Constructs a new instance of <code>MetalProgressBarUI</code>. */ public MetalProgressBarUI() { @@ -59,16 +61,87 @@ public class MetalProgressBarUI } /** - * Returns an instance of MetalProgressBarUI. + * Returns a new instance of <code>MetalProgressBarUI</code>. * * @param component the component for which we return an UI instance * - * @return an instance of MetalProgressBarUI + * @return A new instance of <code>MetalProgressBarUI</code>. */ public static ComponentUI createUI(JComponent component) { - if (instance == null) - instance = new MetalProgressBarUI(); - return instance; + return new MetalProgressBarUI(); + } + + /** + * Performs the painting for determinate progress bars. This calls the + * superclass behaviour and then adds some highlighting to the upper and left + * edge of the progress bar. + * + * @param g the graphics context + * @param c not used here + */ + public void paintDeterminate(Graphics g, JComponent c) + { + super.paintDeterminate(g, c); + Color saved = g.getColor(); + Insets i = progressBar.getInsets(); + int w = progressBar.getWidth(); + int h = progressBar.getHeight(); + int orientation = progressBar.getOrientation(); + + Color shadow = MetalLookAndFeel.getControlShadow(); + g.setColor(shadow); + + g.drawLine(i.left, i.top, w - i.right, i.top); + g.drawLine(i.left, i.top, i.left, h - i.bottom); + int full = getAmountFull(i, w, h); + if (full > 0) + { + Color darkShadow = MetalLookAndFeel.getPrimaryControlDarkShadow(); + g.setColor(darkShadow); + if (orientation == JProgressBar.HORIZONTAL) + { + g.drawLine(i.left, i.top, i.left, h - i.bottom); + g.drawLine(i.left, i.top, i.left + full - 1, i.top); + } + else + { + if (full >= (h - i.top - i.bottom)) + g.drawLine(i.left, i.top, w - i.right, i.top); + g.drawLine(i.left, h - i.bottom, i.left, h - i.bottom - full); + } + } + g.setColor(saved); + } + + /** + * Performs the painting for indeterminate progress bars. This calls the + * superclass behaviour and then adds some highlighting to the upper and left + * edge of the progress bar. + * + * @param g the graphics context + * @param c not used here + */ + public void paintIndeterminate(Graphics g, JComponent c) + { + super.paintIndeterminate(g, c); + Color saved = g.getColor(); + Insets i = progressBar.getInsets(); + int w = progressBar.getWidth(); + int h = progressBar.getHeight(); + Color shadow = MetalLookAndFeel.getControlShadow(); + g.setColor(shadow); + g.drawLine(i.left, i.top, w - i.right, i.top); + g.drawLine(i.left, i.top, i.left, h - i.bottom); + + boxRect = getBox(boxRect); + Color darkShadow = MetalLookAndFeel.getPrimaryControlDarkShadow(); + g.setColor(darkShadow); + int orientation = progressBar.getOrientation(); + if (orientation == JProgressBar.HORIZONTAL) + g.drawLine(boxRect.x, i.top, boxRect.x + boxRect.width - 1, i.top); + else + g.drawLine(i.left, boxRect.y, i.left, boxRect.y + boxRect.height - 1); + g.setColor(saved); } } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalRadioButtonUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalRadioButtonUI.java index a668f91..f37626e 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalRadioButtonUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalRadioButtonUI.java @@ -38,20 +38,38 @@ exception statement from your version. */ package javax.swing.plaf.metal; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Rectangle; + +import javax.swing.AbstractButton; import javax.swing.JComponent; +import javax.swing.JRadioButton; +import javax.swing.UIDefaults; +import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicRadioButtonUI; + +/** + * A UI delegate for the {@link JRadioButton} component. + */ 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; - + /** Used to draw the focus rectangle. */ + protected Color focusColor; + + /** Used to fill the icon when the button is pressed. */ + protected Color selectColor; + + /** Used to draw disabled text. */ + protected Color disabledTextColor; + /** - * Constructs a new instance of MetalRadioButtonUI. + * Constructs a new instance of <code>MetalRadioButtonUI</code>. */ public MetalRadioButtonUI() { @@ -59,16 +77,108 @@ public class MetalRadioButtonUI } /** - * Returns an instance of MetalRadioButtonUI. + * Returns a new instance of <code>MetalRadioButtonUI</code>. * * @param component the component for which we return an UI instance * - * @return an instance of MetalRadioButtonUI + * @return A new instance of <code>MetalRadioButtonUI</code>. */ public static ComponentUI createUI(JComponent component) { - if (instance == null) - instance = new MetalRadioButtonUI(); - return instance; + return new MetalRadioButtonUI(); + } + + /** + * Sets the default values for the specified button. + * + * @param b the button. + */ + public void installDefaults(AbstractButton b) + { + super.installDefaults(b); + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + disabledTextColor = defaults.getColor("RadioButton.disabledText"); + focusColor = defaults.getColor("RadioButton.focus"); + selectColor = defaults.getColor("RadioButton.select"); + } + + /** + * Clears any defaults set in the installDefaults() method. + * + * @param b the {@link JRadioButton}. + */ + protected void uninstallDefaults(AbstractButton b) + { + super.uninstallDefaults(b); + disabledTextColor = null; + focusColor = null; + selectColor = null; + } + + /** + * Returns the color used to fill the {@link JRadioButton}'s icon when the + * button is pressed. The default color is obtained from the + * {@link UIDefaults} via an entry with the key + * <code>RadioButton.select</code>. + * + * @return The select color. + */ + protected Color getSelectColor() + { + return selectColor; + } + + /** + * Returns the color for the {@link JRadioButton}'s text when the button is + * disabled. The default color is obtained from the {@link UIDefaults} via + * an entry with the key <code>RadioButton.disabledText</code>. + * + * @return The disabled text color. + */ + protected Color getDisabledTextColor() + { + return disabledTextColor; + } + + /** + * Returns the color used to draw the focus rectangle when the + * {@link JRadioButton} has the focus. The default color is obtained from + * the {@link UIDefaults} via an entry with the key + * <code>RadioButton.focus</code>. + * + * @return The color used to draw the focus rectangle. + * + * @see #paintFocus(Graphics, Rectangle, Dimension) + */ + protected Color getFocusColor() + { + return focusColor; + } + + /** + * Paints the {@link JRadioButton}. + * + * @param g the graphics device. + * @param c the component (an instance of {@link JRadioButton}). + */ + public void paint(Graphics g, JComponent c) + { + super.paint(g, c); + // FIXME: disabled text isn't being drawn correctly, it's possible that + // it could be done here... + } + + /** + * Paints the focus rectangle for the {@link JRadioButton}. + * + * @param g the graphics device. + * @param t the bounding rectangle for the text. + * @param d ??? + */ + protected void paintFocus(Graphics g, Rectangle t, Dimension d) + { + g.setColor(focusColor); + g.drawRect(t.x - 1, t.y + 2, t.width + 2, t.height - 4); } + } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java index 4196a4e..faed803 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalRootPaneUI.java @@ -39,9 +39,16 @@ exception statement from your version. */ package javax.swing.plaf.metal; import javax.swing.JComponent; +import javax.swing.JRootPane; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicRootPaneUI; +/** + * A UI delegate for the {@link JRootPane} component. This class is not fully + * implemented. + * + * @since 1.4 + */ public class MetalRootPaneUI extends BasicRootPaneUI { @@ -51,7 +58,7 @@ public class MetalRootPaneUI private static MetalRootPaneUI instance = null; /** - * Constructs a new instance of MetalRootPaneUI. + * Constructs a shared instance of <code>MetalRootPaneUI</code>. */ public MetalRootPaneUI() { @@ -59,11 +66,11 @@ public class MetalRootPaneUI } /** - * Returns an instance of MetalRootPaneUI. + * Returns a shared instance of <code>MetalRootPaneUI</code>. * * @param component the component for which we return an UI instance * - * @return an instance of MetalRootPaneUI + * @return A shared instance of <code>MetalRootPaneUI</code>. */ public static ComponentUI createUI(JComponent component) { diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java index 526dfb5..9602ade 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalScrollBarUI.java @@ -38,30 +38,106 @@ exception statement from your version. */ package javax.swing.plaf.metal; +import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Rectangle; -import java.util.HashMap; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import javax.swing.JButton; import javax.swing.JComponent; +import javax.swing.JScrollBar; import javax.swing.UIDefaults; import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicScrollBarUI; -public class MetalScrollBarUI - extends BasicScrollBarUI +/** + * A UI delegate for the {@link JScrollBar} component. + */ +public class MetalScrollBarUI extends BasicScrollBarUI { + + /** + * A property change handler for the UI delegate that monitors for + * changes to the "JScrollBar.isFreeStanding" property, and updates + * the buttons and track rendering as appropriate. + */ + class MetalScrollBarPropertyChangeHandler + extends BasicScrollBarUI.PropertyChangeHandler + { + /** + * Creates a new handler. + * + * @see #createPropertyChangeListener() + */ + public MetalScrollBarPropertyChangeHandler() + { + // Nothing to do here. + } + + /** + * Handles a property change event. If the event name is + * <code>JSlider.isFreeStanding</code>, this method updates the + * delegate, otherwise the event is passed up to the super class. + * + * @param e the property change event. + */ + public void propertyChange(PropertyChangeEvent e) + { + if (e.getPropertyName().equals(FREE_STANDING_PROP)) + { + Boolean prop = (Boolean) e.getNewValue(); + isFreeStanding = (prop == null ? true : prop.booleanValue()); + if (increaseButton != null) + increaseButton.setFreeStanding(isFreeStanding); + if (decreaseButton != null) + decreaseButton.setFreeStanding(isFreeStanding); + } + else + super.propertyChange(e); + } + } + + /** The name for the 'free standing' property. */ + public static final String FREE_STANDING_PROP = "JScrollBar.isFreeStanding"; - /** 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; + /** The minimum thumb size for a scroll bar that is not free standing. */ + private static final Dimension MIN_THUMB_SIZE = new Dimension(15, 15); + /** The minimum thumb size for a scroll bar that is free standing. */ + private static final Dimension MIN_THUMB_SIZE_FREE_STANDING + = new Dimension(17, 17); + + /** The button that increases the value in the scroll bar. */ + protected MetalScrollButton increaseButton; + + /** The button that decreases the value in the scroll bar. */ + protected MetalScrollButton decreaseButton; + + /** + * The scroll bar width. + */ + protected int scrollBarWidth; + + /** + * A flag that indicates whether the scroll bar is "free standing", which + * means it has complete borders and can be used anywhere in the UI. A + * scroll bar which is not free standing has borders missing from one + * side, and relies on being part of another container with its own borders + * to look right visually. */ + protected boolean isFreeStanding = true; + + /** + * The color for the scroll bar shadow (this is read from the UIDefaults in + * the installDefaults() method). + */ + Color scrollBarShadowColor; + /** - * Constructs a new instance of MetalScrollBarUI. + * Constructs a new instance of <code>MetalScrollBarUI</code>, with no + * specific initialisation. */ public MetalScrollBarUI() { @@ -69,28 +145,192 @@ public class MetalScrollBarUI } /** - * Returns an instance of MetalScrollBarUI. + * Returns a new instance of <code>MetalScrollBarUI</code>. * * @param component the component for which we return an UI instance * - * @return an instance of MetalScrollBarUI + * @return An instance of MetalScrollBarUI */ public static ComponentUI createUI(JComponent component) { - if (instances == null) - instances = new HashMap(); + return new MetalScrollBarUI(); + } + + /** + * Installs the defaults. + */ + protected void installDefaults() + { + // need to initialise isFreeStanding before calling the super class, + // so that the value is set when createIncreaseButton() and + // createDecreaseButton() are called (unless there is somewhere earlier + // that we can do this). + Boolean prop = (Boolean) scrollbar.getClientProperty(FREE_STANDING_PROP); + isFreeStanding = (prop == null ? true : prop.booleanValue()); + scrollBarShadowColor = UIManager.getColor("ScrollBar.shadow"); + super.installDefaults(); + } + + /** + * Creates a property change listener for the delegate to use. This + * overrides the method to provide a custom listener for the + * {@link MetalLookAndFeel} that can handle the + * <code>JScrollBar.isFreeStanding</code> property. + * + * @return A property change listener. + */ + protected PropertyChangeListener createPropertyChangeListener() + { + return new MetalScrollBarPropertyChangeHandler(); + } + + /** + * Creates a new button to use as the control at the lower end of the + * {@link JScrollBar}. + * + * @param orientation the orientation of the button ({@link #NORTH}, + * {@link #SOUTH}, {@link #EAST} or {@link #WEST}). + * + * @return The button. + */ + protected JButton createDecreaseButton(int orientation) + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + scrollBarWidth = defaults.getInt("ScrollBar.width"); + decreaseButton = new MetalScrollButton(orientation, scrollBarWidth, + isFreeStanding); + return decreaseButton; + } - Object o = instances.get(component); - MetalScrollBarUI instance; - if (o == null) + /** + * Creates a new button to use as the control at the upper end of the + * {@link JScrollBar}. + * + * @param orientation the orientation of the button ({@link #NORTH}, + * {@link #SOUTH}, {@link #EAST} or {@link #WEST}). + * + * @return The button. + */ + protected JButton createIncreaseButton(int orientation) + { + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + scrollBarWidth = defaults.getInt("ScrollBar.width"); + increaseButton = new MetalScrollButton(orientation, scrollBarWidth, + isFreeStanding); + return increaseButton; + } + + /** + * Paints the track for the scrollbar. + * + * @param g the graphics device. + * @param c the component. + * @param trackBounds the track bounds. + */ + protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds) + { + g.setColor(MetalLookAndFeel.getControl()); + g.fillRect(trackBounds.x, trackBounds.y, trackBounds.width, + trackBounds.height); + if (scrollbar.getOrientation() == HORIZONTAL) + paintTrackHorizontal(g, c, trackBounds.x, trackBounds.y, + trackBounds.width, trackBounds.height); + else + paintTrackVertical(g, c, trackBounds.x, trackBounds.y, + trackBounds.width, trackBounds.height); + + } + + /** + * Paints the track for a horizontal scrollbar. + * + * @param g the graphics device. + * @param c the component. + * @param x the x-coordinate for the track bounds. + * @param y the y-coordinate for the track bounds. + * @param w the width for the track bounds. + * @param h the height for the track bounds. + */ + private void paintTrackHorizontal(Graphics g, JComponent c, + int x, int y, int w, int h) + { + if (c.isEnabled()) { - instance = new MetalScrollBarUI(); - instances.put(component, instance); + g.setColor(MetalLookAndFeel.getControlDarkShadow()); + g.drawLine(x, y, x, y + h - 1); + g.drawLine(x, y, x + w - 1, y); + g.drawLine(x + w - 1, y, x + w - 1, y + h - 1); + + g.setColor(scrollBarShadowColor); + g.drawLine(x + 1, y + 1, x + 1, y + h - 1); + g.drawLine(x + 1, y + 1, x + w - 2, y + 1); + + if (isFreeStanding) + { + g.setColor(MetalLookAndFeel.getControlDarkShadow()); + g.drawLine(x, y + h - 2, x + w - 1, y + h - 2); + g.setColor(scrollBarShadowColor); + g.drawLine(x, y + h - 1, x + w - 1, y + h - 1); + } } else - instance = (MetalScrollBarUI) o; - - return instance; + { + g.setColor(MetalLookAndFeel.getControlDisabled()); + if (isFreeStanding) + g.drawRect(x, y, w - 1, h - 1); + else + { + g.drawLine(x, y, x + w - 1, y); + g.drawLine(x, y, x, y + h - 1); + g.drawLine(x + w - 1, y, x + w - 1, y + h - 1); + } + } + } + + /** + * Paints the track for a vertical scrollbar. + * + * @param g the graphics device. + * @param c the component. + * @param x the x-coordinate for the track bounds. + * @param y the y-coordinate for the track bounds. + * @param w the width for the track bounds. + * @param h the height for the track bounds. + */ + private void paintTrackVertical(Graphics g, JComponent c, + int x, int y, int w, int h) + { + if (c.isEnabled()) + { + g.setColor(MetalLookAndFeel.getControlDarkShadow()); + g.drawLine(x, y, x, y + h - 1); + g.drawLine(x, y, x + w - 1, y); + g.drawLine(x, y + h - 1, x + w - 1, y + h - 1); + + g.setColor(scrollBarShadowColor); + g.drawLine(x + 1, y + 1, x + w - 1, y + 1); + g.drawLine(x + 1, y + 1, x + 1, y + h - 2); + + if (isFreeStanding) + { + g.setColor(MetalLookAndFeel.getControlDarkShadow()); + g.drawLine(x + w - 2, y, x + w - 2, y + h - 1); + g.setColor(MetalLookAndFeel.getControlHighlight()); + g.drawLine(x + w - 1, y, x + w - 1, y + h - 1); + } + } + else + { + g.setColor(MetalLookAndFeel.getControlDisabled()); + if (isFreeStanding) + g.drawRect(x, y, w - 1, h - 1); + else + { + g.drawLine(x, y, x + w - 1, y); + g.drawLine(x, y, x, y + h - 1); + g.drawLine(x, y + h - 1, x + w - 1, y + h - 1); + } + } } /** @@ -102,45 +342,139 @@ public class MetalScrollBarUI */ 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); + // a disabled scrollbar has no thumb in the metal look and feel + if (!c.isEnabled()) + return; + if (scrollbar.getOrientation() == HORIZONTAL) + paintThumbHorizontal(g, c, thumbBounds); + else + paintThumbVertical(g, c, thumbBounds); - // draw the outer dark line - g.setColor(thumbDarkShadowColor); - g.drawRect(thumbBounds.x, thumbBounds.y, thumbBounds.width - 1, - thumbBounds.height - 1); + // draw the pattern + MetalUtils.fillMetalPattern(c, g, thumbBounds.x + 3, thumbBounds.y + 3, + thumbBounds.width - 6, thumbBounds.height - 6, + thumbHighlightColor, thumbLightShadowColor); + } - // draw the inner light line + /** + * Paints the thumb for a horizontal scroll bar. + * + * @param g the graphics device. + * @param c the scroll bar component. + * @param thumbBounds the thumb bounds. + */ + private void paintThumbHorizontal(Graphics g, JComponent c, + Rectangle thumbBounds) + { + int x = thumbBounds.x; + int y = thumbBounds.y; + int w = thumbBounds.width; + int h = thumbBounds.height; + + // first we fill the background + g.setColor(thumbColor); + if (isFreeStanding) + g.fillRect(x, y, w, h - 1); + else + g.fillRect(x, y, w, h); + + // then draw the dark box + g.setColor(thumbLightShadowColor); + if (isFreeStanding) + g.drawRect(x, y, w - 1, h - 2); + else + { + g.drawLine(x, y, x + w - 1, y); + g.drawLine(x, y, x, y + h - 1); + g.drawLine(x + w - 1, y, x + w - 1, y + h -1); + } + + // then the highlight 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); - + if (isFreeStanding) + { + g.drawLine(x + 1, y + 1, x + w - 3, y + 1); + g.drawLine(x + 1, y + 1, x + 1, y + h - 3); + } + else + { + g.drawLine(x + 1, y + 1, x + w - 3, y + 1); + g.drawLine(x + 1, y + 1, x + 1, y + h - 1); + } + // 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); + g.drawLine(x + w, y + 1, x + w, y + h - 1); - // 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. + * Paints the thumb for a vertical scroll bar. + * + * @param g the graphics device. + * @param c the scroll bar component. + * @param thumbBounds the thumb bounds. + */ + private void paintThumbVertical(Graphics g, JComponent c, + Rectangle thumbBounds) + { + int x = thumbBounds.x; + int y = thumbBounds.y; + int w = thumbBounds.width; + int h = thumbBounds.height; + + // first we fill the background + g.setColor(thumbColor); + if (isFreeStanding) + g.fillRect(x, y, w - 1, h); + else + g.fillRect(x, y, w, h); + + // then draw the dark box + g.setColor(thumbLightShadowColor); + if (isFreeStanding) + g.drawRect(x, y, w - 2, h - 1); + else + { + g.drawLine(x, y, x + w - 1, y); + g.drawLine(x, y, x, y + h - 1); + g.drawLine(x, y + h - 1, x + w - 1, y + h - 1); + } + + // then the highlight + g.setColor(thumbHighlightColor); + if (isFreeStanding) + { + g.drawLine(x + 1, y + 1, x + w - 3, y + 1); + g.drawLine(x + 1, y + 1, x + 1, y + h - 3); + } + else + { + g.drawLine(x + 1, y + 1, x + w - 1, y + 1); + g.drawLine(x + 1, y + 1, x + 1, y + h - 3); + } + + // draw the shadow line + UIDefaults def = UIManager.getLookAndFeelDefaults(); + g.setColor(def.getColor("ScrollBar.shadow")); + g.drawLine(x + 1, y + h, x + w - 2, y + h); + } + + /** + * Returns the minimum thumb size. For a free standing scroll bar the + * minimum size is <code>17 x 17</code> pixels, whereas for a non free + * standing scroll bar the minimum size is <code>15 x 15</code> pixels. * * @return The minimum thumb size. */ protected Dimension getMinimumThumbSize() { - return MIN_THUMB_SIZE; + if (isFreeStanding) + return MIN_THUMB_SIZE_FREE_STANDING; + else + return MIN_THUMB_SIZE; } + } + diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalScrollButton.java b/libjava/classpath/javax/swing/plaf/metal/MetalScrollButton.java new file mode 100644 index 0000000..84f9cfe --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/MetalScrollButton.java @@ -0,0 +1,483 @@ +/* MetalScrollButton.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 java.awt.Rectangle; + +import javax.swing.SwingUtilities; +import javax.swing.plaf.basic.BasicArrowButton; + +/** + * A button used by the {@link MetalScrollBarUI}. The button appearance + * varies according to the button direction, whether or not it is part of a + * "free standing" scroll bar, and the current state of the button. + */ +public class MetalScrollButton extends BasicArrowButton +{ + + /** + * The maximum size for buttons. + * @see #getMaximumSize() + */ + private static Dimension maximumSize; + + /** The width of the button. */ + private int buttonWidth; + + /** + * A flag that indicates whether the button is part of a free standing + * scroll bar. This affects how the border is drawn. + */ + private boolean freeStanding; + + /** + * Creates a new button. + * + * @param direction the direction (this should be one of {@link #NORTH}, + * {@link #SOUTH}, {@link #EAST} and {@link #WEST}, but + * this is not enforced). + * @param width the button width. + * @param freeStanding a flag indicating whether the scroll button is free + * standing or not. + */ + public MetalScrollButton(int direction, int width, boolean freeStanding) + { + super(direction); + buttonWidth = width; + this.freeStanding = freeStanding; + } + + /** + * Returns the button width. + * + * @return The button width. + */ + public int getButtonWidth() + { + return buttonWidth; + } + + /** + * Sets the free standing flag. This controls how the button border is + * drawn. + * + * @param freeStanding the new value of the flag. + */ + public void setFreeStanding(boolean freeStanding) + { + this.freeStanding = freeStanding; + } + + /** + * Paints the button. + * + * @param g the graphics device. + */ + public void paint(Graphics g) + { + Rectangle bounds = SwingUtilities.getLocalBounds(this); + + // fill the background + if (getModel().isPressed()) + g.setColor(MetalLookAndFeel.getControlShadow()); + else + g.setColor(MetalLookAndFeel.getControl()); + g.fillRect(0, 0, bounds.width, bounds.height); + + paintArrow(g, bounds.width, bounds.height); + + // paint a border manually - I tried using a real (custom) Border + // but couldn't get it to stay set for the button, something was + // overwriting it... + if (freeStanding) + { + if (direction == WEST) + paintWestBorderFreeStanding(g, bounds.width, bounds.height); + else if (direction == EAST) + paintEastBorderFreeStanding(g, bounds.width, bounds.height); + else if (direction == SOUTH) + paintSouthBorderFreeStanding(g, bounds.width, bounds.height); + else // asume NORTH + paintNorthBorderFreeStanding(g, bounds.width, bounds.height); + } + else + { + if (direction == WEST) + paintWestBorder(g, bounds.width, bounds.height); + else if (direction == EAST) + paintEastBorder(g, bounds.width, bounds.height); + else if (direction == SOUTH) + paintSouthBorder(g, bounds.width, bounds.height); + else // asume NORTH + paintNorthBorder(g, bounds.width, bounds.height); + } + } + + private void paintArrow(Graphics g, int w, int h) + { + if (isEnabled()) + g.setColor(MetalLookAndFeel.getBlack()); + else + g.setColor(MetalLookAndFeel.getControlDisabled()); + + if (direction == SOUTH) + { + int x = w / 2; + int y = h / 2 + 2; + for (int i = 1; i < 5; i++) + g.drawLine(x - i, y - i, x + i - 1, y - i); + } + else if (direction == EAST) + { + int x = w / 2 + 2; + int y = h / 2; + for (int i = 1; i < 5; i++) + g.drawLine(x - i, y - i, x - i, y + i - 1); + } + else if (direction == WEST) + { + int x = w / 2 - 3; + int y = h / 2; + for (int i = 1; i < 5; i++) + g.drawLine(x + i, y - i, x + i, y + i - 1); + } + else // assume NORTH + { + int x = w / 2; + int y = h / 2 - 3; + for (int i = 1; i < 5; i++) + g.drawLine(x - i, y + i, x + i - 1, y + i); + } + } + /** + * Paints the border for a button with a {@link #NORTH} direction that + * belongs to a free standing scroll bar. + * + * @param g the graphics device. + * @param w the button width. + * @param h the button height. + */ + private void paintNorthBorderFreeStanding(Graphics g, int w, int h) + { + if (isEnabled()) + { + g.setColor(MetalLookAndFeel.getControlDarkShadow()); + g.drawLine(0, 0, w - 2, 0); + g.drawLine(0, 0, 0, h - 1); + g.drawLine(2, h - 1, w - 2, h - 1); + g.drawLine(w - 2, 2, w - 2, h - 1); + + g.setColor(MetalLookAndFeel.getControlHighlight()); + g.drawLine(1, 1, 1, h - 2); + g.drawLine(1, 1, w - 3, 1); + g.drawLine(w - 1, 1, w - 1, h - 1); + + g.setColor(MetalLookAndFeel.getControl()); + g.drawLine(1, h - 1, 1, h - 1); + g.drawLine(w - 2, 1, w - 2, 1); + } + else + { + g.setColor(MetalLookAndFeel.getControlDisabled()); + g.drawLine(0, 0, w - 1, 0); + g.drawLine(w - 1, 0, w - 1, h - 1); + g.drawLine(0, 0, 0, h - 1); + } + } + + /** + * Paints the border for a button with a {@link #SOUTH} direction that + * belongs to a free standing scroll bar. + * + * @param g the graphics device. + * @param w the button width. + * @param h the button height. + */ + private void paintSouthBorderFreeStanding(Graphics g, int w, int h) + { + if (isEnabled()) + { + g.setColor(MetalLookAndFeel.getControlDarkShadow()); + g.drawLine(0, 0, w - 2, 0); + g.drawLine(0, 0, 0, h - 1); + g.drawLine(2, h - 1, w - 2, h - 1); + g.drawLine(w - 2, 2, w - 2, h - 1); + + g.setColor(MetalLookAndFeel.getControlHighlight()); + g.drawLine(1, 1, 1, h - 1); + g.drawLine(1, 1, w - 1, 1); + g.drawLine(w - 1, 1, w - 1, h - 1); + + g.setColor(MetalLookAndFeel.getControl()); + g.drawLine(1, h - 1, 1, h - 1); + g.drawLine(w - 1, 1, w - 1, 1); + } + else + { + g.setColor(MetalLookAndFeel.getControlDisabled()); + g.drawLine(0, h - 1, w - 1, h - 1); + g.drawLine(w - 1, 0, w - 1, h - 1); + g.drawLine(0, 0, 0, h - 1); + } + } + + /** + * Paints the border for a button with an {@link #EAST} direction that + * belongs to a free standing scroll bar. + * + * @param g the graphics device. + * @param w the button width. + * @param h the button height. + */ + private void paintEastBorderFreeStanding(Graphics g, int w, int h) + { + if (isEnabled()) + { + g.setColor(MetalLookAndFeel.getControlDarkShadow()); + g.drawLine(0, 0, w - 2, 0); + g.drawLine(w - 2, 0, w - 2, h - 2); + g.drawLine(0, h - 2, w - 2, h - 2); + + g.setColor(MetalLookAndFeel.getControlHighlight()); + g.drawLine(0, 1, w - 1, 1); + g.drawLine(w - 1, 1, w - 1, h - 1); + g.drawLine(0, h - 1, w - 1, h - 1); + + g.setColor(MetalLookAndFeel.getControl()); + g.drawLine(w - 2, 1, w - 2, 1); + } + else + { + g.setColor(MetalLookAndFeel.getControlDisabled()); + g.drawLine(0, 0, w - 1, 0); + g.drawLine(w - 1, 0, w - 1, h - 1); + g.drawLine(0, h - 1, w - 1, h - 1); + } + } + + /** + * Paints the border for a button with a {@link #WEST} direction that + * belongs to a free standing scroll bar. + * + * @param g the graphics device. + * @param w the button width. + * @param h the button height. + */ + private void paintWestBorderFreeStanding(Graphics g, int w, int h) + { + if (isEnabled()) + { + g.setColor(MetalLookAndFeel.getControlDarkShadow()); + g.drawLine(0, 0, w - 1, 0); + g.drawLine(0, 0, 0, h - 2); + g.drawLine(0, h - 2, w - 1, h - 2); + + g.setColor(MetalLookAndFeel.getControlHighlight()); + g.drawLine(1, 1, w - 1, 1); + g.drawLine(1, 1, 1, h - 1); + g.drawLine(1, h - 1, w - 1, h - 1); + + g.setColor(MetalLookAndFeel.getControl()); + g.drawLine(1, h - 2, 1, h - 2); + } + else + { + g.setColor(MetalLookAndFeel.getControlDisabled()); + g.drawLine(0, 0, w - 1, 0); + g.drawLine(0, 0, 0, h - 1); + g.drawLine(0, h - 1, w - 1, h - 1); + } + } + + /** + * Paints the border for a button with a {@link #NORTH} direction that + * belongs to a scroll bar that is not free standing. + * + * @param g the graphics device. + * @param w the button width. + * @param h the button height. + */ + private void paintNorthBorder(Graphics g, int w, int h) + { + if (isEnabled()) + { + g.setColor(MetalLookAndFeel.getControlDarkShadow()); + g.drawLine(0, 0, 0, h - 1); + + g.setColor(MetalLookAndFeel.getControlHighlight()); + g.drawLine(1, 0, 1, h - 1); + g.drawLine(1, 0, w - 1, 0); + } + else + { + g.setColor(MetalLookAndFeel.getControlDisabled()); + g.drawLine(0, 0, 0, h - 1); + } + } + + /** + * Paints the border for a button with a {@link #SOUTH} direction that + * belongs to a scroll bar that is not free standing. + * + * @param g the graphics device. + * @param w the button width. + * @param h the button height. + */ + private void paintSouthBorder(Graphics g, int w, int h) + { + if (isEnabled()) + { + g.setColor(MetalLookAndFeel.getControlDarkShadow()); + g.drawLine(0, 0, 0, h - 1); + g.drawLine(0, h - 1, w - 1, h - 1); + + g.setColor(MetalLookAndFeel.getControlHighlight()); + g.drawLine(1, 0, 1, h - 1); + g.drawLine(1, 0, w - 1, 0); + + g.setColor(MetalLookAndFeel.getControl()); + g.drawLine(1, h - 1, 1, h - 1); + } + else + { + g.setColor(MetalLookAndFeel.getControlDisabled()); + g.drawLine(0, 0, 0, h - 1); + } + } + + /** + * Paints the border for a button with an {@link #EAST} direction that + * belongs to a scroll bar that is not free standing. + * + * @param g the graphics device. + * @param w the button width. + * @param h the button height. + */ + private void paintEastBorder(Graphics g, int w, int h) + { + if (isEnabled()) + { + g.setColor(MetalLookAndFeel.getControlDarkShadow()); + g.drawLine(0, 0, w - 1, 0); + g.drawLine(w - 1, 2, w - 1, h - 1); + g.setColor(MetalLookAndFeel.getControlHighlight()); + g.drawLine(0, 1, w - 2, 1); + g.drawLine(0, 1, 0, h - 1); + } + else + { + g.setColor(MetalLookAndFeel.getControlDisabled()); + g.drawLine(0, 0, w - 1, 0); + } + } + + /** + * Paints the border for a button with a {@link #WEST} direction that + * belongs to a scroll bar that is not free standing. + * + * @param g the graphics device. + * @param w the button width. + * @param h the button height. + */ + private void paintWestBorder(Graphics g, int w, int h) + { + Rectangle bounds = SwingUtilities.getLocalBounds(this); + if (isEnabled()) + { + g.setColor(MetalLookAndFeel.getControlDarkShadow()); + g.drawLine(0, 0, bounds.width - 1, 0); + g.setColor(MetalLookAndFeel.getControlHighlight()); + g.drawLine(0, 1, bounds.width - 1, 1); + g.drawLine(0, 1, 0, bounds.height - 1); + } + else + { + g.setColor(MetalLookAndFeel.getControlDisabled()); + g.drawLine(0, 0, bounds.width - 1, 0); + } + } + + /** + * Returns the preferred size for the button, which varies depending on + * the direction of the button and whether or not it is free standing. + * + * @return The preferred size. + */ + public Dimension getPreferredSize() + { + int adj = 1; + if (!freeStanding) + adj = 2; + + if (direction == EAST) + return new Dimension(buttonWidth - adj, buttonWidth); + else if (direction == WEST) + return new Dimension(buttonWidth - 2, buttonWidth); + else if (direction == SOUTH) + return new Dimension(buttonWidth, buttonWidth - adj); + else // assume NORTH + return new Dimension(buttonWidth, buttonWidth - 2); + } + + /** + * Returns the minimum size for the button. + * + * @return The minimum size for the button. + */ + public Dimension getMinimumSize() + { + return getPreferredSize(); + } + + /** + * Returns the maximum size for the button. + * + * @return <code>Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE)</code>. + */ + public Dimension getMaximumSize() + { + if (maximumSize == null) + maximumSize = new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); + return maximumSize; + } + +} diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalScrollPaneUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalScrollPaneUI.java index 3e1198b..d5bf175 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalScrollPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalScrollPaneUI.java @@ -39,19 +39,18 @@ exception statement from your version. */ package javax.swing.plaf.metal; import javax.swing.JComponent; +import javax.swing.JScrollPane; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicScrollPaneUI; +/** + * A UI delegate for the {@link JScrollPane} component. + */ 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. + * Constructs a new instance of <code>MetalScrollPaneUI</code>. */ public MetalScrollPaneUI() { @@ -59,16 +58,14 @@ public class MetalScrollPaneUI } /** - * Returns an instance of MetalScrollPaneUI. + * Returns a shared instance of <code>MetalScrollPaneUI</code>. * * @param component the component for which we return an UI instance * - * @return an instance of MetalScrollPaneUI + * @return A shared instance of <code>MetalScrollPaneUI</code>. */ public static ComponentUI createUI(JComponent component) { - if (instance == null) - instance = new MetalScrollPaneUI(); - return instance; + return new MetalScrollPaneUI(); } } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalSeparatorUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalSeparatorUI.java index 6e78ccb..1d48e9b 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalSeparatorUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalSeparatorUI.java @@ -38,10 +38,20 @@ exception statement from your version. */ package javax.swing.plaf.metal; +import java.awt.Color; +import java.awt.Graphics; +import java.awt.Rectangle; + import javax.swing.JComponent; +import javax.swing.JSeparator; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicSeparatorUI; +/** + * A UI delegate for the {@link JSeparator} component. + */ public class MetalSeparatorUI extends BasicSeparatorUI { @@ -51,7 +61,7 @@ public class MetalSeparatorUI private static MetalSeparatorUI instance = null; /** - * Constructs a new instance of MetalSeparatorUI. + * Constructs a new instance of <code>MetalSeparatorUI</code>. */ public MetalSeparatorUI() { @@ -59,11 +69,11 @@ public class MetalSeparatorUI } /** - * Returns an instance of MetalSeparatorUI. + * Returns a shared instance of <code>MetalSeparatorUI</code>. * * @param component the component for which we return an UI instance * - * @return an instance of MetalSeparatorUI + * @return A shared instance of <code>MetalSeparatorUI</code>. */ public static ComponentUI createUI(JComponent component) { @@ -71,4 +81,51 @@ public class MetalSeparatorUI instance = new MetalSeparatorUI(); return instance; } + + /** + * The separator is made of two lines. The top line will be + * the Metal theme color separatorForeground (or left line if it's vertical). + * The bottom or right line will be the Metal theme color + * separatorBackground. + * 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(); + Color c1 = UIManager.getColor("Separator.foreground"); + Color c2 = UIManager.getColor("Separator.background"); + JSeparator s; + if (c instanceof JSeparator) + s = (JSeparator) c; + else + return; + + if (s.getOrientation() == JSeparator.HORIZONTAL) + { + int midAB = r.height / 2; + g.setColor(c1); + g.drawLine(r.x, r.y + midAB - 1, r.x + r.width, r.y + midAB - 1); + + g.setColor(c2); + g.fillRect(r.x, r.y + midAB, r.x + r.width, r.y + midAB); + } + else + { + int midAD = r.height / 2 + r.y; + g.setColor(c1); + g.drawLine(r.x, r.y, r.x, r.y + r.height); + + g.setColor(c2); + g.fillRect(r.x + midAD, r.y + r.height, r.x + midAD, r.y + r.height); + } + g.setColor(saved); + } } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalSliderUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalSliderUI.java index 4b52c4b..08fb99d 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalSliderUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalSliderUI.java @@ -42,8 +42,8 @@ import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Rectangle; +import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; -import java.util.HashMap; import javax.swing.Icon; import javax.swing.JComponent; @@ -56,16 +56,59 @@ import javax.swing.plaf.basic.BasicSliderUI; /** * A UI delegate for the {@link JSlider} component. */ -public class MetalSliderUI - extends BasicSliderUI +public class MetalSliderUI extends BasicSliderUI { - // TODO: find a use for this + /** + * A property change handler that updates the rendered component in response + * to specific property change events. This custom handler is used to + * intercept the "JSlider.isFilled" property, which is only recognised by + * the {@link MetalLookAndFeel}. + */ + protected class MetalPropertyListener + extends BasicSliderUI.PropertyChangeHandler + { + /** + * Creates a new listener. + */ + protected MetalPropertyListener() + { + // Nothing to do here. + } + + /** + * Handles property change events. Events with the name "JSlider.isFilled" + * are handled here, and other events are passed to the superclass. + * + * @param e the property change event. + */ + public void propertyChange(PropertyChangeEvent e) + { + if (e.getPropertyName().equals(SLIDER_FILL)) + { + Boolean b = (Boolean) e.getNewValue(); + if (b == null) + filledSlider = false; + else + filledSlider = b.booleanValue(); + } + else + super.propertyChange(e); + } + } + + /** The thumb color (unused, because an icon is used to draw the thumb). */ protected static Color thumbColor; - // TODO: find a use for this + /** + * The highlight color used for drawing the track rect when the slider is + * enabled. + */ protected static Color highlightColor; - // TODO: find a use for this + /** + * The shadow color used for drawing the track rect when the slider is + * enabled. + */ protected static Color darkShadowColor; /** The track width. */ @@ -85,17 +128,14 @@ public class MetalSliderUI /** The gap between the track and the tick marks. */ protected final int TICK_BUFFER = 4; + /** A key to look up the filledSlider setting in the {@link UIManager}. */ + protected final String SLIDER_FILL = "JSlider.isFilled"; + /** * A flag that controls whether or not the track is filled up to the value * of the slider. */ protected boolean filledSlider; - - /** A key to look up the filledSlider setting in the {@link UIManager}. */ - protected final String SLIDER_FILL = "JSlider.isFilled"; - - /** The UI instances for MetalSliderUIs */ - private static HashMap instances; /** * Constructs a new instance. @@ -104,33 +144,27 @@ public class MetalSliderUI { super(null); filledSlider = UIManager.getBoolean(SLIDER_FILL); + darkShadowColor = MetalLookAndFeel.getControlDarkShadow(); + highlightColor = MetalLookAndFeel.getControlHighlight(); } /** - * Returns an instance of MetalSliderUI. + * Returns a new instance of <code>MetalSliderUI</code>. * - * @param component the component for which we return an UI instance + * @param component the component (ignored). * - * @return an instance of MetalSliderUI + * @return A new instance of <code>MetalSliderUI</code>. */ 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; + return new MetalSliderUI(); } + /** + * Installs the default for this UI delegate in the supplied component. + * + * @param c the component. + */ public void installUI(JComponent c) { super.installUI(c); @@ -140,6 +174,18 @@ public class MetalSliderUI } /** + * Creates a property change listener for the slider. + * + * @param slider the slider. + * + * @return A new instance of {@link MetalPropertyListener}. + */ + protected PropertyChangeListener createPropertyChangeListener(JSlider slider) + { + return new MetalPropertyListener(); + } + + /** * Paints the thumb icon for the slider. * * @param g the graphics device. @@ -153,46 +199,79 @@ public class MetalSliderUI } /** - * Creates a property change listener for the slider. - * - * @param slider the slider. - */ - protected PropertyChangeListener createPropertyChangeListener(JSlider slider) - { - // TODO: try to figure out why it might be necessary to override this - // method as is done in Sun's implementation - return super.createPropertyChangeListener(slider); - } - - /** * Paints the track along which the thumb control moves. * * @param g the graphics device. */ public void paintTrack(Graphics g) { + Color shadowColor = MetalLookAndFeel.getControlShadow(); if (slider.getOrientation() == JSlider.HORIZONTAL) - { - if (filledSlider) { - // TODO: fill the track + int trackX = trackRect.x; + int trackY = trackRect.y + (trackRect.height - getTrackWidth()) / 2; + int trackW = trackRect.width - 1; + int trackH = getTrackWidth(); + + // draw border + if (slider.isEnabled()) + BasicGraphicsUtils.drawEtchedRect(g, trackX, trackY, trackW, trackH, + darkShadowColor, shadowColor, darkShadowColor, highlightColor); + else + { + g.setColor(MetalLookAndFeel.getControlShadow()); + g.drawRect(trackX, trackY, trackW - 2, trackH - 2); + } + + // fill track (if required) + if (filledSlider) + { + int xPos = xPositionForValue(slider.getValue()); + int x = (slider.getInverted() ? xPos : trackRect.x); + int w = (slider.getInverted() ? trackX + trackW - xPos + : xPos - trackRect.x); + g.setColor(MetalLookAndFeel.getControlShadow()); + g.fillRect(x + 1, trackY + 1, w - 3, getTrackWidth() - 3); + if (slider.isEnabled()) + { + g.setColor(MetalLookAndFeel.getControl()); + g.drawLine(x + 1, trackY + 1, x + w - 3, trackY + 1); + g.drawLine(x + 1, trackY + 1, x + 1, + trackY + getTrackWidth() - 3); + } + } } - BasicGraphicsUtils.drawEtchedRect(g, trackRect.x, trackRect.y - + (trackRect.height - getTrackWidth()) / 2, trackRect.width - 1, - getTrackWidth(), Color.darkGray, Color.gray, Color.darkGray, - Color.white); - } else - { - if (filledSlider) { - // TODO: fill the track + int trackX = trackRect.x + (trackRect.width - getTrackWidth()) / 2; + int trackY = trackRect.y; + int trackW = getTrackWidth(); + int trackH = trackRect.height - 1; + if (slider.isEnabled()) + BasicGraphicsUtils.drawEtchedRect(g, trackX, trackY, trackW, trackH, + darkShadowColor, shadowColor, darkShadowColor, highlightColor); + else + { + g.setColor(MetalLookAndFeel.getControlShadow()); + g.drawRect(trackX, trackY, trackW - 2, trackH - 2); + } + + if (filledSlider) + { + int yPos = yPositionForValue(slider.getValue()); + int y = (slider.getInverted() ? trackY : yPos); + int h = (slider.getInverted() ? yPos - trackY + : trackY + trackH - yPos); + g.setColor(MetalLookAndFeel.getControlShadow()); + g.fillRect(trackX + 1, y + 1, getTrackWidth() - 3, h - 3); + if (slider.isEnabled()) + { + g.setColor(MetalLookAndFeel.getControl()); + g.drawLine(trackX + 1, y + 1, trackX + trackW - 3, y + 1); + g.drawLine(trackX + 1, y + 1, trackX + 1, y + h - 3); + } + } } - BasicGraphicsUtils.drawEtchedRect(g, trackRect.x + (trackRect.width - - getTrackWidth()) / 2, trackRect.y, getTrackWidth(), - trackRect.height - 1, Color.darkGray, Color.gray, Color.darkGray, - Color.white); - } } /** @@ -262,12 +341,13 @@ public class MetalSliderUI */ protected int getThumbOverhang() { - // TODO: figure out what this is used for + // FIXME: for what might this method be used? return 0; } protected void scrollDueToClickInTrack(int dir) { + // FIXME: for what might this method be overridden? super.scrollDueToClickInTrack(dir); } @@ -283,8 +363,10 @@ public class MetalSliderUI { // Note the incoming 'g' has a translation in place to get us to the // start of the tick rect already... - // TODO: get color from UIManager... - g.setColor(new Color(153, 153, 204)); + if (slider.isEnabled()) + g.setColor(MetalLookAndFeel.getPrimaryControlShadow()); + else + g.setColor(MetalLookAndFeel.getControlDisabled()); g.drawLine(x, TICK_BUFFER, x, TICK_BUFFER + tickLength / 2); } @@ -300,8 +382,10 @@ public class MetalSliderUI { // Note the incoming 'g' has a translation in place to get us to the // start of the tick rect already... - // TODO: get color from UIManager... - g.setColor(new Color(153, 153, 204)); + if (slider.isEnabled()) + g.setColor(MetalLookAndFeel.getPrimaryControlShadow()); + else + g.setColor(MetalLookAndFeel.getControlDisabled()); g.drawLine(x, TICK_BUFFER, x, TICK_BUFFER + tickLength); } @@ -317,8 +401,10 @@ public class MetalSliderUI { // Note the incoming 'g' has a translation in place to get us to the // start of the tick rect already... - // TODO: get color from UIManager... - g.setColor(new Color(153, 153, 204)); + if (slider.isEnabled()) + g.setColor(MetalLookAndFeel.getPrimaryControlShadow()); + else + g.setColor(MetalLookAndFeel.getControlDisabled()); g.drawLine(TICK_BUFFER - 1, y, TICK_BUFFER - 1 + tickLength / 2, y); } @@ -334,8 +420,10 @@ public class MetalSliderUI { // Note the incoming 'g' has a translation in place to get us to the // start of the tick rect already... - // TODO: get color from UIManager... - g.setColor(new Color(153, 153, 204)); + if (slider.isEnabled()) + g.setColor(MetalLookAndFeel.getPrimaryControlShadow()); + else + g.setColor(MetalLookAndFeel.getControlDisabled()); g.drawLine(TICK_BUFFER - 1, y, TICK_BUFFER - 1 + tickLength, y); } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneDivider.java b/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneDivider.java index 60e9c05..016e095 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneDivider.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneDivider.java @@ -78,7 +78,7 @@ class MetalSplitPaneDivider extends BasicSplitPaneDivider { //super.paint(g); Dimension s = getSize(); - MetalUtils.fillMetalPattern(g, 2, 2, s.width - 4, s.height - 4, + MetalUtils.fillMetalPattern(splitPane, 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 index b7ea898..b39fb23 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalSplitPaneUI.java @@ -39,24 +39,22 @@ 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.JSplitPane; 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; +import javax.swing.plaf.basic.BasicSplitPaneUI; -public class MetalSplitPaneUI - extends BasicSplitPaneUI +/** + * A UI delegate for the {@link JSplitPane} component. + */ +public class MetalSplitPaneUI extends BasicSplitPaneUI { - - /** The UI instances for MetalSplitPaneUIs */ - private static HashMap instances; - /** - * Constructs a new instance of MetalSplitPaneUI. + * Constructs a new instance of <code>MetalSplitPaneUI</code>. */ public MetalSplitPaneUI() { @@ -64,28 +62,15 @@ public class MetalSplitPaneUI } /** - * Returns an instance of MetalSplitPaneUI. + * Returns a new instance of <code>MetalSplitPaneUI</code>. * * @param component the component for which we return an UI instance * - * @return an instance of MetalSplitPaneUI + * @return A new instance of <code>MetalSplitPaneUI</code>. */ 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; + return new MetalSplitPaneUI(); } /** diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java index 1b5fe14..b1e02c7 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalTabbedPaneUI.java @@ -40,7 +40,6 @@ package javax.swing.plaf.metal; import java.awt.Graphics; import java.awt.LayoutManager; -import java.util.HashMap; import javax.swing.JComponent; import javax.swing.JTabbedPane; @@ -48,11 +47,9 @@ import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicTabbedPaneUI; /** - * A UI delegate used for the {@link JTabbedPane} component in the - * {@link MetalLookAndFeel}. + * A UI delegate for the {@link JTabbedPane} component. */ -public class MetalTabbedPaneUI - extends BasicTabbedPaneUI +public class MetalTabbedPaneUI extends BasicTabbedPaneUI { /** @@ -65,13 +62,14 @@ public class MetalTabbedPaneUI * public for compatibility. */ public class TabbedPaneLayout - extends BasicTabbedPaneUI.TabbedPaneLayout + extends BasicTabbedPaneUI.TabbedPaneLayout { /** * Creates a new instance of the layout manager. */ public TabbedPaneLayout() { + // Nothing to do here. } /** @@ -102,9 +100,6 @@ public class MetalTabbedPaneUI } } - /** The shared UI instance for JTabbedPanes. */ - private static HashMap instances = null; - /** * Constructs a new instance of MetalTabbedPaneUI. */ @@ -122,20 +117,7 @@ public class 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; + return new MetalTabbedPaneUI(); } /** @@ -145,7 +127,7 @@ public class MetalTabbedPaneUI */ protected LayoutManager createLayoutManager() { - return new TabbedPaneLayout(); + return super.createLayoutManager(); } /** diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalTextFieldUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalTextFieldUI.java index d6e50e1..6984dae 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalTextFieldUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalTextFieldUI.java @@ -38,19 +38,16 @@ exception statement from your version. */ package javax.swing.plaf.metal; -import java.util.HashMap; - import javax.swing.JComponent; +import javax.swing.JTextField; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicTextFieldUI; -public class MetalTextFieldUI - extends BasicTextFieldUI +/** + * A UI delegate for the {@link JTextField} component. + */ +public class MetalTextFieldUI extends BasicTextFieldUI { - - /** The UI instances for MetalTextFieldUIs */ - private static HashMap instances = null; - /** * Constructs a new instance of MetalTextFieldUI. */ @@ -60,27 +57,14 @@ public class MetalTextFieldUI } /** - * Returns an instance of MetalTextFieldUI. + * Returns a new instance of <code>MetalTextFieldUI</code>. * * @param component the component for which we return an UI instance * - * @return an instance of MetalTextFieldUI + * @return A new instance of <code>MetalTextFieldUI</code>. */ 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; + return new MetalTextFieldUI(); } } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalToggleButtonUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalToggleButtonUI.java index be6d0c3..46a19bd 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalToggleButtonUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalToggleButtonUI.java @@ -39,13 +39,24 @@ exception statement from your version. */ package javax.swing.plaf.metal; import java.awt.Color; +import java.awt.Font; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.Rectangle; +import javax.swing.AbstractButton; import javax.swing.JComponent; +import javax.swing.JToggleButton; +import javax.swing.SwingUtilities; import javax.swing.UIDefaults; import javax.swing.UIManager; import javax.swing.plaf.ComponentUI; +import javax.swing.plaf.basic.BasicButtonUI; import javax.swing.plaf.basic.BasicToggleButtonUI; +/** + * A UI delegate for the {@link JToggleButton} component. + */ public class MetalToggleButtonUI extends BasicToggleButtonUI { @@ -59,21 +70,26 @@ public class MetalToggleButtonUI /** The color for disabled button labels. */ protected Color disabledTextColor; - /** The shared UI instance for MetalToggleButtonUIs */ - private static MetalToggleButtonUI instance = null; + /** + * Returns a new instance of <code>MetalToggleButtonUI</code>. + * + * @param component the component for which we return an UI instance + * + * @return A new instance of <code>MetalToggleButtonUI</code>. + */ + public static ComponentUI createUI(JComponent component) + { + return new MetalToggleButtonUI(); + } /** - * Constructs a new instance of MetalToggleButtonUI. + * Constructs a new instance of <code>MetalToggleButtonUI</code>. */ public MetalToggleButtonUI() { super(); - focusColor = getFocusColor(); - selectColor = getSelectColor(); - disabledTextColor = getDisabledTextColor(); } - /** * Returns the color for the focus border. * @@ -81,8 +97,7 @@ public class MetalToggleButtonUI */ protected Color getFocusColor() { - UIDefaults def = UIManager.getLookAndFeelDefaults(); - return def.getColor(getPropertyPrefix() + ".focus"); + return focusColor; } /** @@ -92,32 +107,98 @@ public class MetalToggleButtonUI */ protected Color getSelectColor() { - UIDefaults def = UIManager.getLookAndFeelDefaults(); - return def.getColor(getPropertyPrefix() + ".select"); + return selectColor; } /** - * Returns the color for the text label of disabled buttons. + * Returns the color for the text label of disabled buttons. The value + * is initialised in the {@link #installDefaults(AbstractButton)} method + * by reading the <code>ToggleButton.disabledText</code> item from the UI + * defaults. * - * @return the color for the text label of disabled buttons + * @return The color for the text label of disabled buttons. */ protected Color getDisabledTextColor() { - UIDefaults def = UIManager.getLookAndFeelDefaults(); - return def.getColor(getPropertyPrefix() + ".disabledText"); + return disabledTextColor; } /** - * Returns an instance of MetalToggleButtonUI. - * - * @param component the component for which we return an UI instance - * - * @return an instance of MetalToggleButtonUI + * Updates the button with the defaults for this look and feel. + * + * @param b the button. */ - public static ComponentUI createUI(JComponent component) + public void installDefaults(AbstractButton b) + { + super.installDefaults(b); + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + focusColor = defaults.getColor(getPropertyPrefix() + "focus"); + selectColor = defaults.getColor(getPropertyPrefix() + "select"); + disabledTextColor = defaults.getColor(getPropertyPrefix() + "disabledText"); + } + + /** + * Paints the button background when it is pressed/selected. + * + * @param g the graphics device. + * @param b the button. + */ + protected void paintButtonPressed(Graphics g, AbstractButton b) + { + if (b.isContentAreaFilled() && b.isOpaque()) + { + Color saved = g.getColor(); + Rectangle bounds = SwingUtilities.getLocalBounds(b); + g.setColor(selectColor); + g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height); + g.setColor(saved); + } + } + + /** + * Paints the text for the button. + * + * @param g the graphics device. + * @param c the component. + * @param textRect the bounds for the text. + * @param text the text. + * + * @deprecated 1.4 Use {@link BasicButtonUI#paintText(java.awt.Graphics, + * javax.swing.AbstractButton, java.awt.Rectangle, java.lang.String)}. + */ + protected void paintText(Graphics g, JComponent c, Rectangle textRect, + String text) + { + Font savedFont = g.getFont(); + Color savedColor = g.getColor(); + g.setFont(c.getFont()); + if (c.isEnabled()) + g.setColor(c.getForeground()); + else + g.setColor(disabledTextColor); + FontMetrics fm = g.getFontMetrics(c.getFont()); + int ascent = fm.getAscent(); + g.drawString(text, textRect.x, textRect.y + ascent); + g.setFont(savedFont); + g.setColor(savedColor); + } + + /** + * Draws the focus highlight around the text and icon. + * + * @param g the graphics device. + * @param b the button. + */ + protected void paintFocus(Graphics g, AbstractButton b, Rectangle viewRect, + Rectangle textRect, Rectangle iconRect) { - if (instance == null) - instance = new MetalToggleButtonUI(); - return instance; + if (!b.hasFocus()) + return; + Color saved = g.getColor(); + g.setColor(focusColor); + Rectangle fr = iconRect.union(textRect); + g.drawRect(fr.x - 1, fr.y - 1, fr.width + 1, fr.height + 1); + g.setColor(saved); } + } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalToolBarUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalToolBarUI.java index 39af001..c5ca913 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalToolBarUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalToolBarUI.java @@ -38,20 +38,73 @@ exception statement from your version. */ package javax.swing.plaf.metal; +import java.awt.event.ContainerListener; +import java.beans.PropertyChangeListener; + import javax.swing.JComponent; +import javax.swing.JToolBar; +import javax.swing.border.Border; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicToolBarUI; -public class MetalToolBarUI - extends BasicToolBarUI +/** + * A UI delegate for the {@link JToolBar} component. + */ +public class MetalToolBarUI extends BasicToolBarUI { + + /** + * A listener (no longer used) that responds when components are added to or + * removed from the {@link JToolBar}. The required behaviour is now + * handled in the super class. + * + * @see MetalToolBarUI#createContainerListener() + */ + protected class MetalContainerListener + extends BasicToolBarUI.ToolBarContListener + { + /** + * Creates a new instance. + */ + protected MetalContainerListener() + { + // Nothing to do here. + } + } - // FIXME: maybe replace by a Map of instances when this becomes stateful - /** The shared UI instance for MetalToolBarUIs */ - private static MetalToolBarUI instance = null; + /** + * A listener (no longer used) that responds to property change events in a + * {@link JToolBar} component. The required behaviour is now handled in the + * super class. + * + * @see MetalToolBarUI#createRolloverListener() + */ + protected class MetalRolloverListener + extends BasicToolBarUI.PropertyListener + { + /** + * Creates a new instance. + */ + protected MetalRolloverListener() + { + // Nothing to do here. + } + } + + /** + * The container listener (an implementation specific field, according to the + * spec, and not used in GNU Classpath). + */ + protected ContainerListener contListener; + + /** + * The rollover listener (an implementation specific field, according to the + * spec, and not used in GNU Classpath). + */ + protected PropertyChangeListener rolloverListener; /** - * Constructs a new instance of MetalToolBarUI. + * Creates a new instance of this UI delegate. */ public MetalToolBarUI() { @@ -59,16 +112,51 @@ public class MetalToolBarUI } /** - * Returns an instance of MetalToolBarUI. + * Returns a new instance of <code>MetalToolBarUI</code>. * - * @param component the component for which we return an UI instance + * @param component the component for which we return an UI instance * - * @return an instance of MetalToolBarUI + * @return A new instance of <code>MetalToolBarUI</code>. */ public static ComponentUI createUI(JComponent component) { - if (instance == null) - instance = new MetalToolBarUI(); - return instance; + return new MetalToolBarUI(); + } + + /** + * Returns <code>null</code> as permitted by recent versions of the API + * specification. Originally it seems this method returned a new instance of + * {@link MetalRolloverListener}, but this is now redundant. + * + * @return <code>null</code>. + */ + protected PropertyChangeListener createRolloverListener() + { + return null; + } + + /** + * Returns <code>null</code> as permitted by recent versions of the API + * specification. Originally it seems this method returned a new instance of + * {@link MetalContainerListener}, but this is now redundant. + * + * @return <code>null</code>. + */ + protected ContainerListener createContainerListener() + { + return null; + } + + /** + * Returns a border with no rollover effect for buttons in the tool bar. + * + * @return A border. + * + * @see MetalBorders#getToolbarButtonBorder() + */ + protected Border createNonRolloverBorder() + { + return MetalBorders.getToolbarButtonBorder(); } + } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalToolTipUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalToolTipUI.java index c88b653..5085d17 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalToolTipUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalToolTipUI.java @@ -38,32 +38,92 @@ exception statement from your version. */ package javax.swing.plaf.metal; +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.awt.Toolkit; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; + +import javax.swing.AbstractButton; import javax.swing.JComponent; +import javax.swing.JMenuItem; +import javax.swing.JToolTip; +import javax.swing.KeyStroke; +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.UIResource; import javax.swing.plaf.basic.BasicToolTipUI; +/** + * A UI delegate for the {@link JToolTip} component. + */ public class MetalToolTipUI extends BasicToolTipUI { + /** + * The amount of space between the tool tip text and the accelerator + * description (if visible). + */ + public static final int padSpaceBetweenStrings = 12; - // FIXME: maybe replace by a Map of instances when this becomes stateful - /** The shared UI instance for MetalToolTipUIs */ + /** The shared UI instance. */ private static MetalToolTipUI instance = null; - + + /** A flag controlling the visibility of the accelerator (if there is one). */ + private boolean isAcceleratorHidden; + + /** A string representing the accelerator key for the component. */ + private String acceleratorString; + + /** + * The delimiter for the accelerator string. + */ + private String acceleratorDelimiter; + + /** The font for the accelerator string. */ + private Font acceleratorFont; + + /** The color for the accelerator string. */ + private Color acceleratorForeground; + + /** The active border. */ + private Border activeBorder; + + /** The inactive border. */ + private Border inactiveBorder; + /** - * Constructs a new instance of MetalToolTipUI. + * Constructs a new instance of <code>MetalToolTipUI</code>. */ public MetalToolTipUI() { super(); + UIDefaults defaults = UIManager.getLookAndFeelDefaults(); + activeBorder = defaults.getBorder("ToolTip.border"); + inactiveBorder = defaults.getBorder("ToolTip.borderInactive"); + isAcceleratorHidden = defaults.getBoolean("ToolTip.hideAccelerator"); + acceleratorFont = defaults.getFont("MenuItem.acceleratorFont"); + acceleratorForeground = defaults.getColor("MenuItem.acceleratorForeground"); + acceleratorDelimiter = defaults.getString("MenuItem.acceleratorDelimiter"); } /** - * Returns an instance of MetalToolTipUI. + * Returns a shared instance of the <code>MetalToolTipUI</code> class. + * Although this UI delegate does maintain state information, there is never + * more than one tool tip visible, so it is OK to use a shared instance. * - * @param component the component for which we return an UI instance + * @param component the component (a {@link JToolTip}). * - * @return an instance of MetalToolTipUI + * @return A shared instance of the <code>MetalToolTipUI</code> class. */ public static ComponentUI createUI(JComponent component) { @@ -71,4 +131,202 @@ public class MetalToolTipUI instance = new MetalToolTipUI(); return instance; } + + /** + * Returns a string representing the accelerator key (if there is one) for + * the component that the tool tip belongs to. + * + * @return A string representing the accelerator key. + */ + public String getAcceleratorString() + { + return acceleratorString; + } + + /** + * Installs the UI for the specified component (a {@link JToolTip}). + * + * @param c the {@link JToolTip} component. + */ + public void installUI(JComponent c) + { + super.installUI(c); + Border existingBorder = c.getBorder(); + if (existingBorder == null || existingBorder instanceof UIResource) + { + if (c.isEnabled()) + c.setBorder(activeBorder); + else + c.setBorder(inactiveBorder); + } + } + + /** + * Clears the defaults set in {@link #installUI(JComponent)}. + * + * @param c the component. + */ + public void uninstallUI(JComponent c) + { + super.uninstallUI(c); + if (c.getBorder() instanceof UIResource) + c.setBorder(null); + } + + /** + * Returns <code>true</code> if the accelerator string is hidden, and + * <code>false</code> otherwise. This setting is controlled by the + * <code>ToolTip.hideAccelerator</code> entry in the UI defaults table. + * + * @return A boolean. + */ + protected boolean isAcceleratorHidden() + { + return isAcceleratorHidden; + } + + /** + * Returns the preferred size for the {@link JToolTip} component. + * + * @param c the component (a {@link JToolTip}). + * + * @return The preferred size. + */ + public Dimension getPreferredSize(JComponent c) + { + if (isAcceleratorHidden()) + return super.getPreferredSize(c); + else + { + Insets insets = c.getInsets(); + JToolTip tt = (JToolTip) c; + String tipText = tt.getTipText(); + if (tipText != null) + { + FontMetrics fm = c.getFontMetrics(c.getFont()); + int prefH = fm.getHeight() + insets.top + insets.bottom; + int prefW = fm.stringWidth(tipText) + insets.left + insets.right; + + // this seems to be the first opportunity we have to get the + // accelerator string from the component (if it has one) + acceleratorString = fetchAcceleratorString(c); + if (acceleratorString != null) + { + prefW += padSpaceBetweenStrings; + fm = c.getFontMetrics(acceleratorFont); + prefW += fm.stringWidth(acceleratorString); + } + return new Dimension(prefW, prefH); + } + else return new Dimension(0, 0); + } + } + + /** + * Paints the tool tip. + * + * @param g the graphics context. + * @param c the {@link JToolTip} component. + */ + public void paint(Graphics g, JComponent c) + { + JToolTip tip = (JToolTip) c; + + String text = tip.getTipText(); + Toolkit t = tip.getToolkit(); + if (text == null) + return; + + Rectangle vr = new Rectangle(); + vr = SwingUtilities.calculateInnerArea(tip, vr); + Rectangle ir = new Rectangle(); + Rectangle tr = new Rectangle(); + FontMetrics fm = t.getFontMetrics(tip.getFont()); + int ascent = fm.getAscent(); + SwingUtilities.layoutCompoundLabel(tip, fm, text, null, + SwingConstants.CENTER, SwingConstants.LEFT, + SwingConstants.CENTER, SwingConstants.CENTER, vr, ir, tr, 0); + Color saved = g.getColor(); + g.setColor(Color.BLACK); + + g.drawString(text, vr.x, vr.y + ascent); + + // paint accelerator + if (acceleratorString != null) + { + g.setFont(acceleratorFont); + g.setColor(acceleratorForeground); + fm = t.getFontMetrics(acceleratorFont); + int width = fm.stringWidth(acceleratorString); + g.drawString(acceleratorString, vr.x + vr.width - width - padSpaceBetweenStrings/2, + vr.y + vr.height - fm.getDescent()); + } + + g.setColor(saved); + } + + /** + * Returns a string representing the accelerator for the component, or + * <code>null</code> if the component has no accelerator. + * + * @param c the component. + * + * @return A string representing the accelerator (possibly + * <code>null</code>). + */ + private String fetchAcceleratorString(JComponent c) + { + String result = null; + if (c instanceof JToolTip) + { + JToolTip toolTip = (JToolTip) c; + JComponent component = toolTip.getComponent(); + KeyStroke ks = null; + int mne = 0; + if (component instanceof JMenuItem) + { + JMenuItem item = (JMenuItem) component; + ks = item.getAccelerator(); + if (ks == null) + mne = item.getMnemonic(); + } + else if (component instanceof AbstractButton) + { + AbstractButton button = (AbstractButton) component; + mne = button.getMnemonic(); + } + if (mne > 0) + ks = KeyStroke.getKeyStroke(Character.toUpperCase((char) mne), + InputEvent.ALT_MASK, false); + if (ks != null) + result = acceleratorToString(ks); + } + return result; + } + + /** + * Returns a string representing an accelerator. + * + * @param accelerator the accelerator (<code>null</code> not permitted). + * + * @return A string representing an accelerator. + */ + private String acceleratorToString(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); + } + } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalTreeUI.java b/libjava/classpath/javax/swing/plaf/metal/MetalTreeUI.java index 8d16f74..0ffa0d1 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalTreeUI.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalTreeUI.java @@ -38,21 +38,50 @@ exception statement from your version. */ package javax.swing.plaf.metal; -import java.util.HashMap; +import java.awt.Graphics; +import java.awt.Insets; +import java.awt.Rectangle; +import java.awt.event.ComponentListener; +import java.awt.event.FocusListener; +import java.awt.event.KeyListener; +import java.awt.event.MouseListener; +import java.beans.PropertyChangeListener; +import java.util.Hashtable; import javax.swing.JComponent; +import javax.swing.JTree; +import javax.swing.UIDefaults; +import javax.swing.UIManager; +import javax.swing.tree.TreeCellEditor; +import javax.swing.tree.TreeModel; +import javax.swing.tree.TreePath; +import javax.swing.event.CellEditorListener; +import javax.swing.event.TreeExpansionListener; +import javax.swing.event.TreeModelListener; +import javax.swing.event.TreeSelectionListener; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.basic.BasicTreeUI; -public class MetalTreeUI - extends BasicTreeUI +/** + * A UI delegate for the {@link JTree} component. + */ +public class MetalTreeUI extends BasicTreeUI { - /** The UI instances for MetalTreeUIs */ - private static HashMap instances = null; - + /** Listeners */ + private PropertyChangeListener propertyChangeListener; + private FocusListener focusListener; + private TreeSelectionListener treeSelectionListener; + private MouseListener mouseListener; + private KeyListener keyListener; + private PropertyChangeListener selectionModelPropertyChangeListener; + private ComponentListener componentListener; + private CellEditorListener cellEditorListener; + private TreeExpansionListener treeExpansionListener; + private TreeModelListener treeModelListener; + /** - * Constructs a new instance of MetalTreeUI. + * Constructs a new instance of <code>MetalTreeUI</code>. */ public MetalTreeUI() { @@ -60,27 +89,238 @@ public class MetalTreeUI } /** - * Returns an instance of MetalTreeUI. + * Returns a new instance of <code>MetalTreeUI</code>. * * @param component the component for which we return an UI instance * - * @return an instance of MetalTreeUI + * @return A new instance of <code>MetalTreeUI</code>. */ public static ComponentUI createUI(JComponent component) { - if (instances == null) - instances = new HashMap(); + return new MetalTreeUI(); + } + + /** + * 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. + */ + protected int getHorizontalLegBuffer() + { + return super.getHorizontalLegBuffer(); + } + + /** + * Configures the specified component appropriate for the look and feel. + * This method is invoked when the ComponentUI instance is being installed + * as the UI delegate on the specified component. This method should completely + * configure the component for the look and feel, including the following: + * 1. Install any default property values for color, fonts, borders, icons, + * opacity, etc. on the component. Whenever possible, property values + * initialized by the client program should not be overridden. + * 2. Install a LayoutManager on the component if necessary. + * 3. Create/add any required sub-components to the component. + * 4. Create/install event listeners on the component. + * 5. Create/install a PropertyChangeListener on the component in order + * to detect and respond to component property changes appropriately. + * 6. Install keyboard UI (mnemonics, traversal, etc.) on the component. + * 7. Initialize any appropriate instance data. + */ + public void installUI(JComponent c) + { + tree = (JTree) c; + configureLayoutCache(); + + 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); + tree.setScrollsOnExpand(defaults.getBoolean("Tree.scrollsOnExpand")); + rightChildIndent = defaults.getInt("Tree.rightChildIndent"); + leftChildIndent = defaults.getInt("Tree.leftChildIndent"); + setRowHeight(defaults.getInt("Tree.rowHeight")); + tree.setRowHeight(defaults.getInt("Tree.rowHeight")); + tree.requestFocusInWindow(false); + + setExpandedIcon(defaults.getIcon("Tree.expandedIcon")); + setCollapsedIcon(defaults.getIcon("Tree.collapsedIcon")); + + currentCellRenderer = createDefaultCellRenderer(); + rendererPane = createCellRendererPane(); + createdRenderer = true; + setCellEditor(createDefaultCellEditor()); + createdCellEditor = true; + TreeModel mod = tree.getModel(); + setModel(mod); + + treeSelectionModel = tree.getSelectionModel(); + drawingCache = new Hashtable(); + nodeDimensions = createNodeDimensions(); + + propertyChangeListener = createPropertyChangeListener(); + focusListener = createFocusListener(); + treeSelectionListener = createTreeSelectionListener(); + mouseListener = createMouseListener(); + keyListener = createKeyListener(); + selectionModelPropertyChangeListener = createSelectionModelPropertyChangeListener(); + componentListener = createComponentListener(); + cellEditorListener = createCellEditorListener(); + treeExpansionListener = createTreeExpansionListener(); + treeModelListener = createTreeModelListener(); - Object o = instances.get(component); - MetalTreeUI instance; - if (o == null) + editingRow = -1; + lastSelectedRow = -1; + + installKeyboardActions(); + + tree.addPropertyChangeListener(propertyChangeListener); + tree.addFocusListener(focusListener); + tree.addTreeSelectionListener(treeSelectionListener); + tree.addMouseListener(mouseListener); + tree.addKeyListener(keyListener); + tree.addPropertyChangeListener(selectionModelPropertyChangeListener); + tree.addComponentListener(componentListener); + tree.addTreeExpansionListener(treeExpansionListener); + if (treeModel != null) + treeModel.addTreeModelListener(treeModelListener); + + if (mod != null) { - instance = new MetalTreeUI(); - instances.put(component, instance); + TreePath path = new TreePath(mod.getRoot()); + if (!tree.isExpanded(path)) + toggleExpandState(path); } - else - instance = (MetalTreeUI) o; + + completeUIInstall(); + } + + /** + * Reverses configuration which was done on the specified component during + * installUI. This method is invoked when this UIComponent instance is being + * removed as the UI delegate for the specified component. This method should + * undo the configuration performed in installUI, being careful to leave the + * JComponent instance in a clean state (no extraneous listeners, + * look-and-feel-specific property objects, etc.). This should include + * the following: + * 1. Remove any UI-set borders from the component. + * 2. Remove any UI-set layout managers on the component. + * 3. Remove any UI-added sub-components from the component. + * 4. Remove any UI-added event/property listeners from the component. + * 5. Remove any UI-installed keyboard UI from the component. + * 6. Nullify any allocated instance data objects to allow for GC. + */ + public void uninstallUI(JComponent c) + { + tree.setFont(null); + tree.setForeground(null); + tree.setBackground(null); + + uninstallKeyboardActions(); + + tree.removePropertyChangeListener(propertyChangeListener); + tree.removeFocusListener(focusListener); + tree.removeTreeSelectionListener(treeSelectionListener); + tree.removeMouseListener(mouseListener); + tree.removeKeyListener(keyListener); + tree.removePropertyChangeListener(selectionModelPropertyChangeListener); + tree.removeComponentListener(componentListener); + tree.removeTreeExpansionListener(treeExpansionListener); + + TreeCellEditor tce = tree.getCellEditor(); + if (tce != null) + tce.removeCellEditorListener(cellEditorListener); + TreeModel tm = tree.getModel(); + if (tm != null) + tm.removeTreeModelListener(treeModelListener); + + tree = null; + uninstallComponents(); + completeUIUninstall(); + } + + /** + * This function converts between the string passed into the client + * property and the internal representation (currently an int). + * + * @param lineStyleFlag - String representation + */ + protected void decodeLineStyle(Object lineStyleFlag) + { + // FIXME: not implemented + } - return instance; + /** + * Checks if the location is in expand control. + * + * @param row - current row + * @param rowLevel - current level + * @param mouseX - current x location of the mouse click + * @param mouseY - current y location of the mouse click + */ + protected boolean isLocationInExpandControl(int row, int rowLevel, + int mouseX, int mouseY) + { + return super.isLocationInExpandControl(tree.getPathForRow(row), + mouseX, mouseY); + } + + /** + * 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 current graphics configuration. + * @param c - the current component to draw + */ + public void paint(Graphics g, JComponent c) + { + // Calls BasicTreeUI's paint since it takes care of painting all + // types of icons. + super.paint(g, c); + } + + /** + * Paints the horizontal separators. + * + * @param g - the current graphics configuration. + * @param c - the current component to draw + */ + protected void paintHorizontalSeparators(Graphics g, JComponent c) + { + // FIXME: not implemented + } + + + /** + * Paints the vertical part of the leg. The receiver should NOT modify + * clipBounds, insets. + * + * @param g - the current graphics configuration. + * @param clipBounds - + * @param insets - + * @param path - the current path + */ + protected void paintVerticalPartOfLeg(Graphics g, Rectangle clipBounds, + Insets insets, TreePath path) + { + super.paintVerticalPartOfLeg(g, clipBounds, insets, path); + } + + /** + * Paints the horizontal part of the leg. The receiver should NOT \ + * modify clipBounds, or insets. + * NOTE: parentRow can be -1 if the root is not visible. + */ + protected void paintHorizontalPartOfLeg(Graphics g, Rectangle clipBounds, + Insets insets, Rectangle bounds, + TreePath path, int row, + boolean isExpanded, boolean hasBeenExpanded, + boolean isLeaf) + { + super.paintHorizontalPartOfLeg(g, clipBounds, insets, bounds, path, row, + isExpanded, hasBeenExpanded, isLeaf); } } diff --git a/libjava/classpath/javax/swing/plaf/metal/MetalUtils.java b/libjava/classpath/javax/swing/plaf/metal/MetalUtils.java index a342ee0..c0b4e65 100644 --- a/libjava/classpath/javax/swing/plaf/metal/MetalUtils.java +++ b/libjava/classpath/javax/swing/plaf/metal/MetalUtils.java @@ -1,4 +1,4 @@ -/* Metaltils.java +/* MetalUtils.java Copyright (C) 2005 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -38,7 +38,12 @@ 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.Graphics2D; +import java.awt.TexturePaint; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; /** * Some utility and helper methods for the Metal Look & Feel. @@ -49,6 +54,21 @@ class MetalUtils { /** + * The typical metal pattern for use with Graphics2D. + */ + static BufferedImage pattern2D; + + /** + * The light color to draw the pattern. + */ + static Color lightColor; + + /** + * The dark color to draw to draw the pattern. + */ + static Color darkColor; + + /** * Fills a rectangle with the typical Metal pattern. * * @param g the <code>Graphics</code> context to use @@ -57,31 +77,78 @@ class MetalUtils * @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 h 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, + static void fillMetalPattern(Component c, 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++) + if (g instanceof Graphics2D) + fillMetalPattern2D((Graphics2D) g, x, y, w, h, light, dark); + else { - // 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) + int xOff = 0; + for (int mY = y; mY < (y + h); mY++) { - g.drawLine(mX, mY, mX, mY); + // set color alternating with every line + if (((mY - y) % 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; } + } + } + + /** + * Fills a rectangle with the typical Metal pattern using Java2D. + * + * @param g2d the <code>Graphics2D</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 h the height of the rectangle to fill + */ + static void fillMetalPattern2D(Graphics2D g2d, int x, int y, int w, int h, + Color light, Color dark) + { + if (pattern2D == null || !darkColor.equals(dark) || !lightColor.equals(light)) + initializePattern(light, dark); + + // Prepare the texture. + TexturePaint texture = + new TexturePaint(pattern2D, new Rectangle2D.Double(0., 0., 4., 4.)); + g2d.setPaint(texture); + g2d.fillRect(x, y, w, h); + } - // increase x offset - xOff++; - if (xOff > 3) - xOff = 0; - } + /** + * Initializes the pattern image. + */ + static void initializePattern(Color light, Color dark) + { + pattern2D = new BufferedImage(4, 4, BufferedImage.TYPE_INT_ARGB); + lightColor = light; + darkColor = dark; + Graphics g = pattern2D.getGraphics(); + g.setColor(light); + g.fillRect(0, 0, 1, 1); + g.fillRect(2, 2, 1, 1); + g.setColor(dark); + g.fillRect(1, 1, 1, 1); + g.fillRect(3, 3, 1, 1); + g.dispose(); } } diff --git a/libjava/classpath/javax/swing/plaf/metal/OceanTheme.java b/libjava/classpath/javax/swing/plaf/metal/OceanTheme.java new file mode 100644 index 0000000..85a8cb1 --- /dev/null +++ b/libjava/classpath/javax/swing/plaf/metal/OceanTheme.java @@ -0,0 +1,209 @@ +/* DefaultMetalTheme.java -- A modern theme for 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 javax.swing.UIDefaults; +import javax.swing.plaf.ColorUIResource; + +/** + * A modern theme for the Metal Look & Feel. + * @since 1.5 + * + * @author Roman Kennke (roman@kennke.org) + */ +public class OceanTheme extends DefaultMetalTheme +{ + /** + * The OceanTheme value for black. + */ + static final ColorUIResource BLACK = new ColorUIResource(51, 51, 51); + + /** + * The OceanTheme value for primary1. + */ + static final ColorUIResource PRIMARY1 = new ColorUIResource(99, 130, 191); + + /** + * The OceanTheme value for primary1. + */ + static final ColorUIResource PRIMARY2 = new ColorUIResource(163, 184, 204); + + /** + * The OceanTheme value for primary1. + */ + static final ColorUIResource PRIMARY3 = new ColorUIResource(184, 207, 229); + + /** + * The OceanTheme value for secondary1. + */ + static final ColorUIResource SECONDARY1 = new ColorUIResource(122, 138, 153); + + /** + * The OceanTheme value for secondary2. + */ + static final ColorUIResource SECONDARY2 = new ColorUIResource(184, 207, 229); + + /** + * The OceanTheme value for secondary3. + */ + static final ColorUIResource SECONDARY3 = new ColorUIResource(238, 238, 238); + + /** + * The OceanTheme value for inactive control text. + */ + static final ColorUIResource INACTIVE_CONTROL_TEXT = + new ColorUIResource(153, 153, 153); + + /** + * Returns the name of this theme, "Ocean" + */ + public String getName() + { + return "Ocean"; + } + + /** + * Returns the color for control text, which is the + * value of the theme's black value. + */ + public ColorUIResource getControlTextColor() + { + return getBlack(); + } + + /** + * Returns the desktop color, which is the theme's white color. + */ + public ColorUIResource getDesktopColor() + { + return getWhite(); + } + + /** + * Returns the color for inactive control text, which is the + * RGB value (153, 153, 153). + */ + public ColorUIResource getInactiveControlTextColor() + { + return INACTIVE_CONTROL_TEXT; + } + + /** + * Returns the OceanTheme's color for disabled menu foreground, + * + */ + public ColorUIResource getMenuDisabledForeground() + { + return INACTIVE_CONTROL_TEXT; + } + + + /** + * Returns the OceanTheme's color for black, the RGB value + * (51, 51, 51). + * + * @return Returns the OceanTheme's value for black + */ + protected ColorUIResource getBlack() + { + return BLACK; + } + + /** + * Return the OceanTheme's value for primary 1, the RGB value + * (99, 130, 191). + */ + protected ColorUIResource getPrimary1() + { + return PRIMARY1; + } + + /** + * Return the OceanTheme's value for primary 2, the RGB value + * (163, 184, 204). + */ + protected ColorUIResource getPrimary2() + { + return PRIMARY2; + } + + /** + * Return the OceanTheme's value for primary 1, the RGB value + * (184, 207, 229). + */ + protected ColorUIResource getPrimary3() + { + return PRIMARY3; + } + + /** + * Return the OceanTheme's value for secondary 1, the RGB value + * (122, 138, 153). + */ + protected ColorUIResource getSecondary1() + { + return SECONDARY1; + } + + /** + * Return the OceanTheme's value for secondary 2, the RGB value + * (184, 207, 229). + */ + protected ColorUIResource getSecondary2() + { + return SECONDARY2; + } + /** + * Return the OceanTheme's value for secondary 3, the RGB value + * (238, 238, 238). + */ + protected ColorUIResource getSecondary3() + { + return SECONDARY3; + } + + /** + * Adds customized entries to the UIDefaults table. + * + * @param defaults the UI defaults table + */ + public void addCustomEntriesToTable(UIDefaults defaults) + { + defaults.put("Button.rollover", Boolean.TRUE); + } +} diff --git a/libjava/classpath/javax/swing/plaf/metal/package.html b/libjava/classpath/javax/swing/plaf/metal/package.html index 2ea787b..8675493 100644 --- a/libjava/classpath/javax/swing/plaf/metal/package.html +++ b/libjava/classpath/javax/swing/plaf/metal/package.html @@ -40,7 +40,16 @@ exception statement from your version. --> <head><title>GNU Classpath - javax.swing.plaf.metal</title></head> <body> -<p>Provides a cross-platform look and feel known as "Metal".</p> - +<p>Provides a cross-platform look and feel known as "Metal". To install this +look and feel, add the following code (or something similar) +near the start of your application:</p> +<pre>try + { + UIManager.setLookAndFeel(new MetalLookAndFeel()); + } +catch (UnsupportedLookAndFeelException e) + { + e.printStackTrace(); + }</pre> </body> </html> diff --git a/libjava/classpath/javax/swing/plaf/multi/MultiLookAndFeel.java b/libjava/classpath/javax/swing/plaf/multi/MultiLookAndFeel.java index a70a8ff..2bd358d 100644 --- a/libjava/classpath/javax/swing/plaf/multi/MultiLookAndFeel.java +++ b/libjava/classpath/javax/swing/plaf/multi/MultiLookAndFeel.java @@ -56,6 +56,7 @@ public class MultiLookAndFeel extends LookAndFeel { */ public MultiLookAndFeel() { + // Nothing to do here. } /** |