aboutsummaryrefslogtreecommitdiff
path: root/libjava/javax/swing/plaf
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@gcc.gnu.org>2004-03-17 21:29:02 +0000
committerGraydon Hoare <graydon@gcc.gnu.org>2004-03-17 21:29:02 +0000
commit86881a7b541b2ec6557b1a315f841b211d14c576 (patch)
tree02790a2b250b62643a1de68b63bd078238bfaf46 /libjava/javax/swing/plaf
parentab3533d6559205bee768b8d9e359111d52d10733 (diff)
downloadgcc-86881a7b541b2ec6557b1a315f841b211d14c576.zip
gcc-86881a7b541b2ec6557b1a315f841b211d14c576.tar.gz
gcc-86881a7b541b2ec6557b1a315f841b211d14c576.tar.bz2
[multiple changes]
2004-03-12 Graydon Hoare <graydon@redhat.com> * gnu/java/awt/peer/gtk/GdkGraphics2D.java: Clipping fixes. * javax/swing/JComponent.java (paint): Use persistent double buffer. * javax/swing/JList.java (ListListener): Revalidate on changes. * javax/swing/JScrollPane.java: Reimplement. * javax/swing/JViewport.java: Reimplement. * javax/swing/ScrollPaneLayout.java: Reimplement. * javax/swing/ViewportLayout.java: Tidy up. * javax/swing/plaf/basic/BasicButtonListener.java: Remove printlns. * javax/swing/plaf/basic/BasicScrollPaneUI.java: Reimplement. * javax/swing/plaf/basic/BasicSliderUI.java: Handle missing labels. * javax/swing/plaf/basic/BasicViewportUI.java: Implement in terms of backing store only. 2004-03-11 Thomas Fitzsimmons <fitzsim@redhat.com> * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkWindowPeer.c (window_wm_protocols_filter): New function. (window_focus_in_cb): Remove function. (window_focus_out_cb): Likewise. (window_focus_or_active_state_change_cb): New function. (create): Add filter that removes WM_TAKE_FOCUS client messages. (connectSignals): Don't attach handlers to focus-in-event or focus-out-event signals. Handle notify signal. 2004-03-11 David Jee <djee@redhat.com> * gnu/java/awt/peer/gtk/GtkCheckboxPeer.java (gtkSetLabel): New native method declaration. (setLabel): Use gtkSetLabel. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxPeer.c (Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_gtkSetLabel): New method. 2004-03-10 Thomas Fitzsimmons <fitzsim@redhat.com> * gnu/java/awt/peer/gtk/GdkGraphics.java (setColor): Default to black when color argument is null. 2004-03-10 Kim Ho <kho@redhat.com> * java/awt/Container.java: Remove check for drag events. 2004-03-10 Kim Ho <kho@redhat.com> * java/awt/Container.java: (visitChild): Remove candidate clip. Use the component clip to intersect. * gnu/java/awt/peer/gtk/GtkComponentPeer.java: (handleEvent): Use the PaintEvent's clip. 2004-03-10 Kim Ho <kho@redhat.com> * gnu/java/awt/peer/gtk/GtkComponentPeer.java: (handleEvent): Don't set the clip for the Graphics object. 2004-03-09 Graydon Hoare <graydon@redhat.com> * jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGlyphVector.c: Fix double <-> fixed macros, reset font transform. * jni/gtk-peer/gnu_java_awt_peer_gtk_GdkClasspathFontPeerMetrics.c: Likewise. 2004-03-09�� Kim Ho <kho@redhat.com> * java/awt/Container.java: (visitChild): Move the x and y coordinate of the component rectangle to correct position. (handleEvent): Forward drag events to the pressed component. * javax/swing/plaf/basic/BasicScrollBarUI.java: Fix comments. (ArrowButtonListener::mousePressed): Stop the existing timer. (mouseDragged): Implement. (TrackListener::mousePressed): Only react if the press doesn't occur on the thumb, otherwise just set the offset. (TrackListener::mouseReleased): Unset the isAdjusting value. (createIncreaseIcon): Switch icon. (createDecreaseIcon): Switch icon. (calculatePreferredSize): Use width. (getThumbBounds): Use the top as the lower value. (layoutVScrollBar): Switch the button locations. (paintIncreaseHighlight): Paint correct side of thumb. (paintDecreaseHighlight): ditto. (valueForYPosition): Use top as the lower value. * javax/swing/plaf/basic/BasicSliderUI.java: Fix comments. (mouseDragged): Implement. (mousePressed): Only react when the thumb isn't pressed, otherwise just set offset. (mouseReleased): Handle a release of the thumb. (scrollDueToClickInTrack): Stop the timer first. * javax/swing/JProgressBar.java: (setString): Fix change condition. * javax/swing/JSeparator.java: Remove println's. 2004-03-08 David Jee <djee@redhat.com> * java/awt/image/AffineTransformOp.java: (filter): Use Graphics2D interface instead of directly using the GdkGraphics2D peer. 2004-03-05 David Jee <djee@redhat.com> * gnu/java/awt/peer/gtk/GtkButtonPeer.java (handleEvent): Action events are generated upon MOUSE_RELEASED. * java/awt/Container.java (acquireComponentForMouseEvent): Fixed. (handleEvent): Fixed. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkEvents.c (state_to_awt_mods_with_button_states): New method. (pre_event_handler): Fixed mouse event generation. 2004-03-05 Olga Rodimina <rodimina@redhat.com> gnu/java/awt/peer/gtk/GdkGraphics2D.java (GdkGraphics2D (BufferedImage)): Initialize pixmap associated with specified BufferedImage. (setPaint): Changed implementation of Texture Paint to use AffineTransformOp. * java/awt/image/AffineTransformOp.java (createCompatibleDestRaster): Throw RasterFormatException if resulting width or height of raster is 0. 2004-03-04 Olga Rodimina <rodimina@redhat.com> * java/awt/image/AffineTransformOp.java: Removed unnecessary field interpolationType. Formatted some of the lines to be consistent with the GNU style. (AffineTransformOp): Create new RenderingHints containing specified interpolation type. (createCompatibleDestImage): Implemented. (createCompatibleDestRaster): Implemented. (filter): Implemented. (getBounds2D(BufferedImage)): Implemented. (getBounds2D(Raster)): Implemented. (getInterpolationType): Get interpolation value from rendering hints. 2004-03-04 David Jee <djee@redhat.com> * gnu/java/awt/peer/gtk/GtkContainerPeer.java (setFont): Check if child peers are null. 2004-03-04 Graydon Hoare <graydon@redhat.com> * testsuite/lib/libjava.exp (libjava_find_lib): Don't include .libs in -L option. (libjava_arguments): Add new libraries to argument list. 2004-03-04 Tom Tromey <tromey@redhat.com> * Makefile.in: Rebuilt. * Makefile.am (toolexeclib_LTLIBRARIES): Added lib-java-awt.la, lib-javax-swing.la, lib-java-applet.la, lib-java-beans.la. (misc_java_source_files): New macro. (swing_java_source_files): Likewise. (awt_java_source_files): Pruned. (applet_java_source_files): New macro. (beans_java_source_files): Likewise. (lib_java_applet_la_SOURCES): Likewise. (lib_java_awt_la_SOURCES): Likewise. (lib_javax_swing_la_SOURCES): Likewise. (lib_java_beans_la_SOURCES): Likewise. (all_java_object_files): Likewise. (%.lo: %.java): Use all_java_object_files. (all_java_source_files): Added new _SOURCES. (ordinary_java_source_files): Removed awt_java_source_files. 2004-03-02 Olga Rodimina <rodimina@redhat.com> * Makefile.am: Added java/awt/image/AffineTransformOp.java * Makefile.in: Re-generated. * java/awt/image/AffineTransformOp.java: New Class. 2004-03-01 Olga Rodimina <rodimina@redhat.com> * gnu/java/awt/peer/gtk/GdkGraphics2D.java (setPaint): Interpret correctly TexturePaint's anchor rectangle. (drawImage): Fixed scale factors of the affine transform. 2004-02-27 David Jee <djee@redhat.com> * gnu/java/awt/peer/gtk/GdkGraphics.java (GdkGraphics(Component)): Inherit font from component. (drawString): Use font style. * gnu/java/awt/peer/gtk/GtkCheckboxPeer.java (gtkSetFont): New native method declaration. (setFont): New method. * gnu/java/awt/peer/gtk/GtkComponentPeer.java (gtkSetFont): New native method declaration. (setFont): Call new native method gtkSetFont. * gnu/java/awt/peer/gtk/GtkContainerPeer.java (setFont): For all child components who do not their fonts set, set their peers' fonts with this container's font. * gnu/java/awt/peer/gtk/GtkLabelPeer.java: Move all native method declarations to the top for readability. (gtkSetFont): New native method declaration. (setFont): New method. * java/awt/Component.java (setFont): Invalidate after setting the font. * java/awt/Container.java (invalidateTree): New method. (setFont): Invalidate the container tree after setting the font. * jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics.c (Java_gnu_java_awt_peer_gtk_GdkGraphics_drawString): Use font style. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkCheckboxPeer.c (Java_gnu_java_awt_peer_gtk_GtkCheckboxPeer_gtkSetFont): New method. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c (Java_gnu_java_awt_peer_gtk_GtkComponentPeer_gtkSetFont): New method. * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkLabelPeer.c (Java_gnu_java_awt_peer_gtk_GtkLabelPeer_gtkSetFont): New method. 2004-02-27 Olga Rodimina <rodimina@redhat.com> * gnu/java/awt/peer/gtk/GdkGraphics2D.java (updateBufferedImage): New helper function. Updates BufferedImage in memory if it was changed. (draw): changed to update BufferedImage in memory after this drawing operation (fill): Ditto. (draw3DRect): Ditto. (fill3DRect): Ditto. (clearRect): Ditto. (drawRaster): Ditto. (drawImage) : Ditto. Update only in case of GtkOffScreenImage with no affine transformation. (drawGlyphVector): Ditto. 2004-02-26 Olga Rodimina <rodimina@redhat.com> * gnu/java/awt/peer/gtk/GdkGraphics2D.java (isBufferedImageGraphics): New Helper function. Returns true if this graphics2d can be used to draw into buffered image and false otherwise. (updateImagePixels): New Helper function. Updates pixels in the BufferedImage. * jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c (getImagePixels): New function. Returns pixels of the buffered image associated with this Graphics2D. 2004-02-26 David Jee <djee@redhat.com> * java/awt/BorderLayout.java (layoutContainer): Fix width and height calculations to ensure that they're non-negative. * java/awt/Component.java (setBackground): If c is null, inherit from closest ancestor whose background color is set. 2004-02-26�� Kim Ho�� <kho@redhat.com> * Makefile.am: Add new files. * Makefile.in: Re-generate. * javax/swing/JProgressBar.java: (JProgressBar(int, int int)): Throw IllegalArgumentException if orientation is invalid. (JProgressBar(BoundedRangeModel)): Create ChangeListener and register it. UpdateUI. (getChangeListeners): Implement. (setModel): Reset ChangeListener. * javax/swing/JScrollBar.java: Implement. * javax/swing/JSeparator.java: Implement. * javax/swing/JSlider.java: (JSlider(int, int, int, int)): Throw IllegalArgumentException if orientation is invalid. (getChangeListeners): Fix method name. * javax/swing/SwingUtilities.java: (layoutCompoundLabel): If there is no text, set the text rectangle dimensions to 0. * javax/swing/plaf/basic/BasicButtonUI.java: (paint): If there is no text, don't paint it. * javax/swing/plaf/basic/BasicScrollBarUI.java: Implement. * javax/swing/plaf/basic/BasicSeparatorUI.java: Implement. * javax/swing/plaf/basic/BasicSliderUI.java: (propertyChange): If the model changes, change the listeners accordingly. 2004-02-25 Graydon Hoare <graydon@redhat.com> * javax/swing/AbstractButton.java: Add "final" qualifiers. * javax/swing/JList.java: Reimplement. * javax/swing/DefaultListSelectionModel.java: Reimplement. * javax/swing/plaf/basic/BasicListUI.java: Reimplement. * javax/swing/plaf/basic/BasicLookAndFeel.java: Add "purple" values. * javax/swing/ListModel.java: Javadoc. * javax/swing/ListSelectionModel.java: Add missing methods. * javax/swing/AbstractListModel.java: Javadoc and corrections. * javax/swing/DefaultListModel.java: Javadoc and corrections. * javax/swing/ListModel.java: Javadoc and corrections. * javax/swing/DefaultListCellRenderer.java: Minor tidying. 2004-02-25 David Jee <djee@redhat.com> * gnu/java/awt/peer/gtk/GtkFontPeer.java (GtkFontPeer): Change default size to 12. * gnu/java/awt/peer/gtk/GtkToolkit.java (getFontPeer): Change default size to 12. (getClasspathFontPeer): Likewise. Set default name to "Default". * java/awt/Font.java (Font(Map)): Call Font(String,Map). (Font(String,Map)): If attrs is null, initialize it as an empty HashMap, which will ensure that the Font will get default attributes. 2004-02-25 David Jee <djee@redhat.com> * gnu/java/awt/peer/gtk/GtkFontPeer.java (GtkFontPeer(String,int)): Call the new constructor with size 1. (GtkFontPeer(String,int,int)): New constructor with size attribute. * gnu/java/awt/peer/gtk/GtkToolkit.java (getFontPeer(String,int)): Call the new overload method with size 1. (getFontPeer(String,int,int)): New method. Overloaded with size attribute. (getClasspathFontPeer): Set the size of the font. 2004-02-24 Olga Rodimina <rodimina@redhat.com> * gnu/java/awt/peer/gtk/GdkGraphics2D.java (bimage): New field. (GdkGraphics2D): New Constructor. Constructs Graphics object that can be used to draw into the Buffered Image. * gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java: (GdkGraphicsEnvironment): Fixed to include public keyword. (createGraphics): Implemented. * gnu/java/awt/peer/gtk/GtkToolkit.java (getLocalGraphicsEnvironment): Implemented. * java/awt/GraphicsEnvironment.java: (getLocalGraphicsEnvironment): Implemented. * java/awt/image/BufferedImage.java: (createGraphics): Implemented. 2004-02-24 David Jee <djee@redhat.com> * java/awt/Component.java (eventTypeEnabled): Add MOUSE_MOVED and MOUSE_DRAGGED event types. * java/awt/Container.java (addNotifyContainerChildren): Fix event enabling. 2004-02-23 Olga Rodimina <rodimina@redhat.com> * Makefile.am: Added gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java * Makefile.in: Re-generated. * gnu/java/awt/peer/gtk/GdkGraphicsEnvironment.java: New Class. 2004-02-19 Kim Ho <kho@redhat.com> * Makefile.am: Add BasicProgressBarUI * Makefile.in: Regenerate. * javax/swing/JProgressBar.java: Re-implement. * javax/swing/plaf/basic/BasicLookAndFeel.java Add constants for JProgressBar. * javax/swing/plaf/basic/BasicProgressBarUI.java Implement. * javax/swing/plaf/basic/BasicSliderUI.java Change comments. (calculateGeometry): New method (paint): Remove unnecessary size calculations. 2004-02-18 Olga Rodimina <rodimina@redhat.com> * gnu/java/awt/peer/gtk/GdkGraphics2D.java (drawRaster): Fixed small error that caused imageToUser transformation to be set incorrectly. (toString): Implemented. 2004-02-18 David Jee <djee@redhat.com> * java/awt/CardLayout.java (addLayoutComponent): Show the first component added as the default. (removeLayoutComponent): After removing, show the next component. (gotoComponent): If there is only one component, show it and return. 2004-02-18 Kim Ho <kho@redhat.com> * javax/swing/JSlider.java: Re-order modifiers. * javax/swing/JLabel.java: Re-order modifiers. * javax/swing/JComponent.java: (addPropertyChangeListener): Implement. (removePropertyChangeListener): ditto. (firePropertyChangeEvent): ditto. 2004-02-17 David Jee <djee@redhat.com> * java/awt/Component.java (show): Dispatch ComponentEvent via system event queue. (hide): Likewise. (move): Likewise. (resize): Likewise. (reshape): Likewise. * java/awt/Window.java (setBoundsCallback): Likewise. 2004-02-17 David Jee <djee@redhat.com> * jni/gtk-peer/gnu_java_awt_peer_gtk_GtkComponentPeer.c (Java_gnu_java_awt_peer_gtk_GtkComponentPeer_setNativeBounds): Use gtk_widget_set_size_request() instead of the deprecated gtk_widget_set_usize(). 2004-02-17 Kim Ho <kho@redhat.com> * javax/swing/JSlider.java: Fix comments and make property strings constants. (createStandardLabels): Use the labels preferred size as bounds. * javax/swing/plaf/basic/BasicSliderUI.java Fix comments. (ScrollHandler::actionPerformed): Don't calculate the timer stop value. Let the MouseListeners find the stop location. (getPreferredHorizontalSize): Re-implement. (getPreferredVerticalSize): ditto. (getMinimumHorizontalSize): ditto. (getMinimumVerticalSize): ditto. (getPreferredSize): ditto. (getMinimumSize): ditto. (getMaximumSize): ditto. (paintTicks): Use doubles to find the tick location. (paintHorizontalLabel):�� Use preferredSize as initial width and height. (paintVerticalLabel): ditto. 2004-02-17 Kim Ho <kho@redhat.com> * javax/swing/JLabel.java: Changed property strings to constants. (DISPLAYED_MNEMONIC_INDEX_CHANGED_PROPERTY): New property. (setText): Change mnemonic index if text is too short. (setDisplayedMnemonicIndex): Fire property change event. (getDisplayedMnemonicIndex): Remove check against short text. 2004-02-17 Olga Rodimina <rodimina@redhat.com> * gnu/java/awt/peer/gtk/GdkGraphics2D.java: (drawImage(img,xform,obs)): Invert xform before passing the xform to cairo. (drawImage(img,x,y,bgcolor,obs)): Implemented. (drawImage (img,x,y,w,h,bgcolor,obs)): Partly implemented. (drawImage (img,x,y,w,h,obs)): Implemented. (drawImage (img,dx1,dy1,dx2,dy2,sx1,sy1,sx2,sy2, bgcolor,obs)): Partly implemented. (drawImage (img,dx1,dy1,dx2,dy2,sx1,sy1,sx2,sy2,obs)): Implemented. * java/awt/image/BufferedImage.java: (copyData): if dest is null, create raster with same dimensions as the current image. 2004-02-16 Graydon Hoare <graydon@redhat.com> * javax/swing/plaf/basic/BasicLabelUI.java (getPreferredSize): Use layoutCL. * javax/swing/plaf/basic/BasicGraphicsUtils.java (getPreferredButtonSize): Start with empty view rect, layout using component's preferred alignment. * javax/swing/plaf/basic/BasicLookAndFeel.java: Add some Label and List defaults. 2004-02-16 David Jee <djee@redhat.com> * java/awt/Component.java (show): Dispatch COMPONENT_SHOWN ComponentEvent. (hide): Dispatch COMPONENT_HIDDEN ComponentEvent. (move): Erase old bounds and repaint new bounds. Dispatch COMPONENT_MOVED ComponentEvent. (resize): Erase old bounds and repaint new bounds. Dispatch COMPONENT_RESIZED ComponentEvent. (reshape): Dispatch COMPONENT_RESIZED and COMPONENT_MOVED ComponentEvents. * java/awt/Window.java (setBoundsCallback): Dispatch COMPONENT_RESIZED and COMPONENT_MOVED ComponentEvents. 2004-02-16 Olga Rodimina <rodimina@redhat.com> * gnu/java/awt/peer/gtk/GdkGraphics2D.java: (setRenderingHint): Added implementation of Interpolation rendering hints. (setRenderingHints): Ditto. * jni/gtk-peer/gnu_java_awt_peer_gtk_GdkGraphics2D.c: (drawPixels): fixed to allow user to choose type of filtering that should be used when displaying images. (cairoSurfaceSetFilter): New method. Sets filter type for interpolation of pixel values. 2004-02-16 David Jee <djee@redhat.com> * java/awt/GridBagLayout.java (calcCellSizes): Rows or columns with zero sizes should still be considered for extra space distribution. 2004-02-16 Kim Ho <kho@redhat.com> * javax/swing/JLabel.java: Re-implement. * javax/swing/plaf/basic/BasicLabelUI.java Re-implement. * javax/swing/plaf/basic/BasicLookAndFeel.java: Added constant. 2004-02-16�� Kim Ho�� <kho@redhat.com> * javax/swing/JSlider.java: Fix indentation and comments. (setModel): Remove null check to conform with Sun's. (setOrientation): Throw exception if not HORIZONTAL or VERTICAL. (getInverted): Use private variable instead of ComponentOrientation. (setInverted): ditto. * javax/swing/plaf/basic/BasicSliderUI.java: Fix indentation and comments. (propertyChange): Remove check for inverted slider, handle in main paint. (getMinimumSize): Return preferred size. (getMaximumSize): ditto. (calculateFocusRect): Don't relocate rectangle. (drawInverted): Return XOR of the slider's inversion and the component's orientation. (paint): Update leftToRightCache 2004-02-13 David Jee <djee@redhat.com> * java/awt/GridBagLayout.java (GetLayoutInfo): Fix weight and size distribution. Relocate repeated code to helper methods. (sortBySpan): New helper method. (distributeSizeAndWeight): Likewise. (calcCellWeights): Likewise. (calcCellSizes): Add comments. 2004-02-13 David Jee <djee@redhat.com> * java/awt/Component.java (show): Only do something if component is invisible at the moment. (hide): Only do something if component is visible at the moment. (reshape): If lightweight, erase old bounds and repaint new bounds. 2004-02-13�� Kim Ho�� <kho@redhat.com> * Makefile.am: Updated for new file. * Makefile.in: Regenerated. * javax/swing/JSlider.java: Reimplement. * javax/swing/SwingUtilities.java (layoutCompoundLabel): Use icon height instead of width. (paintComponent): Implement. * javax/swing/plaf/basic/BasicLookAndFeel.java: Add JSlider defaults. * javax/swing/plaf/basic/BasicSliderUI.java: Implement. New file. From-SVN: r79607
Diffstat (limited to 'libjava/javax/swing/plaf')
-rw-r--r--libjava/javax/swing/plaf/basic/BasicButtonListener.java3
-rw-r--r--libjava/javax/swing/plaf/basic/BasicButtonUI.java3
-rw-r--r--libjava/javax/swing/plaf/basic/BasicGraphicsUtils.java11
-rw-r--r--libjava/javax/swing/plaf/basic/BasicLabelUI.java493
-rw-r--r--libjava/javax/swing/plaf/basic/BasicListUI.java710
-rw-r--r--libjava/javax/swing/plaf/basic/BasicLookAndFeel.java67
-rw-r--r--libjava/javax/swing/plaf/basic/BasicProgressBarUI.java820
-rw-r--r--libjava/javax/swing/plaf/basic/BasicScrollBarUI.java1397
-rw-r--r--libjava/javax/swing/plaf/basic/BasicScrollPaneUI.java34
-rw-r--r--libjava/javax/swing/plaf/basic/BasicSeparatorUI.java266
-rw-r--r--libjava/javax/swing/plaf/basic/BasicSliderUI.java2213
-rw-r--r--libjava/javax/swing/plaf/basic/BasicViewportUI.java108
12 files changed, 5823 insertions, 302 deletions
diff --git a/libjava/javax/swing/plaf/basic/BasicButtonListener.java b/libjava/javax/swing/plaf/basic/BasicButtonListener.java
index 393ba37..98b4c8b 100644
--- a/libjava/javax/swing/plaf/basic/BasicButtonListener.java
+++ b/libjava/javax/swing/plaf/basic/BasicButtonListener.java
@@ -87,15 +87,12 @@ public class BasicButtonListener
}
public void mouseMoved(MouseEvent e)
{
- System.err.println("button got mouse move");
}
public void mouseDragged(MouseEvent e)
{
- System.err.println("button got mouse drag");
}
public void mouseClicked(MouseEvent e)
{
- System.err.println("button got mouse click");
}
/**
diff --git a/libjava/javax/swing/plaf/basic/BasicButtonUI.java b/libjava/javax/swing/plaf/basic/BasicButtonUI.java
index 7d59fc2..5dbd17e 100644
--- a/libjava/javax/swing/plaf/basic/BasicButtonUI.java
+++ b/libjava/javax/swing/plaf/basic/BasicButtonUI.java
@@ -250,7 +250,8 @@ public class BasicButtonUI extends ButtonUI
paintButtonNormal(g, br, c);
paintIcon(g, c, ir);
- paintText(g, c, tr, b.getText());
+ if (text != null)
+ paintText(g, c, tr, b.getText());
paintFocus(g, c, vr, tr, ir);
}
diff --git a/libjava/javax/swing/plaf/basic/BasicGraphicsUtils.java b/libjava/javax/swing/plaf/basic/BasicGraphicsUtils.java
index 65cc7b9..1f2f744 100644
--- a/libjava/javax/swing/plaf/basic/BasicGraphicsUtils.java
+++ b/libjava/javax/swing/plaf/basic/BasicGraphicsUtils.java
@@ -597,10 +597,7 @@ public class BasicGraphicsUtils
Insets insets = b.getInsets();
Insets margin = b.getMargin();
- /* For determining the ideal size, do not assume a size restriction. */
- viewRect = new Rectangle(0, 0,
- /* width */ Integer.MAX_VALUE,
- /* height */ Integer.MAX_VALUE);
+ viewRect = new Rectangle();
/* java.awt.Toolkit.getFontMetrics is deprecated. However, it
* seems not obvious how to get to the correct FontMetrics object
@@ -614,14 +611,13 @@ public class BasicGraphicsUtils
b.getToolkit().getFontMetrics(b.getFont()), // see comment above
b.getText(),
b.getIcon(),
- SwingUtilities.TOP, // important:
- SwingUtilities.LEFT, // large vrect, stick to the top left
+ b.getVerticalAlignment(),
+ b.getHorizontalAlignment(),
b.getVerticalTextPosition(),
b.getHorizontalTextPosition(),
viewRect, iconRect, textRect,
textIconGap);
-
/* +------------------------+ +------------------------+
* | | | |
* | ICON | | CONTENTCONTENTCONTENT |
@@ -629,6 +625,7 @@ public class BasicGraphicsUtils
* | TEXTTEXTTEXT | | CONTENTCONTENTCONTENT |
* +------------------------+ +------------------------+
*/
+
contentRect = textRect.union(iconRect);
return new Dimension(insets.left + margin.left
diff --git a/libjava/javax/swing/plaf/basic/BasicLabelUI.java b/libjava/javax/swing/plaf/basic/BasicLabelUI.java
index 51c694a..219c6fa 100644
--- a/libjava/javax/swing/plaf/basic/BasicLabelUI.java
+++ b/libjava/javax/swing/plaf/basic/BasicLabelUI.java
@@ -1,5 +1,5 @@
/* BasicLabelUI.java
- Copyright (C) 2002 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
This file is part of GNU Classpath.
@@ -35,7 +35,6 @@ this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
-
package javax.swing.plaf.basic;
import java.awt.Color;
@@ -47,156 +46,384 @@ import java.awt.Insets;
import java.awt.Rectangle;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
+import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JLabel;
+import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
+import javax.swing.UIDefaults;
+import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.LabelUI;
-public class BasicLabelUI extends LabelUI
- implements PropertyChangeListener
+
+/**
+ * This is the Basic Look and Feel class for the JLabel. One BasicLabelUI
+ * object is used to paint all JLabels that utilize the Basic L&F.
+ */
+public class BasicLabelUI extends LabelUI implements PropertyChangeListener
{
- int gap = 3;
- Color foreground;
+ /** The labelUI that is shared by all labels. */
+ protected static BasicLabelUI labelUI;
-
- public static ComponentUI createUI(final JComponent c) {
- return new BasicLabelUI();
- }
-
-
- public void installUI(final JComponent c) {
- super.installUI(c);
-
- foreground = new Color(0,0,250);
- }
-
+ /**
+ * Creates a new BasicLabelUI object.
+ */
+ public BasicLabelUI()
+ {
+ super();
+ }
- public Dimension getPreferredSize(JComponent c)
- {
- JLabel b = (JLabel)c;
- /*
- We cannot use this method because it is not part of the
- official Swing API.
-
- Dimension d = BasicGraphicsUtils.getPreferredSize(b,
- gap,
- b.getText(),
- b.getIcon(),
- b.getVerticalAlignment(),
- b.getHorizontalAlignment(),
- b.getHorizontalTextPosition(),
- b.getVerticalTextPosition());
- System.out.println("JLABEL->^^^^^^^^^^^^^^^^^^^^^^ BASIC-PREF="+d + ",T="+b.getText());
- */
- return new Dimension(100, 30);
- }
+ /**
+ * Creates and returns a UI for the label. Since one UI is shared by all
+ * labels, this means creating only if necessary and returning the shared
+ * UI.
+ *
+ * @param c The {@link JComponent} that a UI is being created for.
+ *
+ * @return A label UI for the Basic L&F.
+ */
+ public static ComponentUI createUI(JComponent c)
+ {
+ if (labelUI == null)
+ labelUI = new BasicLabelUI();
+ return labelUI;
+ }
+
+ /**
+ * Returns the preferred size of this component as calculated by the
+ * {@link layoutCL} method.
+ *
+ * @param c This {@link JComponent} to get a preferred size for.
+ *
+ * @return The preferred size.
+ */
+ public Dimension getPreferredSize(JComponent c)
+ {
+ JLabel lab = (JLabel)c;
+ Rectangle vr = new Rectangle();
+ Rectangle ir = new Rectangle();
+ Rectangle tr = new Rectangle();
+ Insets insets = lab.getInsets();
+ FontMetrics fm = lab.getToolkit().getFontMetrics(lab.getFont());
+ layoutCL(lab, fm, lab.getText(), lab.getIcon(), vr, ir, tr);
+ Rectangle cr = tr.union(ir);
+ return new Dimension(insets.left + cr.width + insets.right,
+ insets.top + cr.height + insets.bottom);
+ }
- public void paint(Graphics g, JComponent c)
- {
- JLabel b = (JLabel) c;
-
- Rectangle tr = new Rectangle();
- Rectangle ir = new Rectangle();
- Rectangle vr = new Rectangle();
-
- Font f = c.getFont();
-
- g.setFont(f);
-
- FontMetrics fm = g.getFontMetrics(f);
-
- Insets i = c.getInsets();
-
- Rectangle bound = c.getBounds();
-
- System.out.println("BOUND=" + bound + ", insets = " + i + ", " + b.getText());
-
- if (bound == null)
- {
- vr.x = i.left;
- vr.y = i.top;
- vr.width = b.getWidth() - (i.right + i.left);
- vr.height = b.getHeight() - (i.bottom + i.top);
- }
- else
- {
- vr.x = bound.x + i.left;
- vr.y = bound.y + i.top;
- vr.width = bound.width - (i.right + i.left);
- vr.height = bound.height - (i.bottom + i.top);
- }
-
- System.out.println(" VIEW-RECT-JLABEL="+vr+", insets="+i+", FONTM="+fm);
-
- String text = SwingUtilities.layoutCompoundLabel(c,
- fm,
- b.getText(),
- b.getIcon(),
- b.getVerticalAlignment(),
- b.getHorizontalAlignment(),
- b.getVerticalTextPosition(),
- b.getHorizontalTextPosition(),
- vr,
- ir,
- tr,
- gap);
-
- paintIcon(g, c, ir);
- paintText(g, c, tr, b.getText());
- paintFocus(g, c, vr, tr, ir);
- }
+ /**
+ * This method returns the minimum size of the {@link JComponent} given. If
+ * this method returns null, then it is up to the Layout Manager to give
+ * this component a minimum size.
+ *
+ * @param c The {@link JComponent} to get a minimum size for.
+ *
+ * @return The minimum size.
+ */
+ public Dimension getMinimumSize(JComponent c)
+ {
+ return getPreferredSize(c);
+ }
+
+ /**
+ * This method returns the maximum size of the {@link JComponent} given. If
+ * this method returns null, then it is up to the Layout Manager to give
+ * this component a maximum size.
+ *
+ * @param c The {@link JComponent} to get a maximum size for.
+ *
+ * @return The maximum size.
+ */
+ public Dimension getMaximumSize(JComponent c)
+ {
+ return getPreferredSize(c);
+ }
+ /**
+ * The method that paints the label according to its current state.
+ *
+ * @param g The {@link Graphics} object to paint with.
+ * @param c The {@link JComponent} to paint.
+ */
+ public void paint(Graphics g, JComponent c)
+ {
+ JLabel b = (JLabel) c;
- protected void paintFocus(Graphics g,
- JComponent c,
- Rectangle vr,
- Rectangle tr,
- Rectangle ir)
- {
- }
+ Font saved_font = g.getFont();
- protected void paintIcon(Graphics g,
- JComponent c,
- Rectangle iconRect)
- {
- JLabel b = (JLabel) c;
- if (b.getIcon() != null)
- {
- int x = iconRect.x;
- int y = iconRect.y;
-
- System.out.println("WE HAVE AN ICON: " + b.getIcon());
-
- b.getIcon().paintIcon(c, g, x, y);
- }
- else
- {
- //System.out.println("NO ICON FOR BUTTON:" + b.text);
- }
- }
+ Rectangle tr = new Rectangle();
+ Rectangle ir = new Rectangle();
+ Rectangle vr = new Rectangle();
+
+ Font f = c.getFont();
+
+ g.setFont(f);
+ FontMetrics fm = g.getFontMetrics(f);
+
+ vr = SwingUtilities.calculateInnerArea(c, vr);
+
+ if (vr.width < 0)
+ vr.width = 0;
+ if (vr.height < 0)
+ vr.height = 0;
+
+ Icon icon = (b.isEnabled()) ? b.getIcon() : b.getDisabledIcon();
+ String text = layoutCL(b, fm, b.getText(), icon, vr, ir, tr);
- protected void paintText(Graphics g,
- JComponent c,
- Rectangle textRect,
- String text)
+ if (b.isOpaque())
{
- // AbstractLabel b = (AbstractLabel) c;
-
- System.out.println("JLabel: drawing string: " + text + ", at:" + textRect);
-
- g.setColor(foreground);
- //g.setBackColor(new Color(190,190,190));
-
- g.drawLine(0,0,100,100);
-
- BasicGraphicsUtils.drawString(g, text, 0, 0 /*textRect.x*/, 0 /*textRect.y*/);
+ g.setColor(b.getBackground());
+ g.fillRect(vr.x, vr.y, vr.width, vr.height);
}
- public void propertyChange (PropertyChangeEvent event)
+ if (icon != null)
+ icon.paintIcon(b, g, ir.x, ir.y);
+ if (b.isEnabled())
+ paintEnabledText(b, g, text, tr.x, tr.y + fm.getAscent());
+ else
+ paintDisabledText(b, g, text, tr.x, tr.y + fm.getAscent());
+ g.setFont(saved_font);
+ }
+
+ /**
+ * This method is simply calls SwingUtilities's layoutCompoundLabel.
+ *
+ * @param label The label to lay out.
+ * @param fontMetrics The FontMetrics for the font used.
+ * @param text The text to paint.
+ * @param icon The icon to draw.
+ * @param viewR The entire viewable rectangle.
+ * @param iconR The icon bounds rectangle.
+ * @param textR The text bounds rectangle.
+ *
+ * @return A possibly clipped version of the text.
+ */
+ protected String layoutCL(JLabel label, FontMetrics fontMetrics,
+ String text, Icon icon, Rectangle viewR,
+ Rectangle iconR, Rectangle textR)
+ {
+ return SwingUtilities.layoutCompoundLabel(label, fontMetrics, text, icon,
+ label.getVerticalAlignment(),
+ label.getHorizontalAlignment(),
+ label.getVerticalTextPosition(),
+ label.getHorizontalTextPosition(),
+ viewR, iconR, textR,
+ label.getIconTextGap());
+ }
+
+ /**
+ * Paints the text if the label is disabled. By default, this paints the
+ * clipped text returned by layoutCompoundLabel using the
+ * background.brighter() color. It also paints the same text using the
+ * background.darker() color one pixel to the right and one pixel down.
+ *
+ * @param l The {@link JLabel} being painted.
+ * @param g The {@link Graphics} object to paint with.
+ * @param s The String to paint.
+ * @param textX The x coordinate of the start of the baseline.
+ * @param textY The y coordinate of the start of the baseline.
+ */
+ protected void paintDisabledText(JLabel l, Graphics g, String s, int textX,
+ int textY)
+ {
+ Color saved_color = g.getColor();
+
+ g.setColor(l.getBackground().brighter());
+
+ int mnemIndex = l.getDisplayedMnemonicIndex();
+
+ if (mnemIndex != -1)
+ BasicGraphicsUtils.drawStringUnderlineCharAt(g, s, mnemIndex, textX,
+ textY);
+ else
+ g.drawString(s, textX, textY);
+
+ g.setColor(l.getBackground().darker());
+ if (mnemIndex != -1)
+ BasicGraphicsUtils.drawStringUnderlineCharAt(g, s, mnemIndex, textX + 1,
+ textY + 1);
+ else
+ g.drawString(s, textX + 1, textY + 1);
+
+ g.setColor(saved_color);
+ }
+
+ /**
+ * Paints the text if the label is enabled. The text is painted using the
+ * foreground color.
+ *
+ * @param l The {@link JLabel} being painted.
+ * @param g The {@link Graphics} object to paint with.
+ * @param s The String to paint.
+ * @param textX The x coordinate of the start of the baseline.
+ * @param textY The y coordinate of the start of the baseline.
+ */
+ protected void paintEnabledText(JLabel l, Graphics g, String s, int textX,
+ int textY)
+ {
+ Color saved_color = g.getColor();
+ g.setColor(l.getForeground());
+
+ int mnemIndex = l.getDisplayedMnemonicIndex();
+
+ if (mnemIndex != -1)
+ BasicGraphicsUtils.drawStringUnderlineCharAt(g, s, mnemIndex, textX,
+ textY);
+ else
+ g.drawString(s, textX, textY);
+
+ g.setColor(saved_color);
+ }
+
+ /**
+ * This method installs the UI for the given {@link JComponent}. This
+ * method will install the component, defaults, listeners, and keyboard
+ * actions.
+ *
+ * @param c The {@link JComponent} that this UI is being installed on.
+ */
+ public void installUI(JComponent c)
+ {
+ super.installUI(c);
+ if (c instanceof JLabel)
+ {
+ JLabel l = (JLabel) c;
+
+ installComponents(l);
+ installDefaults(l);
+ installListeners(l);
+ installKeyboardActions(l);
+ }
+ }
+
+ /**
+ * This method uninstalls the UI for the given {@link JComponent}. This
+ * method will uninstall the component, defaults, listeners, and keyboard
+ * actions.
+ *
+ * @param c The {@link JComponent} that this UI is being installed on.
+ */
+ public void uninstallUI(JComponent c)
+ {
+ super.uninstallUI(c);
+ if (c instanceof JLabel)
+ {
+ JLabel l = (JLabel) c;
+
+ uninstallKeyboardActions(l);
+ uninstallListeners(l);
+ uninstallDefaults(l);
+ uninstallComponents(l);
+ }
+ }
+
+ /**
+ * This method installs the components for this {@link JLabel}.
+ *
+ * @param c The {@link JLabel} to install components for.
+ */
+ protected void installComponents(JLabel c)
+ {
+ //FIXME: fix javadoc + implement.
+ }
+
+ /**
+ * This method uninstalls the components for this {@link JLabel}.
+ *
+ * @param c The {@link JLabel} to uninstall components for.
+ */
+ protected void uninstallComponents(JLabel c)
+ {
+ //FIXME: fix javadoc + implement.
+ }
+
+ /**
+ * This method installs the defaults that are defined in the Basic look and
+ * feel for this {@link JLabel}.
+ *
+ * @param c The {@link JLabel} to install defaults for.
+ */
+ protected void installDefaults(JLabel c)
+ {
+ UIDefaults defaults = UIManager.getLookAndFeelDefaults();
+
+ c.setForeground(defaults.getColor("Label.foreground"));
+ c.setBackground(defaults.getColor("Label.background"));
+ c.setFont(defaults.getFont("Label.font"));
+ c.setBorder(defaults.getBorder("Label.border"));
+ //XXX: There are properties we don't use called disabledForeground
+ //and disabledShadow.
+ }
+
+ /**
+ * This method uninstalls the defaults that are defined in the Basic look
+ * and feel for this {@link JLabel}.
+ *
+ * @param c The {@link JLabel} to uninstall defaults for.
+ */
+ protected void uninstallDefaults(JLabel c)
+ {
+ c.setForeground(null);
+ c.setBackground(null);
+ c.setFont(null);
+ c.setBorder(null);
+ }
+
+ /**
+ * This method installs the keyboard actions for the given {@link JLabel}.
+ *
+ * @param l The {@link JLabel} to install keyboard actions for.
+ */
+ protected void installKeyboardActions(JLabel l)
+ {
+ //FIXME: implement.
+ }
+
+ /**
+ * This method uninstalls the keyboard actions for the given {@link JLabel}.
+ *
+ * @param l The {@link JLabel} to uninstall keyboard actions for.
+ */
+ protected void uninstallKeyboardActions(JLabel l)
+ {
+ //FIXME: implement.
+ }
+
+ /**
+ * This method installs the listeners for the given {@link JLabel}. The UI
+ * delegate only listens to the label.
+ *
+ * @param c The {@link JLabel} to install listeners for.
+ */
+ protected void installListeners(JLabel c)
+ {
+ c.addPropertyChangeListener(this);
+ }
+
+ /**
+ * This method uninstalls the listeners for the given {@link JLabel}. The UI
+ * delegate only listens to the label.
+ *
+ * @param c The {@link JLabel} to uninstall listeners for.
+ */
+ protected void uninstallListeners(JLabel c)
+ {
+ c.removePropertyChangeListener(this);
+ }
+
+ /**
+ * This method is called whenever any JLabel's that use this UI has one of
+ * their properties change.
+ *
+ * @param e The {@link PropertyChangeEvent} that describes the change.
+ */
+ public void propertyChange(PropertyChangeEvent e)
{
- throw new Error ("Not implemented");
+ JLabel c = (JLabel) e.getSource();
+ c.revalidate();
+ c.repaint();
}
}
diff --git a/libjava/javax/swing/plaf/basic/BasicListUI.java b/libjava/javax/swing/plaf/basic/BasicListUI.java
index 6b83a91..7a1f5a4 100644
--- a/libjava/javax/swing/plaf/basic/BasicListUI.java
+++ b/libjava/javax/swing/plaf/basic/BasicListUI.java
@@ -35,7 +35,6 @@ this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version. */
-
package javax.swing.plaf.basic;
import java.awt.Color;
@@ -44,141 +43,664 @@ import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.awt.event.MouseEvent;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.ListCellRenderer;
+import javax.swing.ListModel;
+import javax.swing.ListSelectionModel;
+import javax.swing.UIDefaults;
+import javax.swing.UIManager;
+import javax.swing.event.ListDataEvent;
+import javax.swing.event.ListDataListener;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.event.MouseInputListener;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.ListUI;
+
+/**
+ * The Basic Look and Feel UI delegate for the
+ * JList.
+ */
public class BasicListUI extends ListUI
{
- int gap_between_cells;
- Color textColor, disabledTextColor, pressedBackgroundColor, normalBackgroundColor;
-
+ /**
+ * A helper class which listens for {@link FocusEvents}
+ * from the JList.
+ */
+ class FocusHandler implements FocusListener
+ {
+ /**
+ * Called when the JList acquires focus.
+ *
+ * @param e The FocusEvent representing focus acquisition
+ */
+ public void focusGained(FocusEvent e)
+ {
+ repaintCellFocus();
+ }
- public static ComponentUI createUI(final JComponent c)
+ /**
+ * Called when the JList loses focus.
+ *
+ * @param e The FocusEvent representing focus loss
+ */
+ public void focusLost(FocusEvent e)
{
- return new BasicButtonUI();
+ repaintCellFocus();
}
-
- public void installUI(final JComponent c)
+ /**
+ * Helper method to repaint the focused cell's
+ * lost or acquired focus state.
+ */
+ void repaintCellFocus()
{
- super.installUI(c);
+ }
+ }
- textColor = new Color(0,0,0);
- disabledTextColor = new Color(130, 130, 130);
- pressedBackgroundColor = new Color(150,150,150);
- normalBackgroundColor = new Color(192,192,192);
+ /**
+ * A helper class which listens for {@link ListDataEvent}s generated by
+ * the {@link JList}'s {@link ListModel}.
+ *
+ * @see javax.swing.JList#model
+ */
+ class ListDataHandler implements ListDataListener
+ {
+ /**
+ * Called when a general change has happened in the model which cannot
+ * be represented in terms of a simple addition or deletion.
+ *
+ * @param e The event representing the change
+ */
+ public void contentsChanged(ListDataEvent e)
+ {
+ // System.err.println(this + ".contentsChanged(" + e + ")");
+ BasicListUI.this.damageLayout();
}
- public Dimension getPreferredSize(JComponent c)
+ /**
+ * Called when an interval of objects has been added to the model.
+ *
+ * @param e The event representing the addition
+ */
+ public void intervalAdded(ListDataEvent e)
{
- JList l = (JList) c;
-
- System.out.println("XXXXXXXXXXXXXXXxx getPreferredSize------------> " + l);
-
-
- int rows = l.getVisibleRowCount();
-
- ListCellRenderer render = l.getCellRenderer();
-
- int width = 200;
- int height = rows * 16;
-
- if (l.getModel().getSize() == 0)
- {
- return new Dimension(width, height);
- }
-
- System.out.println("BASIC_LIST_UI ====-> " + l.getModel().getElementAt(0));
-
- Component elt = render.getListCellRendererComponent(l,
- l.getModel().getElementAt(0),
- 0,
- false,
- false);
- Dimension a = elt.getPreferredSize();
- if (a == null)
- {
- return new Dimension(width, height);
- }
-
- return new Dimension(a.width,
- a.height * rows);
+ // System.err.println(this + ".intervalAdded(" + e + ")");
+ BasicListUI.this.damageLayout();
}
- public void paintBackground(Graphics g,
- JComponent c)
+ /**
+ * Called when an inteval of objects has been removed from the model.
+ *
+ * @param e The event representing the removal
+ */
+ public void intervalRemoved(ListDataEvent e)
{
- Dimension size = getPreferredSize(c);
+ // System.err.println(this + ".intervalRemoved(" + e + ")");
+ BasicListUI.this.damageLayout();
+ }
+ }
- g.setColor(normalBackgroundColor);
- g.fillRect(0,0,size.width, size.height);
+ /**
+ * A helper class which listens for {@link ListSelectionEvent}s
+ * from the {@link JList}'s {@link ListSelectionModel}.
+ */
+ class ListSelectionHandler implements ListSelectionListener
+ {
+ /**
+ * Called when the list selection changes.
+ *
+ * @param e The event representing the change
+ */
+ public void valueChanged(ListSelectionEvent e)
+ {
+ // System.err.println(this + ".valueChanged(" + e + ")");
}
+ }
- public void paint(Graphics g,
- JComponent c)
- {
- JList l = (JList) c;
+ /**
+ * A helper class which listens for {@link MouseEvent}s
+ * from the {@link JList}.
+ */
+ class MouseInputHandler implements MouseInputListener
+ {
+ /**
+ * Called when a mouse button press/release cycle completes
+ * on the {@link JList}
+ *
+ * @param event The event representing the mouse click
+ */
+ public void mouseClicked(MouseEvent event)
+ {
+ }
- int rows = l.getVisibleRowCount();
+ /**
+ * Called when a mouse button is pressed down on the
+ * {@link JList}.
+ *
+ * @param event The event representing the mouse press
+ */
+ public void mousePressed(MouseEvent event)
+ {
+ // System.err.println("got mouse click event " + event);
+ int row = BasicListUI.this.convertYToRow(event.y);
+ if (row == -1)
+ return;
- ListCellRenderer render = l.getCellRenderer();
+ // System.err.println("clicked on row " + row);
+ BasicListUI.this.list.setSelectedIndex(row);
+ }
- System.out.println("RENDER-JLIST: " + rows + ", " + l.getModel().getSize());
+ /**
+ * Called when a mouse button is released on
+ * the {@link JList}
+ *
+ * @param event The event representing the mouse press
+ */
+ public void mouseReleased(MouseEvent event)
+ {
+ }
- paintBackground(g, c);
+ /**
+ * Called when the mouse pointer enters the area bounded
+ * by the {@link JList}
+ *
+ * @param event The event representing the mouse entry
+ */
+ public void mouseEntered(MouseEvent event)
+ {
+ }
- if (l.getModel().getSize() == 0)
- return;
+ /**
+ * Called when the mouse pointer leaves the area bounded
+ * by the {@link JList}
+ *
+ * @param event The event representing the mouse exit
+ */
+ public void mouseExited(MouseEvent event)
+ {
+ }
- // use element 0 to figure out how big we are:
- Component elt = render.getListCellRendererComponent(l,
- l.getModel().getElementAt(0),
- 0,
- false,
- false);
- Dimension dim = elt.getPreferredSize();
-
- Rectangle a = new Rectangle(0,
- 0,
- dim.width,
- dim.height);
+ /**
+ * Called when the mouse pointer moves over the area bounded
+ * by the {@link JList} while a button is held down.
+ *
+ * @param event The event representing the mouse drag
+ */
+ public void mouseDragged(MouseEvent event)
+ {
+ }
+
+ /**
+ * Called when the mouse pointer moves over the area bounded
+ * by the {@link JList}.
+ *
+ * @param event The event representing the mouse move
+ */
+ public void mouseMoved(MouseEvent event)
+ {
+ }
+ }
- for (int i=0;i<l.getModel().getSize();i++)
- {
- boolean is_sel = false;
- boolean has_focus = false;
+ /**
+ * Helper class which listens to {@link PropertyChangeEvent}s
+ * from the {@link JList}.
+ */
+ class PropertyChangeHandler implements PropertyChangeListener
+ {
+ /**
+ * Called when the {@link JList} changes one of its bound properties.
+ *
+ * @param e The event representing the property change
+ */
+ public void propertyChange(PropertyChangeEvent e)
+ {
+ // System.err.println(this + ".propertyChange(" + e + ")");
+ if (e.source == BasicListUI.this.list)
+ {
+ if (e.oldValue != null && e.oldValue instanceof ListModel)
+ ((ListModel) e.oldValue).removeListDataListener(BasicListUI.this.listDataListener);
+
+ if (e.newValue != null && e.newValue instanceof ListModel)
+ ((ListModel) e.newValue).addListDataListener(BasicListUI.this.listDataListener);
+ }
+ BasicListUI.this.damageLayout();
+ }
+ }
- Component comp = render.getListCellRendererComponent(l,
- l.getModel().getElementAt(i),
- i,
- is_sel,
- has_focus);
+ /**
+ * Creates a new BasicListUI for the component.
+ *
+ * @param c The component to create a UI for
+ *
+ * @return A new UI
+ */
+ public static ComponentUI createUI(final JComponent c)
+ {
+ return new BasicListUI();
+ }
- //System.out.println("AAAAA=> " + a + ", " + comp + ", index = " + i);
+ /** The current focus listener. */
+ FocusHandler focusListener;
+
+ /** The data listener listening to the model. */
+ ListDataHandler listDataListener;
+
+ /** The selection listener listening to the selection model. */
+ ListSelectionHandler listSelectionListener;
+
+ /** The mouse listener listening to the list. */
+ MouseInputHandler mouseInputListener;
+
+ /** The property change listener listening to the list. */
+ PropertyChangeHandler propertyChangeListener;
+
+ /** Saved reference to the list this UI was created for. */
+ JList list;
+
+ /** The height of a single cell in the list. */
+ int cellHeight;
+
+ /** The width of a single cell in the list. */
+ int cellWidth;
+
+ /**
+ * An array of varying heights of cells in the list, in cases where each
+ * cell might have a different height.
+ */
+ int[] cellHeights;
+
+ /**
+ * A simple counter. When nonzero, indicates that the UI class is out of
+ * date with respect to the underlying list, and must recalculate the
+ * list layout before painting or performing size calculations.
+ */
+ int updateLayoutStateNeeded;
+
+ /**
+ * Calculate the height of a particular row. If there is a fixed {@link
+ * #cellHeight}, return it; otherwise return the specific row height
+ * requested from the {@link #cellHeights} array. If the requested row
+ * is invalid, return <code>-1</code>.
+ *
+ * @param row The row to get the height of
+ *
+ * @return The height, in pixels, of the specified row
+ */
+ int getRowHeight(int row)
+ {
+ if (row < 0 || row >= cellHeights.length)
+ return -1;
+ else if (cellHeight != -1)
+ return cellHeight;
+ else
+ return cellHeights[row];
+ }
- comp.setBounds(a);
+ /**
+ * Calculate the bounds of a particular cell, considering the upper left
+ * corner of the list as the origin position <code>(0,0)</code>.
+ *
+ * @param l Ignored; calculates over <code>this.list</code>
+ * @param index1 The first row to include in the bounds
+ * @param index2 The last row to incude in the bounds
+ *
+ * @return A rectangle encompassing the range of rows between
+ * <code>index1</code> and <code>index2</code> inclusive
+ */
+ public Rectangle getCellBounds(JList l, int index1, int index2)
+ {
+ if (l != list || cellWidth == -1)
+ return null;
+
+ int lo = Math.min(index1, index2);
+ int hi = Math.max(index1, index2);
+ Rectangle lobounds = new Rectangle(0, convertRowToY(lo), cellWidth,
+ getRowHeight(lo));
+ Rectangle hibounds = new Rectangle(0, convertRowToY(hi), cellWidth,
+ getRowHeight(hi));
+ return lobounds.union(hibounds);
+ }
- comp.paint(g);
+ /**
+ * Calculate the Y coordinate of the upper edge of a particular row,
+ * considering the Y coordinate <code>0</code> to occur at the top of the
+ * list.
+ *
+ * @param row The row to calculate the Y coordinate of
+ *
+ * @return The Y coordinate of the specified row, or <code>-1</code> if
+ * the specified row number is invalid
+ */
+ int convertRowToY(int row)
+ {
+ int y = 0;
+ for (int i = 0; i < row; ++i)
+ {
+ int h = getRowHeight(i);
+ if (h == -1)
+ return -1;
+ y += h;
+ }
+ return y;
+ }
- a.y += dim.height + gap_between_cells;
- }
- }
+ /**
+ * Calculate the row number containing a particular Y coordinate,
+ * considering the Y coodrinate <code>0</code> to occur at the top of the
+ * list.
+ *
+ * @param y0 The Y coordinate to calculate the row number for
+ *
+ * @return The row number containing the specified Y value, or <code>-1</code>
+ * if the specified Y coordinate is invalid
+ */
+ int convertYToRow(int y0)
+ {
+ for (int row = 0; row < cellHeights.length; ++row)
+ {
+ int h = getRowHeight(row);
+
+ // System.err.println("convertYToRow(" + y0 + ") vs. " + h);
+ if (y0 < h)
+ return row;
+ y0 -= h;
+ }
+ return -1;
+ }
- public int locationToIndex(JList list, Point location)
+ /**
+ * Recomputes the {@link #cellHeights}, {@link #cellHeight}, and {@link
+ * #cellWidth} properties by examining the variouis properties of the
+ * {@link JList}.
+ */
+ void updateLayoutState()
{
- throw new Error ("Not implemented");
+ int nrows = list.getModel().getSize();
+ cellHeight = -1;
+ cellWidth = -1;
+ if (cellHeights == null || cellHeights.length != nrows)
+ cellHeights = new int[nrows];
+ if (list.getFixedCellHeight() == -1 || list.getFixedCellWidth() == -1)
+ {
+ ListCellRenderer rend = list.getCellRenderer();
+ for (int i = 0; i < nrows; ++i)
+ {
+ Component flyweight = rend.getListCellRendererComponent(list,
+ list.getModel()
+ .getElementAt(i),
+ 0, false,
+ false);
+ Dimension dim = flyweight.getPreferredSize();
+ cellHeights[i] = dim.height;
+ cellWidth = Math.max(cellWidth, dim.width);
+ }
+ }
+ else
+ {
+ cellHeight = list.getFixedCellHeight();
+ cellWidth = list.getFixedCellWidth();
+ }
}
- public Point indexToLocation(JList list, int index)
+ /**
+ * Marks the current layout as damaged and requests revalidation from the
+ * JList.
+ *
+ * @see #updateLayoutStateNeeded
+ */
+ void damageLayout()
+ {
+ updateLayoutStateNeeded = 1;
+ list.revalidate();
+ }
+
+ /**
+ * Calls {@link #updateLayoutState} if {@link #updateLayoutStateNeeded}
+ * is nonzero, then resets {@link #updateLayoutStateNeeded} to zero.
+ */
+ void maybeUpdateLayoutState()
{
- throw new Error ("Not implemented");
+ // System.err.println(this + ".maybeUpdateLayoutState()");
+ if (updateLayoutStateNeeded != 0)
+ {
+ updateLayoutState();
+ updateLayoutStateNeeded = 0;
+ }
}
- public Rectangle getCellBounds(JList list, int index1, int index2)
+ /**
+ * Creates a new BasicListUI object.
+ */
+ public BasicListUI()
+ {
+ focusListener = new FocusHandler();
+ listDataListener = new ListDataHandler();
+ listSelectionListener = new ListSelectionHandler();
+ mouseInputListener = new MouseInputHandler();
+ propertyChangeListener = new PropertyChangeHandler();
+ updateLayoutStateNeeded = 1;
+ }
+
+ /**
+ * Installs various default settings (mostly colors) from the {@link
+ * UIDefaults} into the {@link JList}
+ *
+ * @see #uninstallDefaults
+ */
+ 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"));
+ }
+
+ /**
+ * Resets to <code>null</code> those defaults which were installed in
+ * {@link #installDefaults}
+ */
+ void uninstallDefaults()
+ {
+ UIDefaults defaults = UIManager.getLookAndFeelDefaults();
+ list.setForeground(null);
+ list.setBackground(null);
+ list.setSelectionForeground(null);
+ list.setSelectionBackground(null);
+ }
+
+ /**
+ * Attaches all the listeners we have in the UI class to the {@link
+ * JList}, its model and its selection model.
+ *
+ * @see #uninstallListeners
+ */
+ void installListeners()
+ {
+ list.addFocusListener(focusListener);
+ list.getModel().addListDataListener(listDataListener);
+ list.addListSelectionListener(listSelectionListener);
+ list.addMouseListener(mouseInputListener);
+ list.addMouseMotionListener(mouseInputListener);
+ list.addPropertyChangeListener(propertyChangeListener);
+ }
+
+ /**
+ * Detaches all the listeners we attached in {@link #installListeners}.
+ */
+ void uninstallListeners()
+ {
+ list.removeFocusListener(focusListener);
+ list.getModel().removeListDataListener(listDataListener);
+ list.removeListSelectionListener(listSelectionListener);
+ list.removeMouseListener(mouseInputListener);
+ list.removeMouseMotionListener(mouseInputListener);
+ list.removePropertyChangeListener(propertyChangeListener);
+ }
+
+ /**
+ * Installs keyboard actions for this UI in the {@link JList}.
+ */
+ void installKeyboardActions()
+ {
+ }
+
+ /**
+ * Uninstalls keyboard actions for this UI in the {@link JList}.
+ */
+ void uninstallKeyboardActions()
+ {
+ }
+
+ /**
+ * Installs the various aspects of the UI in the {@link JList}. In
+ * particular, calls {@link #installDefaults}, {@link #installListeners}
+ * and {@link #installKeyboardActions}. Also saves a reference to the
+ * provided component, cast to a {@link JList}.
+ *
+ * @param c The {@link JList} to install the UI into
+ */
+ public void installUI(final JComponent c)
+ {
+ super.installUI(c);
+ list = (JList) c;
+ installDefaults();
+ installListeners();
+ installKeyboardActions();
+ // System.err.println(this + ".installUI()");
+ maybeUpdateLayoutState();
+ }
+
+ /**
+ * Uninstalls all the aspects of the UI which were installed in {@link
+ * #installUI}. When finished uninstalling, drops the saved reference to
+ * the {@link JList}.
+ *
+ * @param c Ignored; the UI is uninstalled from the {@link JList}
+ * reference saved during the call to {@link #installUI}
+ */
+ public void uninstallUI(final JComponent c)
+ {
+ uninstallKeyboardActions();
+ uninstallListeners();
+ uninstallDefaults();
+ list = null;
+ }
+
+ /**
+ * Gets the maximum size this list can assume.
+ *
+ * @param c The component to measure the size of
+ *
+ * @return A new Dimension representing the component's maximum size
+ */
+ public Dimension getMaximumSize(JComponent c)
+ {
+ return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
+ }
+
+ /**
+ * Gets the size this list would prefer to assume. This is calculated by
+ * calling {@link #getCellBounds} over the entire list.
+ *
+ * @param c Ignored; uses the saved {@link JList} reference
+ *
+ * @return DOCUMENT ME!
+ */
+ public Dimension getPreferredSize(JComponent c)
+ {
+ maybeUpdateLayoutState();
+ if (list.getModel().getSize() == 0)
+ return new Dimension(0, 0);
+ Rectangle bounds = getCellBounds(list, 0, list.getModel().getSize() - 1);
+ return bounds.getSize();
+ }
+
+ /**
+ * 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
+ */
+ public void paintBackground(Graphics g, JComponent c)
+ {
+ Dimension size = getPreferredSize(c);
+ Color save = g.getColor();
+ g.setColor(c.getBackground());
+ g.fillRect(0, 0, size.width, size.height);
+ g.setColor(save);
+ }
+
+ /**
+ * Paints a single cell in the list.
+ *
+ * @param g The graphics context to paint in
+ * @param row The row number to paint
+ * @param bounds The bounds of the cell to paint, assuming a coordinate
+ * system beginning at <code>(0,0)</code> in the upper left corner of the
+ * list
+ * @param rend A cell renderer to paint with
+ * @param data The data to provide to the cell renderer
+ * @param sel A selection model to provide to the cell renderer
+ * @param lead The lead selection index of the list
+ */
+ void paintCell(Graphics g, int row, Rectangle bounds, ListCellRenderer rend,
+ ListModel data, ListSelectionModel sel, int lead)
+ {
+ boolean is_sel = list.isSelectedIndex(row);
+ boolean has_focus = false;
+ Component comp = rend.getListCellRendererComponent(list,
+ data.getElementAt(row),
+ 0, is_sel, has_focus);
+ g.translate(bounds.x, bounds.y);
+ comp.setBounds(new Rectangle(0, 0, bounds.width, bounds.height));
+ comp.paint(g);
+ g.translate(-bounds.x, -bounds.y);
+ }
+
+ /**
+ * Paints the list by calling {@link #paintBackground} and then repeatedly
+ * calling {@link #paintCell} for each visible cell in the list.
+ *
+ * @param g The graphics context to paint with
+ * @param c Ignored; uses the saved {@link JList} reference
+ */
+ public void paint(Graphics g, JComponent c)
+ {
+ int nrows = Math.min(list.getVisibleRowCount(), list.getModel().getSize());
+ if (nrows == 0)
+ return;
+
+ maybeUpdateLayoutState();
+ ListCellRenderer render = list.getCellRenderer();
+ ListModel model = list.getModel();
+ ListSelectionModel sel = list.getSelectionModel();
+ int lead = sel.getLeadSelectionIndex();
+ paintBackground(g, list);
+
+ for (int row = 0; row < nrows; ++row)
+ {
+ Rectangle bounds = getCellBounds(list, row, row);
+ paintCell(g, row, bounds, render, model, sel, lead);
+ }
+ }
+
+ public int locationToIndex(JList list, Point location)
+ {
+ throw new Error("Not implemented");
+ }
+
+ public Point indexToLocation(JList list, int index)
{
- throw new Error ("Not implemented");
+ throw new Error("Not implemented");
}
}
diff --git a/libjava/javax/swing/plaf/basic/BasicLookAndFeel.java b/libjava/javax/swing/plaf/basic/BasicLookAndFeel.java
index 901ea51..c4d3d80 100644
--- a/libjava/javax/swing/plaf/basic/BasicLookAndFeel.java
+++ b/libjava/javax/swing/plaf/basic/BasicLookAndFeel.java
@@ -226,6 +226,13 @@ public abstract class BasicLookAndFeel extends LookAndFeel
protected void initComponentDefaults(UIDefaults defaults)
{
Object[] uiDefaults;
+
+ // The JDK's default L&F happens to use these three purple shades
+ // extensively.
+ Color lightPurple = new Color(0xCC, 0xCC, 0xFF);
+ Color midPurple = new Color(0x99, 0x99, 0xCC);
+ Color darkPurple = new Color(0x66, 0x66, 0x99);
+
uiDefaults = new Object[] {
"AbstractUndoableEdit.undoText", "Undo",
@@ -275,8 +282,8 @@ public abstract class BasicLookAndFeel extends LookAndFeel
"CheckBoxMenuItem.font", new FontUIResource("Dialog", Font.PLAIN, 12),
"CheckBoxMenuItem.foreground", new ColorUIResource(Color.black),
"CheckBoxMenuItem.margin", new InsetsUIResource(2, 2, 2, 2),
- "CheckBoxMenuItem.selectionBackground", new ColorUIResource(0, 0, 128),
- "CheckBoxMenuItem.selectionForeground", new ColorUIResource(Color.white),
+ "CheckBoxMenuItem.selectionBackground", new ColorUIResource(lightPurple),
+ "CheckBoxMenuItem.selectionForeground", new ColorUIResource(Color.black),
"ColorChooser.background", new ColorUIResource(Color.lightGray),
"ColorChooser.cancelText", "Cancel",
"ColorChooser.font", new FontUIResource("Dialog", Font.PLAIN, 12),
@@ -316,8 +323,8 @@ public abstract class BasicLookAndFeel extends LookAndFeel
"ComboBox.disabledForeground", new ColorUIResource(Color.gray),
"ComboBox.font", new FontUIResource("SansSerif", Font.PLAIN, 12),
"ComboBox.foreground", new ColorUIResource(Color.black),
- "ComboBox.selectionBackground", new ColorUIResource(0, 0, 128),
- "ComboBox.selectionForeground", new ColorUIResource(Color.white),
+ "ComboBox.selectionBackground", new ColorUIResource(lightPurple),
+ "ComboBox.selectionForeground", new ColorUIResource(Color.black),
"Desktop.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] {
"KP_LEFT", "left",
"KP_RIGHT", "right",
@@ -412,8 +419,8 @@ public abstract class BasicLookAndFeel extends LookAndFeel
"FocusManagerClassName", "TODO",
"FormView.resetButtonText", "Reset",
"FormView.submitButtonText", "Submit Query",
- "InternalFrame.activeTitleBackground", new ColorUIResource(0, 0, 128),
- "InternalFrame.activeTitleForeground", new ColorUIResource(Color.white),
+ "InternalFrame.activeTitleBackground", new ColorUIResource(lightPurple),
+ "InternalFrame.activeTitleForeground", new ColorUIResource(Color.black),
"InternalFrame.border", new BorderUIResource.CompoundBorderUIResource(null,
null),
"InternalFrame.closeIcon", BasicIconFactory.createEmptyFrameIcon(),
@@ -434,6 +441,9 @@ public abstract class BasicLookAndFeel extends LookAndFeel
"Label.disabledForeground", new ColorUIResource(Color.white),
"Label.disabledShadow", new ColorUIResource(Color.gray),
"Label.font", new FontUIResource("Dialog", Font.PLAIN, 12),
+ "Label.foreground", new ColorUIResource(Color.black),
+ "List.background", new ColorUIResource(Color.white),
+ "List.border", new BasicBorders.MarginBorder(),
"List.focusInputMap", new UIDefaults.LazyInputMap(new Object[] {
"PAGE_UP", "scrollUp",
"ctrl \\", "clearSelection",
@@ -455,8 +465,8 @@ public abstract class BasicLookAndFeel extends LookAndFeel
"KP_DOWN", "selectNextRow"
}),
"List.foreground", new ColorUIResource(Color.black),
- "List.selectionBackground", new ColorUIResource(0, 0, 128),
- "List.selectionForeground", new ColorUIResource(Color.white),
+ "List.selectionBackground", new ColorUIResource(0xCC, 0xCC, 0xFF),
+ "List.selectionForeground", new ColorUIResource(Color.black),
"Menu.acceleratorFont", new FontUIResource("Dialog", Font.PLAIN, 12),
"Menu.acceleratorForeground", new ColorUIResource(Color.black),
"Menu.acceleratorSelectionForeground", new ColorUIResource(Color.white),
@@ -482,8 +492,8 @@ public abstract class BasicLookAndFeel extends LookAndFeel
"ENTER", "return",
"SPACE", "return"
},
- "Menutext.selectionBackground", new ColorUIResource(0, 0, 128),
- "Menu.selectionForeground", new ColorUIResource(Color.white),
+ "Menutext.selectionBackground", new ColorUIResource(lightPurple),
+ "Menu.selectionForeground", new ColorUIResource(Color.black),
"MenuBar.background", new ColorUIResource(Color.lightGray),
"MenuBar.border", new BasicBorders.MenuBarBorder(null, null),
"MenuBar.font", new FontUIResource("Dialog", Font.PLAIN, 12),
@@ -503,8 +513,8 @@ public abstract class BasicLookAndFeel extends LookAndFeel
"MenuItem.font", new FontUIResource("Dialog", Font.PLAIN, 12),
"MenuItem.foreground", new ColorUIResource(Color.black),
"MenuItem.margin", new InsetsUIResource(2, 2, 2, 2),
- "MenuItem.selectionBackground", new ColorUIResource(0, 0, 128),
- "MenuItem.selectionForeground", new ColorUIResource(Color.white),
+ "MenuItem.selectionBackground", new ColorUIResource(lightPurple),
+ "MenuItem.selectionForeground", new ColorUIResource(Color.black),
"OptionPane.background", new ColorUIResource(Color.lightGray),
"OptionPane.border", new BorderUIResource.EmptyBorderUIResource(0, 0, 0, 0),
"OptionPane.buttonAreaBorder", new BorderUIResource.EmptyBorderUIResource(0, 0, 0, 0),
@@ -544,8 +554,8 @@ public abstract class BasicLookAndFeel extends LookAndFeel
0),
"notify-field-accept")},
"PasswordField.margin", new InsetsUIResource(0, 0, 0, 0),
- "PasswordField.selectionBackground", new ColorUIResource(0, 0, 128),
- "PasswordField.selectionForeground", new ColorUIResource(Color.white),
+ "PasswordField.selectionBackground", new ColorUIResource(lightPurple),
+ "PasswordField.selectionForeground", new ColorUIResource(Color.black),
"PopupMenu.background", new ColorUIResource(Color.lightGray),
"PopupMenu.border", new BorderUIResource.BevelBorderUIResource(0),
"PopupMenu.font", new FontUIResource("Dialog", Font.PLAIN, 12),
@@ -555,9 +565,11 @@ public abstract class BasicLookAndFeel extends LookAndFeel
"ProgressBar.cellLength", new Integer(1),
"ProgressBar.cellSpacing", new Integer(0),
"ProgressBar.font", new FontUIResource("Dialog", Font.PLAIN, 12),
- "ProgressBar.foreground", new ColorUIResource(0, 0, 128),
- "ProgressBar.selectionBackground", new ColorUIResource(0, 0, 128),
+ "ProgressBar.foreground", new ColorUIResource(midPurple),
+ "ProgressBar.selectionBackground", new ColorUIResource(lightPurple),
"ProgressBar.selectionForeground", new ColorUIResource(Color.lightGray),
+ "ProgressBar.repaintInterval", new Integer(250),
+ "ProgressBar.cycleTime", new Integer(6000),
"RadioButton.background", new ColorUIResource(Color.lightGray),
"RadioButton.border", new BorderUIResource.CompoundBorderUIResource(null,
null),
@@ -587,8 +599,8 @@ public abstract class BasicLookAndFeel extends LookAndFeel
"RadioButtonMenuItem.font", new FontUIResource("Dialog", Font.PLAIN, 12),
"RadioButtonMenuItem.foreground", new ColorUIResource(Color.black),
"RadioButtonMenuItem.margin", new InsetsUIResource(2, 2, 2, 2),
- "RadioButtonMenuItem.selectionBackground", new ColorUIResource(0, 0, 128),
- "RadioButtonMenuItem.selectionForeground", new ColorUIResource(Color.white),
+ "RadioButtonMenuItem.selectionBackground", new ColorUIResource(lightPurple),
+ "RadioButtonMenuItem.selectionForeground", new ColorUIResource(Color.black),
"RootPane.defaultButtonWindowKeyBindings", new Object[] {
"ENTER", "press",
"released ENTER", "release",
@@ -663,6 +675,9 @@ public abstract class BasicLookAndFeel extends LookAndFeel
"Slider.foreground", new ColorUIResource(Color.lightGray),
"Slider.highlight", new ColorUIResource(Color.white),
"Slider.shadow", new ColorUIResource(Color.gray),
+ "Slider.thumbHeight", new Integer(20),
+ "Slider.thumbWidth", new Integer(10),
+ "Slider.tickHeight", new Integer(12),
"SplitPane.ancestorInputMap", new UIDefaults.LazyInputMap(new Object[] {
"F6", "toggleFocus",
"F8", "startResize",
@@ -762,8 +777,8 @@ public abstract class BasicLookAndFeel extends LookAndFeel
"Table.foreground", new ColorUIResource(Color.black),
"Table.gridColor", new ColorUIResource(Color.gray),
"Table.scrollPaneBorder", new BorderUIResource.BevelBorderUIResource(0),
- "Table.selectionBackground", new ColorUIResource(0, 0, 128),
- "Table.selectionForeground", new ColorUIResource(Color.white),
+ "Table.selectionBackground", new ColorUIResource(lightPurple),
+ "Table.selectionForeground", new ColorUIResource(Color.black),
"TableHeader.background", new ColorUIResource(Color.lightGray),
"TableHeader.cellBorder", new BorderUIResource.BevelBorderUIResource(0),
"TableHeader.font", new FontUIResource("Dialog", Font.PLAIN, 12),
@@ -790,8 +805,8 @@ public abstract class BasicLookAndFeel extends LookAndFeel
0), "insert-tab")
},
"TextArea.margin", new InsetsUIResource(0, 0, 0, 0),
- "TextArea.selectionBackground", new ColorUIResource(0, 0, 128),
- "TextArea.selectionForeground", new ColorUIResource(Color.white),
+ "TextArea.selectionBackground", new ColorUIResource(lightPurple),
+ "TextArea.selectionForeground", new ColorUIResource(Color.black),
"TextField.background", new ColorUIResource(Color.white),
"TextField.border", new BasicBorders.FieldBorder(null, null, null, null),
"TextField.caretBlinkRate", new Integer(500),
@@ -804,8 +819,8 @@ public abstract class BasicLookAndFeel extends LookAndFeel
0),
"notify-field-accept")},
"TextField.margin", new InsetsUIResource(0, 0, 0, 0),
- "TextField.selectionBackground", new ColorUIResource(0, 0, 128),
- "TextField.selectionForeground", new ColorUIResource(Color.white),
+ "TextField.selectionBackground", new ColorUIResource(lightPurple),
+ "TextField.selectionForeground", new ColorUIResource(Color.black),
"TextPane.background", new ColorUIResource(Color.white),
"TextPane.border", new BasicBorders.MarginBorder(),
"TextPane.caretBlinkRate", new Integer(500),
@@ -931,9 +946,9 @@ public abstract class BasicLookAndFeel extends LookAndFeel
"Tree.rightChildIndent", new Integer(13),
"Tree.rowHeight", new Integer(16),
"Tree.scrollsOnExpand", Boolean.TRUE,
- "Tree.selectionBackground", new ColorUIResource(0, 0, 128),
+ "Tree.selectionBackground", new ColorUIResource(lightPurple),
"Tree.selectionBorderColor", new ColorUIResource(Color.black),
- "Tree.selectionForeground", new ColorUIResource(Color.white),
+ "Tree.selectionForeground", new ColorUIResource(Color.black),
"Tree.textBackground", new ColorUIResource(Color.lightGray),
"Tree.textForeground", new ColorUIResource(Color.black),
"Viewport.background", new ColorUIResource(Color.lightGray),
diff --git a/libjava/javax/swing/plaf/basic/BasicProgressBarUI.java b/libjava/javax/swing/plaf/basic/BasicProgressBarUI.java
new file mode 100644
index 0000000..bf5cd0a
--- /dev/null
+++ b/libjava/javax/swing/plaf/basic/BasicProgressBarUI.java
@@ -0,0 +1,820 @@
+/* BasicProgressBarUI.java
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.plaf.basic;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Insets;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import javax.swing.JComponent;
+import javax.swing.JProgressBar;
+import javax.swing.SwingConstants;
+import javax.swing.SwingUtilities;
+import javax.swing.Timer;
+import javax.swing.UIDefaults;
+import javax.swing.UIManager;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.ProgressBarUI;
+
+
+/**
+ * The Basic Look and Feel UI delegate for the
+ * JProgressBar.
+ */
+public class BasicProgressBarUI extends ProgressBarUI
+{
+ /**
+ * A helper class that listens for ChangeEvents
+ * from the progressBar's model.
+ */
+ protected class ChangeHandler implements ChangeListener
+ {
+ /**
+ * Called every time the state of the model changes.
+ *
+ * @param e The ChangeEvent given by the model.
+ */
+ public void stateChanged(ChangeEvent e)
+ {
+ // Nothing to do but repaint.
+ progressBar.repaint();
+ }
+ }
+
+ /**
+ * This helper class is used to listen for
+ * PropertyChangeEvents from the progressBar.
+ */
+ private class PropertyChangeHandler implements PropertyChangeListener
+ {
+ /**
+ * Called every time the properties of the
+ * progressBar change.
+ *
+ * @param e The PropertyChangeEvent given by the progressBar.
+ */
+ public void propertyChange(PropertyChangeEvent e)
+ {
+ // Only need to listen for indeterminate changes.
+ // All other things are done on a repaint.
+ if (e.getPropertyName().equals(JProgressBar.INDETERMINATE_CHANGED_PROPERTY))
+ if (((Boolean) e.getNewValue()).booleanValue())
+ startAnimationTimer();
+ else
+ stopAnimationTimer();
+ else
+ progressBar.repaint();
+ }
+ }
+
+ /**
+ * This helper class is used to listen for
+ * the animationTimer's intervals. On every interval,
+ * the bouncing box should move.
+ */
+ private class Animator implements ActionListener
+ {
+ /**
+ * Called every time the animationTimer reaches
+ * its interval.
+ *
+ * @param e The ActionEvent given by the timer.
+ */
+ public void actionPerformed(ActionEvent e)
+ {
+ // Incrementing the animation index will cause
+ // a repaint.
+ incrementAnimationIndex();
+ }
+ }
+
+ /** The timer used to move the bouncing box. */
+ private transient Timer animationTimer = new Timer();
+
+
+ // The total number of frames must be an even number.
+ // The total number of frames is calculated from
+ // the cycleTime and repaintInterval given by
+ // the basic L&F's defaults.
+ //
+ // +-----------------------------------------------+
+ // | frame0 | frame1 | frame2 | frame 3 | frame 4 |
+ // | | frame7 | frame6 | frame 5 | |
+ // +-----------------------------------------------+
+
+ /** The current animation index. */
+ private transient int animationIndex;
+
+ /** The total number of frames.*/
+ private transient int numFrames;
+
+ /** The helper that moves the bouncing box. */
+ private transient Animator animation;
+
+ /** The helper that listens for property change events. */
+ private transient PropertyChangeHandler propertyListener;
+
+ /** The Listener for the model. */
+ protected ChangeListener changeListener;
+
+ /** The progressBar for this UI. */
+ protected JProgressBar progressBar;
+
+ /** The length of the cell. The cell is the painted part. */
+ private transient int cellLength;
+
+ /** The gap between cells. */
+ private transient int cellSpacing;
+
+ /** The color of the text when the bar is not over it.*/
+ private transient Color selectionBackground;
+
+ /** The color of the text when the bar is over it. */
+ private transient Color selectionForeground;
+
+ /**
+ * Creates a new BasicProgressBarUI object.
+ */
+ public BasicProgressBarUI()
+ {
+ super();
+ }
+
+ /**
+ * Creates a new BasicProgressBarUI for the component.
+ *
+ * @param x The JComponent to create the UI for.
+ *
+ * @return A new BasicProgressBarUI.
+ */
+ public static ComponentUI createUI(JComponent x)
+ {
+ return new BasicProgressBarUI();
+ }
+
+ /**
+ * This method returns the length of the bar (from the minimum)
+ * in pixels (or units that the Graphics object draws in) based
+ * on the progressBar's getPercentComplete() value.
+ *
+ * @param b The insets of the progressBar.
+ * @param width The width of the progressBar.
+ * @param height The height of the progressBar.
+ *
+ * @return The length of the bar that should be painted in pixels.
+ */
+ protected int getAmountFull(Insets b, int width, int height)
+ {
+ double percentDone = progressBar.getPercentComplete();
+ if (progressBar.getOrientation() == JProgressBar.HORIZONTAL)
+ return (int) (percentDone * (width - b.left - b.right));
+ else
+ return (int) (percentDone * (height - b.top - b.bottom));
+ }
+
+ /**
+ * The current animation index.
+ *
+ * @return The current animation index.
+ */
+ protected int getAnimationIndex()
+ {
+ return animationIndex;
+ }
+
+ /**
+ * This method returns the size and position of the bouncing box
+ * for the current animation index. It stores the values in the
+ * given rectangle and returns it. It returns null if no box should
+ * be drawn.
+ *
+ * @param r The bouncing box rectangle.
+ *
+ * @return The bouncing box rectangle.
+ */
+ protected Rectangle getBox(Rectangle r)
+ {
+ if (!progressBar.isIndeterminate())
+ return null;
+ //numFrames has to be an even number as defined by spec.
+ int iterations = numFrames / 2 + 1;
+
+ double boxDependent;
+ double boxIndependent;
+
+ if (progressBar.getOrientation() == JProgressBar.HORIZONTAL)
+ {
+ Dimension dims = getPreferredInnerHorizontal();
+ boxDependent = (double) dims.width / iterations;
+ boxIndependent = dims.height;
+ }
+ else
+ {
+ Dimension dims = getPreferredInnerVertical();
+ boxDependent = (double) dims.height / iterations;
+ boxIndependent = dims.width;
+ }
+
+ Rectangle vr = new Rectangle();
+ SwingUtilities.calculateInnerArea(progressBar, vr);
+
+ int index = getAnimationIndex();
+ if (animationIndex > (numFrames + 1) / 2)
+ index = numFrames - getAnimationIndex();
+
+ if (progressBar.getOrientation() == JProgressBar.HORIZONTAL)
+ {
+ r.x = vr.x + (int) (index * boxDependent);
+ r.y = vr.y;
+ r.width = (int) boxDependent;
+ r.height = (int) boxIndependent;
+ }
+ else
+ {
+ index++;
+ r.x = vr.x;
+ r.y = vr.height - (int) (index * boxDependent) + vr.y;
+ r.width = (int) boxIndependent;
+ r.height = (int) boxDependent;
+ }
+
+ return r;
+ }
+
+ /**
+ * This method returns the length of the cells.
+ *
+ * @return The cell length.
+ */
+ protected int getCellLength()
+ {
+ return cellLength;
+ }
+
+ /**
+ * This method returns the spacing between cells.
+ *
+ * @return The cell gap.
+ */
+ protected int getCellSpacing()
+ {
+ return cellSpacing;
+ }
+
+ /**
+ * This method returns the maximum size of the JComponent.
+ * If it returns null, it is up to the LayoutManager
+ * to give it a size.
+ *
+ * @param c The component to find a maximum size for.
+ *
+ * @return The maximum size.
+ */
+ public Dimension getMaximumSize(JComponent c)
+ {
+ return getPreferredSize(c);
+ }
+
+ /**
+ * This method returns the minimum size of the JComponent.
+ * If it returns null, it is up to the LayoutManager to
+ * give it a size.
+ *
+ * @param c The component to find a minimum size for.
+ *
+ * @return The minimum size.
+ */
+ public Dimension getMinimumSize(JComponent c)
+ {
+ return getPreferredSize(c);
+ }
+
+ /**
+ * This method returns the preferred size of the inner
+ * rectangle (the bounds without the insets) if the
+ * progressBar is horizontal.
+ *
+ * @return The preferred size of the progressBar minus
+ * insets if it's horizontal.
+ */
+ protected Dimension getPreferredInnerHorizontal()
+ {
+ Rectangle vr = new Rectangle();
+
+ SwingUtilities.calculateInnerArea(progressBar, vr);
+
+ return new Dimension(vr.width, vr.height);
+ }
+
+ /**
+ * This method returns the preferred size of the inner
+ * rectangle (the bounds without insets) if the
+ * progressBar is vertical.
+ *
+ * @return The preferred size of the progressBar minus
+ * insets if it's vertical.
+ */
+ protected Dimension getPreferredInnerVertical()
+ {
+ Rectangle vr = new Rectangle();
+
+ SwingUtilities.calculateInnerArea(progressBar, vr);
+
+ return new Dimension(vr.width, vr.height);
+ }
+
+ /**
+ * This method returns the preferred size of the
+ * given JComponent. If it returns null, then it
+ * is up to the LayoutManager to give it a size.
+ *
+ * @param c The component to find the preferred size for.
+ *
+ * @return The preferred size of the component.
+ */
+ public Dimension getPreferredSize(JComponent c)
+ {
+ // The only thing we need to worry about is
+ // the text size.
+ Graphics g = progressBar.getGraphics();
+
+ Insets insets = c.getInsets();
+
+ FontMetrics fm = g.getFontMetrics(c.getFont());
+
+ int textW = fm.stringWidth(progressBar.getString());
+ int textH = fm.getHeight();
+
+ g.dispose();
+
+ if (progressBar.getOrientation() == JProgressBar.HORIZONTAL)
+ {
+ if (textH < 20)
+ textH = 20;
+ if (textW < 200)
+ textW = 200;
+ }
+ else
+ {
+ if (textH < 200)
+ textH = 200;
+ if (textW < 20)
+ textW = 20;
+ }
+ textW += insets.left + insets.right;
+ textH += insets.top + insets.bottom;
+ return new Dimension(textW, textH);
+ }
+
+ /**
+ * This method returns the Color that the text is shown in when the bar is
+ * not over the text.
+ *
+ * @return The color of the text when the bar is not over it.
+ */
+ protected Color getSelectionBackground()
+ {
+ return selectionBackground;
+ }
+
+ /**
+ * This method returns the Color that the text is shown in when the bar is
+ * over the text.
+ *
+ * @return The color of the text when the bar is over it.
+ */
+ protected Color getSelectionForeground()
+ {
+ return selectionForeground;
+ }
+
+ /**
+ * This method returns the point (the top left of the bounding box)
+ * where the text should be painted.
+ *
+ * @param g The Graphics object to measure FontMetrics with.
+ * @param progressString The string to paint.
+ * @param x The x coordinate of the overall bounds box.
+ * @param y The y coordinate of the overall bounds box.
+ * @param width The width of the overall bounds box.
+ * @param height The height of the overall bounds box.
+ *
+ * @return The top left of the bounding box where text should be painted.
+ */
+ protected Point getStringPlacement(Graphics g, String progressString, int x,
+ int y, int width, int height)
+ {
+ Rectangle tr = new Rectangle();
+ Rectangle vr = new Rectangle(x, y, width, height);
+ Rectangle ir = new Rectangle();
+
+ Font f = g.getFont();
+ FontMetrics fm = g.getFontMetrics(f);
+
+ SwingUtilities.layoutCompoundLabel(progressBar, fm, progressString, null,
+ SwingConstants.CENTER,
+ SwingConstants.CENTER,
+ SwingConstants.CENTER,
+ SwingConstants.CENTER, vr, ir, tr, 0);
+ return new Point(tr.x, tr.y);
+ }
+
+ /**
+ * This method increments the animation index.
+ */
+ public void incrementAnimationIndex()
+ {
+ animationIndex++;
+ //numFrames is like string length, it should be named numFrames or something
+ if (animationIndex >= numFrames)
+ animationIndex = 0;
+ progressBar.repaint();
+ }
+
+ /**
+ * This method paints the progressBar. It delegates its responsibilities
+ * to paintDeterminate and paintIndeterminate.
+ *
+ * @param g The Graphics object to paint with.
+ * @param c The JComponent to paint.
+ */
+ public void paint(Graphics g, JComponent c)
+ {
+ if (! progressBar.isIndeterminate())
+ paintDeterminate(g, c);
+ else
+ paintIndeterminate(g, c);
+
+ if (progressBar.isBorderPainted())
+ progressBar.getBorder().paintBorder(progressBar, g, 0, 0,
+ progressBar.getWidth(),
+ progressBar.getHeight());
+ }
+
+ /**
+ * This method is called if the painting to be done is
+ * for a determinate progressBar.
+ *
+ * @param g The Graphics object to paint with.
+ * @param c The JComponent to paint.
+ */
+ protected void paintDeterminate(Graphics g, JComponent c)
+ {
+ Color saved = g.getColor();
+ int space = getCellSpacing();
+ int len = getCellLength();
+ int max = progressBar.getMaximum();
+ int min = progressBar.getMinimum();
+ int value = progressBar.getValue();
+
+ Rectangle vr = new Rectangle();
+ SwingUtilities.calculateInnerArea(c, vr);
+
+ Rectangle or = c.getBounds();
+
+ Insets insets = c.getInsets();
+
+ int amountFull = getAmountFull(insets, or.width, or.height);
+
+ g.setColor(c.getBackground());
+ g.fill3DRect(vr.x, vr.y, vr.width, vr.height, false);
+
+ if (max != min && len != 0 && value > min)
+ {
+ int iterations = value / (space + len);
+
+ if (progressBar.getOrientation() == JProgressBar.HORIZONTAL)
+ {
+ double spaceInUnits = space * (double) vr.width / (max - min);
+ double lenInUnits = len * (double) vr.width / (max - min);
+ double currX = vr.x;
+
+ g.setColor(c.getForeground());
+ g.fill3DRect(vr.x, vr.y, amountFull, vr.height, true);
+
+ g.setColor(c.getBackground());
+ if (spaceInUnits != 0)
+ {
+ for (int i = 0; i < iterations; i++)
+ {
+ currX += lenInUnits;
+ g.fill3DRect((int) currX, vr.y, (int) spaceInUnits,
+ vr.height, true);
+ currX += spaceInUnits;
+ }
+ }
+ }
+ else
+ {
+ double currY = vr.y;
+ double spaceInUnits = space * (double) vr.height / (max - min);
+ double lenInUnits = len * (double) vr.height / (max - min);
+
+ g.setColor(c.getForeground());
+ g.fill3DRect(vr.x, vr.y + vr.height - amountFull, vr.width,
+ amountFull, true);
+
+ g.setColor(c.getBackground());
+
+ if (spaceInUnits != 0)
+ {
+ for (int i = 0; i < iterations; i++)
+ {
+ currY -= lenInUnits + spaceInUnits;
+ g.fill3DRect(vr.x, (int) currY, vr.width,
+ (int) spaceInUnits, true);
+ }
+ }
+ }
+ }
+
+ if (progressBar.isStringPainted())
+ paintString(g, 0, 0, or.width, or.height, amountFull, insets);
+ g.setColor(saved);
+ }
+
+ /**
+ * This method is called if the painting to be done is for
+ * an indeterminate progressBar.
+ *
+ * @param g The Graphics object to paint with.
+ * @param c The JComponent to paint.
+ */
+ protected void paintIndeterminate(Graphics g, JComponent c)
+ {
+ //need to paint the box at it's current position. no text is painted since
+ //all we're doing is bouncing back and forth
+ Color saved = g.getColor();
+ Insets insets = c.getInsets();
+
+ Rectangle or = c.getBounds();
+ Rectangle vr = new Rectangle();
+ SwingUtilities.calculateInnerArea(c, vr);
+
+ g.setColor(c.getBackground());
+ g.fill3DRect(vr.x, vr.y, vr.width, vr.height, false);
+
+ Rectangle box = new Rectangle();
+ getBox(box);
+
+ g.setColor(c.getForeground());
+ g.fill3DRect(box.x, box.y, box.width, box.height, true);
+
+ if (progressBar.isStringPainted())
+ paintString(g, 0, 0, or.width, or.height,
+ getAmountFull(insets, or.width, or.height), insets);
+
+ g.setColor(saved);
+ }
+
+ /**
+ * This method paints the string for the progressBar.
+ *
+ * @param g The Graphics object to paint with.
+ * @param x The x coordinate of the progressBar.
+ * @param y The y coordinate of the progressBar.
+ * @param width The width of the progressBar.
+ * @param height The height of the progressBar.
+ * @param amountFull The amount of the progressBar that has its bar filled.
+ * @param b The insets of the progressBar.
+ */
+ protected void paintString(Graphics g, int x, int y, int width, int height,
+ int amountFull, Insets b)
+ {
+ // We want to place in the exact center of the bar.
+ Point placement = getStringPlacement(g, progressBar.getString(),
+ x + b.left, y + b.top,
+ width - b.left - b.right,
+ height - b.top - b.bottom);
+ Color saved = g.getColor();
+
+ // FIXME: The Color of the text should use selectionForeground and selectionBackground
+ // but that can't be done right now, so we'll use white in the mean time.
+ g.setColor(Color.WHITE);
+
+ FontMetrics fm = g.getFontMetrics(progressBar.getFont());
+
+ g.drawString(progressBar.getString(), placement.x,
+ placement.y + fm.getAscent());
+
+ g.setColor(saved);
+ }
+
+ /**
+ * This method sets the current animation index. If the index
+ * is greater than the number of frames, it resets to 0.
+ *
+ * @param newValue The new animation index.
+ */
+ protected void setAnimationIndex(int newValue)
+ {
+ animationIndex = (newValue <= numFrames) ? newValue : 0;
+ progressBar.repaint();
+ }
+
+ /**
+ * This method sets the cell length.
+ *
+ * @param cellLen The cell length.
+ */
+ protected void setCellLength(int cellLen)
+ {
+ cellLength = cellLen;
+ }
+
+ /**
+ * This method sets the cell spacing.
+ *
+ * @param cellSpace The cell spacing.
+ */
+ protected void setCellSpacing(int cellSpace)
+ {
+ cellSpacing = cellSpace;
+ }
+
+ /**
+ * This method starts the animation timer. It is called
+ * when the propertyChangeListener detects that the progressBar
+ * has changed to indeterminate mode.
+ */
+ protected void startAnimationTimer()
+ {
+ if (animationTimer != null)
+ animationTimer.start();
+ }
+
+ /**
+ * This method stops the animation timer. It is called when
+ * the propertyChangeListener detects that the progressBar
+ * has changed to determinate mode.
+ */
+ protected void stopAnimationTimer()
+ {
+ if (animationTimer != null)
+ animationTimer.stop();
+ setAnimationIndex(0);
+ }
+
+ /**
+ * This method changes the settings for the progressBar to
+ * the defaults provided by the current Look and Feel.
+ */
+ protected void installDefaults()
+ {
+ UIDefaults defaults = UIManager.getLookAndFeelDefaults();
+
+ progressBar.setFont(defaults.getFont("ProgressBar.font"));
+ progressBar.setForeground(defaults.getColor("ProgressBar.foreground"));
+ progressBar.setBackground(defaults.getColor("ProgressBar.background"));
+ progressBar.setBorder(defaults.getBorder("ProgressBar.border"));
+
+ selectionForeground = defaults.getColor("ProgressBar.selectionForeground");
+ selectionBackground = defaults.getColor("ProgressBar.selectionBackground");
+ cellLength = defaults.getInt("ProgressBar.cellLength");
+ cellSpacing = defaults.getInt("ProgressBar.cellSpacing");
+
+ int repaintInterval = defaults.getInt("ProgressBar.repaintInterval");
+ int cycleTime = defaults.getInt("ProgressBar.cycleTime");
+
+ if (cycleTime % repaintInterval != 0
+ && (cycleTime / repaintInterval) % 2 != 0)
+ {
+ int div = (cycleTime / repaintInterval) + 2;
+ div /= 2;
+ div *= 2;
+ cycleTime = div * repaintInterval;
+ }
+ setAnimationIndex(0);
+ numFrames = cycleTime / repaintInterval;
+ animationTimer.setDelay(repaintInterval);
+ }
+
+ /**
+ * The method uninstalls any defaults that were
+ * set by the current Look and Feel.
+ */
+ protected void uninstallDefaults()
+ {
+ progressBar.setFont(null);
+ progressBar.setForeground(null);
+ progressBar.setBackground(null);
+
+ selectionForeground = null;
+ selectionBackground = null;
+ }
+
+ /**
+ * This method registers listeners to all the
+ * components that this UI delegate needs to listen to.
+ */
+ protected void installListeners()
+ {
+ changeListener = new ChangeHandler();
+ propertyListener = new PropertyChangeHandler();
+ animation = new Animator();
+
+ progressBar.addChangeListener(changeListener);
+ progressBar.addPropertyChangeListener(propertyListener);
+ animationTimer.addActionListener(animation);
+ }
+
+ /**
+ * This method unregisters listeners to all the
+ * components that were listened to.
+ */
+ protected void uninstallListeners()
+ {
+ progressBar.removeChangeListener(changeListener);
+ progressBar.removePropertyChangeListener(propertyListener);
+ animationTimer.removeActionListener(animation);
+
+ changeListener = null;
+ propertyListener = null;
+ animation = null;
+ }
+
+ /**
+ * This method installs the UI for the given JComponent.
+ * This includes setting up defaults and listeners as
+ * well as initializing any values or objects that
+ * the UI may need.
+ *
+ * @param c The JComponent that is having this UI installed.
+ */
+ public void installUI(JComponent c)
+ {
+ super.installUI(c);
+ if (c instanceof JProgressBar)
+ {
+ progressBar = (JProgressBar) c;
+
+ animationTimer = new Timer();
+ animationTimer.setRepeats(true);
+
+ installDefaults();
+ installListeners();
+ }
+ }
+
+ /**
+ * This method removes the UI for the given JComponent.
+ * This includes removing any listeners or defaults
+ * that the installUI may have set up.
+ *
+ * @param c The JComponent that is having this UI uninstalled.
+ */
+ public void uninstallUI(JComponent c)
+ {
+ super.uninstallUI(c);
+ uninstallListeners();
+ uninstallDefaults();
+
+ animationTimer = null;
+ progressBar = null;
+ }
+}
diff --git a/libjava/javax/swing/plaf/basic/BasicScrollBarUI.java b/libjava/javax/swing/plaf/basic/BasicScrollBarUI.java
new file mode 100644
index 0000000..2e9f76d
--- /dev/null
+++ b/libjava/javax/swing/plaf/basic/BasicScrollBarUI.java
@@ -0,0 +1,1397 @@
+/* BasicScrollBarUI.java
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.plaf.basic;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Insets;
+import java.awt.LayoutManager;
+import java.awt.Point;
+import java.awt.Polygon;
+import java.awt.Rectangle;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseMotionListener;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import javax.swing.BoundedRangeModel;
+import javax.swing.Icon;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JScrollBar;
+import javax.swing.SwingConstants;
+import javax.swing.SwingUtilities;
+import javax.swing.Timer;
+import javax.swing.UIDefaults;
+import javax.swing.UIManager;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.ScrollBarUI;
+
+
+/**
+ * The Basic Look and Feel UI delegate for JScrollBar.
+ */
+public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
+ SwingConstants
+{
+ /**
+ * A helper class that listens to the two JButtons on each end
+ * of the JScrollBar.
+ */
+ protected class ArrowButtonListener extends MouseAdapter
+ {
+ /**
+ * Move the thumb in the direction specified by the
+ * button's arrow. If this button is held down, then
+ * it should keep moving the thumb.
+ *
+ * @param e The MouseEvent fired by the JButton.
+ */
+ public void mousePressed(MouseEvent e)
+ {
+ scrollTimer.stop();
+ scrollListener.setScrollByBlock(false);
+ if (e.getSource() == incrButton)
+ scrollListener.setDirection(POSITIVE_SCROLL);
+ else
+ scrollListener.setDirection(NEGATIVE_SCROLL);
+ scrollTimer.start();
+ }
+
+ /**
+ * Stops the thumb when the JButton is released.
+ *
+ * @param e The MouseEvent fired by the JButton.
+ */
+ public void mouseReleased(MouseEvent e)
+ {
+ scrollTimer.stop();
+ }
+ }
+
+ /**
+ * A helper class that listens to the ScrollBar's model
+ * for ChangeEvents.
+ */
+ protected class ModelListener implements ChangeListener
+ {
+ /**
+ * Called when the model changes.
+ *
+ * @param e The ChangeEvent fired by the model.
+ */
+ public void stateChanged(ChangeEvent e)
+ {
+ getThumbBounds();
+ scrollbar.repaint();
+ }
+ }
+
+ /**
+ * A helper class that listens to the ScrollBar's properties.
+ */
+ public class PropertyChangeHandler implements PropertyChangeListener
+ {
+ /**
+ * Called when one of the ScrollBar's properties change.
+ *
+ * @param e The PropertyChangeEvent fired by the ScrollBar.
+ */
+ public void propertyChange(PropertyChangeEvent e)
+ {
+ if (e.getPropertyName().equals(JScrollBar.MODEL_CHANGED_PROPERTY))
+ {
+ ((BoundedRangeModel) e.getOldValue()).removeChangeListener(modelListener);
+ scrollbar.getModel().addChangeListener(modelListener);
+ getThumbBounds();
+ }
+ else if (e.getPropertyName().equals(JScrollBar.ORIENTATION_CHANGED_PROPERTY))
+ {
+ incrButton.removeMouseListener(buttonListener);
+ decrButton.removeMouseListener(buttonListener);
+ incrButton = createIncreaseButton(scrollbar.getOrientation());
+ decrButton = createDecreaseButton(scrollbar.getOrientation());
+ incrButton.addMouseListener(buttonListener);
+ decrButton.addMouseListener(buttonListener);
+ calculatePreferredSize();
+ layoutContainer(scrollbar);
+ }
+ layoutContainer(scrollbar);
+ scrollbar.repaint();
+ }
+ }
+
+ /**
+ * A helper class that listens for events from
+ * the timer that is used to move the thumb.
+ */
+ protected class ScrollListener implements ActionListener
+ {
+ /** The direction the thumb moves in. */
+ private transient int direction;
+
+ /** Whether movement will be in blocks. */
+ private transient boolean block;
+
+ /**
+ * Creates a new ScrollListener object.
+ * The default is scrolling positively with block movement.
+ */
+ public ScrollListener()
+ {
+ direction = POSITIVE_SCROLL;
+ block = true;
+ }
+
+ /**
+ * Creates a new ScrollListener object using
+ * the given direction and block.
+ *
+ * @param dir The direction to move in.
+ * @param block Whether movement will be in blocks.
+ */
+ public ScrollListener(int dir, boolean block)
+ {
+ direction = dir;
+ this.block = block;
+ }
+
+ /**
+ * Sets the direction to scroll in.
+ *
+ * @param direction The direction to scroll in.
+ */
+ public void setDirection(int direction)
+ {
+ this.direction = direction;
+ }
+
+ /**
+ * Sets whether scrolling will be done in blocks.
+ *
+ * @param block Whether scrolling will be in blocks.
+ */
+ public void setScrollByBlock(boolean block)
+ {
+ this.block = block;
+ }
+
+ /**
+ * Called every time the timer reaches its interval.
+ *
+ * @param e The ActionEvent fired by the timer.
+ */
+ public void actionPerformed(ActionEvent e)
+ {
+ if (block)
+ {
+ // Only need to check it if it's block scrolling
+ // We only block scroll if the click occurs
+ // in the track.
+
+ if (!trackListener.shouldScroll(direction))
+ {
+ trackHighlight = NO_HIGHLIGHT;
+ scrollbar.repaint();
+ return;
+ }
+ scrollByBlock(direction);
+ }
+ else
+ scrollByUnit(direction);
+ }
+ }
+
+ /**
+ * Helper class that listens for movement on the track.
+ */
+ protected class TrackListener extends MouseAdapter
+ implements MouseMotionListener
+ {
+ /** The current X coordinate of the mouse. */
+ protected int currentMouseX;
+
+ /** The current Y coordinate of the mouse. */
+ protected int currentMouseY;
+
+ /** The offset between the current mouse cursor and the
+ current value of the scrollbar. */
+ protected int offset;
+
+ /**
+ * This method is called when the mouse is being
+ * dragged.
+ *
+ * @param e The MouseEvent given.
+ */
+ public void mouseDragged(MouseEvent e)
+ {
+ currentMouseX = e.getX();
+ currentMouseY = e.getY();
+ if (scrollbar.getValueIsAdjusting())
+ {
+ int value;
+ if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL)
+ value = valueForXPosition(currentMouseX) - offset;
+ else
+ value = valueForYPosition(currentMouseY) - offset;
+
+ scrollbar.setValue(value);
+ }
+ }
+
+ /**
+ * This method is called when the mouse is moved.
+ *
+ * @param e The MouseEvent given.
+ */
+ public void mouseMoved(MouseEvent e)
+ {
+ // Not interested in where the mouse
+ // is unless it is being dragged.
+ }
+
+ /**
+ * This method is called when the mouse is
+ * pressed. When it is pressed, the thumb should
+ * move in blocks towards the cursor.
+ *
+ * @param e The MouseEvent given.
+ */
+ public void mousePressed(MouseEvent e)
+ {
+ currentMouseX = e.getX();
+ currentMouseY = e.getY();
+
+ int value;
+ if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL)
+ value = valueForXPosition(currentMouseX);
+ else
+ value = valueForYPosition(currentMouseY);
+
+ if (value == scrollbar.getValue())
+ return;
+
+ if (!thumbRect.contains(e.getPoint()))
+ {
+ scrollTimer.stop();
+ scrollListener.setScrollByBlock(true);
+ if (value > scrollbar.getValue())
+ {
+ trackHighlight = INCREASE_HIGHLIGHT;
+ scrollListener.setDirection(POSITIVE_SCROLL);
+ }
+ else
+ {
+ trackHighlight = DECREASE_HIGHLIGHT;
+ scrollListener.setDirection(NEGATIVE_SCROLL);
+ }
+ scrollTimer.start();
+ }
+ else
+ {
+ // We'd like to keep track of where the cursor
+ // is inside the thumb.
+ // This works because the scrollbar's value represents
+ // "lower" edge of the thumb. The value at which
+ // the cursor is at must be greater or equal
+ // to that value.
+ scrollbar.setValueIsAdjusting(true);
+ offset = value - scrollbar.getValue();
+ }
+ scrollbar.repaint();
+ }
+
+ /**
+ * This method is called when the mouse is released.
+ * It should stop movement on the thumb
+ *
+ * @param e The MouseEvent given.
+ */
+ public void mouseReleased(MouseEvent e)
+ {
+ trackHighlight = NO_HIGHLIGHT;
+ scrollTimer.stop();
+
+ if (scrollbar.getValueIsAdjusting())
+ scrollbar.setValueIsAdjusting(false);
+ scrollbar.repaint();
+ }
+
+ /**
+ * A helper method that decides whether we should
+ * keep scrolling in the given direction.
+ *
+ * @param direction The direction to check for.
+ *
+ * @return Whether the thumb should keep scrolling.
+ */
+ public boolean shouldScroll (int direction)
+ {
+ int value;
+ if (scrollbar.getOrientation() == HORIZONTAL)
+ value = valueForXPosition(currentMouseX);
+ else
+ value = valueForYPosition(currentMouseY);
+
+ if (direction == POSITIVE_SCROLL)
+ return (value > scrollbar.getValue());
+ else
+ return (value < scrollbar.getValue());
+ }
+ }
+
+ /** The listener that listens to the JButtons. */
+ protected ArrowButtonListener buttonListener;
+
+ /** The listener that listens to the model. */
+ protected ModelListener modelListener;
+
+ /** The listener that listens to the scrollbar for property
+ changes. */
+ protected PropertyChangeListener propertyChangeListener;
+
+ /** The listener that listens to the timer. */
+ protected ScrollListener scrollListener;
+
+ /** The listener that listens for MouseEvents on the track. */
+ protected TrackListener trackListener;
+
+ /** The JButton that decrements the scrollbar's value. */
+ protected JButton decrButton;
+
+ /** The JButton that increments the scrollbar's value. */
+ protected JButton incrButton;
+
+ /** The dimensions of the maximum thumb size. */
+ protected static Dimension maximumThumbSize;
+
+ /** The dimensions of the minimum thumb size. */
+ protected static Dimension minimumThumbSize;
+
+ /** The color of the thumb. */
+ protected Color thumbColor;
+
+ /** The outer shadow of the thumb. */
+ protected Color thumbDarkShadowColor;
+
+ /** The top and left edge color for the thumb. */
+ protected Color thumbHighlightColor;
+
+ /** The outer light shadow for the thumb. */
+ protected Color thumbLightShadowColor;
+
+ /** The color that is used when the mouse press
+ occurs in the track. */
+ protected Color trackHighlightColor;
+
+ /** The color of the track. */
+ protected Color trackColor;
+
+ /** The size and position of the track. */
+ protected Rectangle trackRect;
+
+ /** The size and position of the thumb. */
+ protected Rectangle thumbRect;
+
+ /** Indicates that the decrease highlight should be painted. */
+ protected static int DECREASE_HIGHLIGHT = 1;
+
+ /** Indicates that the increase highlight should be painted. */
+ protected static int INCREASE_HIGHLIGHT = 2;
+
+ /** Indicates that no highlight should be painted. */
+ protected static int NO_HIGHLIGHT = 0;
+
+ /** Indicates that the scrolling direction is positive. */
+ private static int POSITIVE_SCROLL = 1;
+
+ /** Indicates that the scrolling direction is negative. */
+ private static int NEGATIVE_SCROLL = -1;
+
+ /** The cached preferred size for the scrollbar. */
+ private transient Dimension preferredSize;
+
+ /** The current highlight status. */
+ protected int trackHighlight;
+
+ /** FIXME: Use this for something (presumably mouseDragged) */
+ protected boolean isDragging;
+
+ /** The timer used to move the thumb when the mouse is held. */
+ protected Timer scrollTimer;
+
+ /** The scrollbar this UI is acting for. */
+ protected JScrollBar scrollbar;
+
+ /**
+ * A helper class that allows us to draw icons for
+ * the JButton.
+ */
+ private class arrowIcon implements Icon
+ {
+ /** The polygon that describes the icon. */
+ private Polygon arrow;
+
+ /**
+ * Creates a new arrowIcon object.
+ *
+ * @param arrow The polygon that describes the arrow.
+ */
+ public arrowIcon(Polygon arrow)
+ {
+ this.arrow = arrow;
+ }
+
+ /**
+ * Returns the height of the icon.
+ *
+ * @return The height of the icon.
+ */
+ public int getIconHeight()
+ {
+ return 10;
+ }
+
+ /**
+ * Returns the width of the icon.
+ *
+ * @return The width of the icon.
+ */
+ public int getIconWidth()
+ {
+ return 10;
+ }
+
+ /**
+ * Paints the icon.
+ *
+ * @param c The Component to paint for.
+ * @param g The Graphics object to draw with.
+ * @param x The X coordinate to draw at.
+ * @param y The Y coordinate to draw at.
+ */
+ 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(arrow);
+
+ g.setColor(saved);
+ g.translate(-x, -y);
+ }
+ }
+
+ /** The Icon that points up. */
+ private static Icon upIcon = new arrowIcon(new Polygon(new int[] { 2, 5, 8 },
+ new int[] { 7, 3, 7 },
+ 3));
+
+ /** The Icon that points down. */
+ private static Icon downIcon = new arrowIcon(new Polygon(new int[] { 2, 5, 8 },
+ new int[] { 3, 7, 3 },
+ 3));
+
+ /** The Icon that points left. */
+ private static Icon leftIcon = new arrowIcon(new Polygon(new int[] { 7, 3, 7 },
+ new int[] { 2, 5, 8 },
+ 3));
+
+ /** The Icon that points right. */
+ private static Icon rightIcon = new arrowIcon(new Polygon(new int[]
+ {
+ 3, 7, 3
+ },
+ new int[]
+ {
+ 2, 5, 8
+ }, 3));
+
+ /**
+ * This method adds a component to the layout.
+ *
+ * @param name The name to associate with the component that is added.
+ * @param child The Component to add.
+ */
+ public void addLayoutComponent(String name, Component child)
+ {
+ // You should not be adding stuff to this component.
+ // The contents are fixed.
+ }
+
+ /**
+ * This method configures the scrollbar's colors. This can be
+ * done by looking up the standard colors from the L&F defaults.
+ */
+ protected void configureScrollBarColors()
+ {
+ UIDefaults defaults = UIManager.getLookAndFeelDefaults();
+
+ trackColor = defaults.getColor("ScrollBar.track");
+ trackHighlightColor = defaults.getColor("ScrollBar.trackHighlight");
+ thumbColor = defaults.getColor("ScrollBar.thumb");
+ thumbHighlightColor = defaults.getColor("ScrollBar.thumbHighlight");
+ thumbDarkShadowColor = defaults.getColor("ScrollBar.thumbDarkShadow");
+ thumbLightShadowColor = defaults.getColor("ScrollBar.thumbLightShadow");
+ }
+
+ /**
+ * This method creates an ArrowButtonListener.
+ *
+ * @return A new ArrowButtonListener.
+ */
+ protected ArrowButtonListener createArrowButtonListener()
+ {
+ return new ArrowButtonListener();
+ }
+
+ /**
+ * This method creates a new JButton with the appropriate
+ * icon for the orientation.
+ *
+ * @param orientation The orientation this JButton uses.
+ *
+ * @return The increase JButton.
+ */
+ protected JButton createIncreaseButton(int orientation)
+ {
+ if (incrButton == null)
+ incrButton = new JButton();
+ if (orientation == SwingConstants.HORIZONTAL)
+ incrButton.setIcon(rightIcon);
+ else
+ incrButton.setIcon(downIcon);
+
+ return incrButton;
+ }
+
+ /**
+ * This method creates a new JButton with the appropriate
+ * icon for the orientation.
+ *
+ * @param orientation The orientation this JButton uses.
+ *
+ * @return The decrease JButton.
+ */
+ protected JButton createDecreaseButton(int orientation)
+ {
+ if (decrButton == null)
+ decrButton = new JButton();
+ if (orientation == SwingConstants.HORIZONTAL)
+ decrButton.setIcon(leftIcon);
+ else
+ decrButton.setIcon(upIcon);
+
+ return decrButton;
+ }
+
+ /**
+ * This method creates a new ModelListener.
+ *
+ * @return A new ModelListener.
+ */
+ protected ModelListener createModelListener()
+ {
+ return new ModelListener();
+ }
+
+ /**
+ * This method creates a new PropertyChangeListener.
+ *
+ * @return A new PropertyChangeListener.
+ */
+ protected PropertyChangeListener createPropertyChangeListener()
+ {
+ return new PropertyChangeHandler();
+ }
+
+ /**
+ * This method creates a new ScrollListener.
+ *
+ * @return A new ScrollListener.
+ */
+ protected ScrollListener createScrollListener()
+ {
+ return new ScrollListener();
+ }
+
+ /**
+ * This method creates a new TrackListener.
+ *
+ * @return A new TrackListener.
+ */
+ protected TrackListener createTrackListener()
+ {
+ return new TrackListener();
+ }
+
+ /**
+ * This method returns a new BasicScrollBarUI.
+ *
+ * @param c The JComponent to create a UI for.
+ *
+ * @return A new BasicScrollBarUI.
+ */
+ public static ComponentUI createUI(JComponent c)
+ {
+ return new BasicScrollBarUI();
+ }
+
+ /**
+ * This method returns the maximum size for this JComponent.
+ *
+ * @param c The JComponent to measure the maximum size for.
+ *
+ * @return The maximum size for the component.
+ */
+ public Dimension getMaximumSize(JComponent c)
+ {
+ return getPreferredSize(c);
+ }
+
+ /**
+ * This method returns the maximum thumb size.
+ *
+ * @return The maximum thumb size.
+ */
+ protected Dimension getMaximumThumbSize()
+ {
+ return maximumThumbSize;
+ }
+
+ /**
+ * This method returns the minimum size for this JComponent.
+ *
+ * @param c The JComponent to measure the minimum size for.
+ *
+ * @return The minimum size for the component.
+ */
+ public Dimension getMinimumSize(JComponent c)
+ {
+ return getPreferredSize(c);
+ }
+
+ /**
+ * This method returns the minimum thumb size.
+ *
+ * @return The minimum thumb size.
+ */
+ protected Dimension getMinimumThumbSize()
+ {
+ return minimumThumbSize;
+ }
+
+ /**
+ * This method calculates the preferred size since
+ * calling getPreferredSize() returns a cached value.
+ */
+ private void calculatePreferredSize()
+ {
+ int height;
+ int width;
+ height = width = 0;
+
+ if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL)
+ {
+ width += incrButton.getPreferredSize().getWidth();
+ width += decrButton.getPreferredSize().getWidth();
+
+ width += Math.max(200, scrollbar.getVisibleAmount());
+
+ height = Math.max(incrButton.getPreferredSize().height,
+ decrButton.getPreferredSize().height);
+ height = Math.max(getMinimumThumbSize().height, height);
+ height = Math.max(20, height);
+ height = Math.min(getMaximumThumbSize().height, height);
+ }
+ else
+ {
+ height += incrButton.getPreferredSize().getHeight();
+ height += decrButton.getPreferredSize().getHeight();
+
+ height += Math.max(200, scrollbar.getVisibleAmount());
+
+ width = Math.max(incrButton.getPreferredSize().width,
+ decrButton.getPreferredSize().width);
+ width = Math.max(getMinimumThumbSize().width, width);
+ width = Math.max(20, width);
+ width = Math.min(getMaximumThumbSize().width, width);
+ }
+
+ Insets insets = scrollbar.getInsets();
+
+ height += insets.top + insets.bottom;
+ width += insets.left + insets.right;
+
+ preferredSize = new Dimension(width, height);
+ }
+
+ /**
+ * This method returns a cached value of the preferredSize.
+ * The only restrictions are: If the scrollbar is horizontal, the
+ * height should be the maximum of the height of the JButtons and
+ * the minimum width of the thumb. For vertical scrollbars, the
+ * calculation is similar (swap width for height and vice versa).
+ *
+ * @param c The JComponent to measure.
+ *
+ * @return The preferredSize.
+ */
+ public Dimension getPreferredSize(JComponent c)
+ {
+ layoutContainer(scrollbar);
+ return preferredSize;
+ }
+
+ /**
+ * This method returns the thumb's bounds based on the
+ * current value of the scrollbar. This method updates the
+ * cached value and returns that.
+ *
+ * @return The thumb bounds.
+ */
+ protected Rectangle getThumbBounds()
+ {
+ int max = scrollbar.getMaximum();
+ int min = scrollbar.getMinimum();
+ int value = scrollbar.getValue();
+ int extent = scrollbar.getVisibleAmount();
+
+ 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 = extent * trackRect.width / (max - min);
+ thumbRect.height = trackRect.height;
+ }
+ else
+ {
+ thumbRect.x = trackRect.x;
+ thumbRect.y = trackRect.y
+ + value * trackRect.height / (max - min);
+
+ thumbRect.width = trackRect.width;
+ thumbRect.height = extent * trackRect.height / (max - min);
+ }
+ return thumbRect;
+ }
+
+ /**
+ * This method calculates the bounds of the track. This method
+ * updates the cached value and returns it.
+ *
+ * @return The track's bounds.
+ */
+ protected Rectangle getTrackBounds()
+ {
+ SwingUtilities.calculateInnerArea(scrollbar, trackRect);
+
+ if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL)
+ {
+ trackRect.width -= incrButton.getPreferredSize().getWidth();
+ trackRect.width -= decrButton.getPreferredSize().getWidth();
+
+ trackRect.x += decrButton.getPreferredSize().getWidth();
+ }
+ else
+ {
+ trackRect.height -= incrButton.getPreferredSize().getHeight();
+ trackRect.height -= decrButton.getPreferredSize().getHeight();
+
+ trackRect.y += incrButton.getPreferredSize().getHeight();
+ }
+ return trackRect;
+ }
+
+ /**
+ * This method installs any addition Components that
+ * are a part of or related to this scrollbar.
+ */
+ protected void installComponents()
+ {
+ incrButton = createIncreaseButton(scrollbar.getOrientation());
+ scrollbar.add(incrButton);
+ decrButton = createDecreaseButton(scrollbar.getOrientation());
+ scrollbar.add(decrButton);
+ }
+
+ /**
+ * This method installs the defaults for the scrollbar specified
+ * by the Basic L&F.
+ */
+ 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"));
+
+ maximumThumbSize = defaults.getDimension("ScrollBar.maximumThumbSize");
+ minimumThumbSize = defaults.getDimension("ScrollBar.minimumThumbSize");
+ }
+
+ /**
+ * This method installs the keyboard actions for the scrollbar.
+ */
+ protected void installKeyboardActions()
+ {
+ // FIXME: implement.
+ }
+
+ /**
+ * This method installs any listeners for the scrollbar.
+ * This method also installs listeners for things such as
+ * the JButtons and the timer.
+ */
+ protected void installListeners()
+ {
+ scrollListener = createScrollListener();
+ trackListener = createTrackListener();
+ buttonListener = createArrowButtonListener();
+ modelListener = createModelListener();
+ propertyChangeListener = createPropertyChangeListener();
+
+ scrollbar.addMouseMotionListener(trackListener);
+ scrollbar.addMouseListener(trackListener);
+
+ incrButton.addMouseListener(buttonListener);
+ decrButton.addMouseListener(buttonListener);
+
+ scrollbar.addPropertyChangeListener(propertyChangeListener);
+ scrollbar.getModel().addChangeListener(modelListener);
+
+ scrollTimer.addActionListener(scrollListener);
+ }
+
+ /**
+ * This method installs the UI for the component.
+ * This can include setting up listeners, defaults,
+ * and components. This also includes initializing any data
+ * objects.
+ *
+ * @param c The JComponent to install.
+ */
+ public void installUI(JComponent c)
+ {
+ super.installUI(c);
+ if (c instanceof JScrollBar)
+ {
+ scrollbar = (JScrollBar) c;
+
+ trackRect = new Rectangle();
+ thumbRect = new Rectangle();
+
+ scrollTimer = new Timer();
+ scrollTimer.setDelay(200);
+ scrollTimer.setRepeats(true);
+
+ installComponents();
+ installListeners();
+ installDefaults();
+ configureScrollBarColors();
+
+ calculatePreferredSize();
+ layoutContainer(scrollbar);
+ }
+ }
+
+ /**
+ * This method lays out the scrollbar.
+ *
+ * @param scrollbarContainer The Container to layout.
+ */
+ public void layoutContainer(Container scrollbarContainer)
+ {
+ if (scrollbarContainer instanceof JScrollBar)
+ {
+ if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL)
+ layoutHScrollbar((JScrollBar) scrollbarContainer);
+ else
+ layoutVScrollbar((JScrollBar) scrollbarContainer);
+ }
+ }
+
+ /**
+ * This method lays out the scrollbar horizontally.
+ *
+ * @param sb The JScrollBar to layout.
+ */
+ protected void layoutHScrollbar(JScrollBar sb)
+ {
+ // All we have to do is layout the 2 buttons?
+ Rectangle vr = new Rectangle();
+ SwingUtilities.calculateInnerArea(scrollbar, vr);
+
+ // Update the rectangles.
+ getTrackBounds();
+ getThumbBounds();
+
+ Dimension incrDims = incrButton.getPreferredSize();
+ Dimension decrDims = decrButton.getPreferredSize();
+
+ decrButton.setBounds(vr.x, vr.y, decrDims.width, trackRect.height);
+ incrButton.setBounds(trackRect.x + trackRect.width, vr.y, incrDims.width,
+ trackRect.height);
+ }
+
+ /**
+ * This method lays out the scrollbar vertically.
+ *
+ * @param sb The JScrollBar to layout.
+ */
+ protected void layoutVScrollbar(JScrollBar sb)
+ {
+ Rectangle vr = new Rectangle();
+ SwingUtilities.calculateInnerArea(scrollbar, vr);
+
+ // Update rectangles
+ getTrackBounds();
+ getThumbBounds();
+
+ Dimension incrDims = incrButton.getPreferredSize();
+ Dimension decrDims = decrButton.getPreferredSize();
+
+ decrButton.setBounds(vr.x, vr.y, trackRect.width, decrDims.height);
+ incrButton.setBounds(vr.x, trackRect.y + trackRect.height,
+ trackRect.width, incrDims.height);
+ }
+
+ /**
+ * This method returns the minimum size required for the layout.
+ *
+ * @param scrollbarContainer The Container that is laid out.
+ *
+ * @return The minimum size.
+ */
+ public Dimension minimumLayoutSize(Container scrollbarContainer)
+ {
+ return preferredLayoutSize(scrollbarContainer);
+ }
+
+ /**
+ * This method is called when the component is painted.
+ *
+ * @param g The Graphics object to paint with.
+ * @param c The JComponent to paint.
+ */
+ public void paint(Graphics g, JComponent c)
+ {
+ layoutContainer(scrollbar);
+
+// Rectangle r = incrButton.getBounds();
+// SwingUtilities.paintComponent(g, incrButton, scrollbar, r.x, r.y, r.width,
+// r.height);
+// r = decrButton.getBounds();
+// SwingUtilities.paintComponent(g, decrButton, scrollbar, r.x, r.y, r.width,
+// r.height);
+
+ paintTrack(g, c, getTrackBounds());
+ paintThumb(g, c, getThumbBounds());
+
+ if (trackHighlight == INCREASE_HIGHLIGHT)
+ paintIncreaseHighlight(g);
+ else if (trackHighlight == DECREASE_HIGHLIGHT)
+ paintDecreaseHighlight(g);
+ }
+
+ /**
+ * This method is called when repainting and the mouse is
+ * pressed in the track. It paints the track below the thumb
+ * with the trackHighlight color.
+ *
+ * @param g The Graphics object to paint with.
+ */
+ protected void paintDecreaseHighlight(Graphics g)
+ {
+ Color saved = g.getColor();
+
+ g.setColor(trackHighlightColor);
+ if (scrollbar.getOrientation() == HORIZONTAL)
+ g.fillRect(trackRect.x, trackRect.y, thumbRect.x - trackRect.x,
+ trackRect.height);
+ else
+ g.fillRect(trackRect.x, trackRect.y, trackRect.width,
+ thumbRect.y - trackRect.y);
+ g.setColor(saved);
+ }
+
+ /**
+ * This method is called when repainting and the mouse is
+ * pressed in the track. It paints the track above the thumb
+ * with the trackHighlight color.
+ *
+ * @param g The Graphics objet to paint with.
+ */
+ protected void paintIncreaseHighlight(Graphics g)
+ {
+ Color saved = g.getColor();
+
+ g.setColor(trackHighlightColor);
+ if (scrollbar.getOrientation() == HORIZONTAL)
+ g.fillRect(thumbRect.x + thumbRect.width, trackRect.y,
+ trackRect.x + trackRect.width - thumbRect.x - thumbRect.width,
+ trackRect.height);
+ else
+ g.fillRect(trackRect.x, thumbRect.y + thumbRect.height,
+ trackRect.width,
+ trackRect.y + trackRect.height - thumbRect.y -
+ thumbRect.height);
+ g.setColor(saved);
+ }
+
+ /**
+ * This method paints the thumb.
+ *
+ * @param g The Graphics object to paint with.
+ * @param c The Component that is being painted.
+ * @param thumbBounds The thumb bounds.
+ */
+ protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds)
+ {
+ Color saved = g.getColor();
+ Point x;
+ Point y;
+ Point z;
+ Polygon lines;
+
+ g.setColor(thumbHighlightColor);
+ x = new Point(thumbBounds.x + 1, thumbBounds.y + 1);
+ y = new Point(x);
+ y.translate(thumbBounds.width - 2, 0);
+ z = new Point(x);
+ z.translate(0, thumbBounds.height - 2);
+
+ lines = new Polygon(new int[] { x.x, y.x, z.x },
+ new int[] { x.y, y.y, z.y }, 3);
+
+ g.drawPolygon(lines);
+
+ g.setColor(thumbLightShadowColor);
+ x = new Point(thumbBounds.x + thumbBounds.width - 1,
+ thumbBounds.y + thumbBounds.height - 1);
+ y = new Point(x);
+ y.translate(-(thumbBounds.width - 2), 0);
+ z = new Point(x);
+ z.translate(0, -(thumbBounds.height - 2));
+
+ lines = new Polygon(new int[] { x.x, y.x, z.x },
+ new int[] { x.y, y.y, z.y }, 3);
+ g.drawPolygon(lines);
+
+ g.setColor(thumbDarkShadowColor);
+ x = new Point(thumbBounds.x + thumbBounds.width,
+ thumbBounds.y + thumbBounds.height);
+ y = new Point(x);
+ y.translate(-thumbBounds.width, 0);
+ z = new Point(x);
+ z.translate(0, -thumbBounds.height);
+
+ lines = new Polygon(new int[] { x.x, y.x, z.x },
+ new int[] { x.y, y.y, z.y }, 3);
+ g.drawPolygon(lines);
+
+ g.setColor(thumbColor);
+ g.fillRect(thumbBounds.x, thumbBounds.y, thumbBounds.width,
+ thumbBounds.height);
+
+ g.setColor(saved);
+ }
+
+ /**
+ * This method paints the track.
+ *
+ * @param g The Graphics object to paint with.
+ * @param c The JComponent being painted.
+ * @param trackBounds The track's bounds.
+ */
+ protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds)
+ {
+ Color saved = g.getColor();
+ g.setColor(trackColor);
+ g.fill3DRect(trackBounds.x, trackBounds.y, trackBounds.width,
+ trackBounds.height, false);
+ g.setColor(saved);
+ }
+
+ /**
+ * This method returns the preferred size for the layout.
+ *
+ * @param scrollbarContainer The Container to find a size for.
+ *
+ * @return The preferred size for the layout.
+ */
+ public Dimension preferredLayoutSize(Container scrollbarContainer)
+ {
+ if (scrollbarContainer instanceof JComponent)
+ return getPreferredSize((JComponent) scrollbarContainer);
+ else
+ return null;
+ }
+
+ /**
+ * This method removes a child component from the layout.
+ *
+ * @param child The child to remove.
+ */
+ public void removeLayoutComponent(Component child)
+ {
+ // You should not be removing stuff from this component.
+ }
+
+ /**
+ * The method scrolls the thumb by a block in the
+ * direction specified.
+ *
+ * @param direction The direction to scroll.
+ */
+ protected void scrollByBlock(int direction)
+ {
+ scrollbar.setValue(scrollbar.getValue() + scrollbar.getBlockIncrement(direction));
+ }
+
+ /**
+ * The method scrolls the thumb by a unit in the
+ * direction specified.
+ *
+ * @param direction The direction to scroll.
+ */
+ protected void scrollByUnit(int direction)
+ {
+ scrollbar.setValue(scrollbar.getValue() + scrollbar.getUnitIncrement(direction));
+ }
+
+ /**
+ * This method sets the thumb's bounds.
+ *
+ * @param x The X position of the thumb.
+ * @param y The Y position of the thumb.
+ * @param width The width of the thumb.
+ * @param height The height of the thumb.
+ */
+ protected void setThumbBounds(int x, int y, int width, int height)
+ {
+ thumbRect.x = x;
+ thumbRect.y = y;
+ thumbRect.width = width;
+ thumbRect.height = height;
+ }
+
+ /**
+ * This method uninstalls any components that
+ * are a part of or related to this scrollbar.
+ */
+ protected void uninstallComponents()
+ {
+ scrollbar.remove(incrButton);
+ scrollbar.remove(decrButton);
+ incrButton = null;
+ decrButton = null;
+ }
+
+ /**
+ * This method uninstalls any defaults that this
+ * scrollbar acquired from the Basic L&F defaults.
+ */
+ protected void uninstallDefaults()
+ {
+ scrollbar.setForeground(null);
+ scrollbar.setBackground(null);
+ scrollbar.setBorder(null);
+ }
+
+ /**
+ * This method uninstalls any keyboard
+ * actions this scrollbar acquired during install.
+ */
+ protected void uninstallKeyboardActions()
+ {
+ // FIXME: implement.
+ }
+
+ /**
+ * This method uninstalls any listeners that
+ * were registered during install.
+ */
+ protected void uninstallListeners()
+ {
+ scrollTimer.removeActionListener(scrollListener);
+
+ scrollbar.getModel().removeChangeListener(modelListener);
+ scrollbar.removePropertyChangeListener(propertyChangeListener);
+
+ decrButton.removeMouseListener(buttonListener);
+ incrButton.removeMouseListener(buttonListener);
+
+ scrollbar.removeMouseListener(trackListener);
+ scrollbar.removeMouseMotionListener(trackListener);
+
+ propertyChangeListener = null;
+ modelListener = null;
+ buttonListener = null;
+ trackListener = null;
+ scrollListener = null;
+ }
+
+ /**
+ * This method uninstalls the UI. This includes
+ * removing any defaults, listeners, and components
+ * that this UI may have initialized. It also nulls
+ * any instance data.
+ *
+ * @param c The Component to uninstall for.
+ */
+ public void uninstallUI(JComponent c)
+ {
+ uninstallDefaults();
+ uninstallListeners();
+ uninstallComponents();
+
+ scrollTimer = null;
+
+ thumbRect = null;
+ trackRect = null;
+
+ trackColor = null;
+ trackHighlightColor = null;
+ thumbColor = null;
+ thumbHighlightColor = null;
+ thumbDarkShadowColor = null;
+ thumbLightShadowColor = null;
+
+ scrollbar = null;
+ }
+
+ /**
+ * This method returns the value in the scrollbar's range given the y
+ * coordinate. If the value is out of range, it will return the closest
+ * legal value.
+ *
+ * @param yPos The y coordinate to calculate a value for.
+ *
+ * @return The value for the y coordinate.
+ */
+ private int valueForYPosition(int yPos)
+ {
+ int min = scrollbar.getMinimum();
+ int max = scrollbar.getMaximum();
+ int len = trackRect.height;
+
+ int value;
+
+ // If the length is 0, you shouldn't be able to even see where the thumb is.
+ // This really shouldn't ever happen, but just in case, we'll return the middle.
+ if (len == 0)
+ return ((max - min) / 2);
+
+ value = ((yPos - trackRect.y) * (max - min) / len + min);
+
+ // If this isn't a legal value, then we'll have to move to one now.
+ if (value > max)
+ value = max;
+ else if (value < min)
+ value = min;
+ return value;
+ }
+
+ /**
+ * This method returns the value in the scrollbar's range given the x
+ * coordinate. If the value is out of range, it will return the closest
+ * legal value.
+ *
+ * @param xPos The x coordinate to calculate a value for.
+ *
+ * @return The value for the x coordinate.
+ */
+ private int valueForXPosition(int xPos)
+ {
+ int min = scrollbar.getMinimum();
+ int max = scrollbar.getMaximum();
+ int len = trackRect.width;
+
+ int value;
+
+ // If the length is 0, you shouldn't be able to even see where the slider is.
+ // This really shouldn't ever happen, but just in case, we'll return the middle.
+ if (len == 0)
+ return ((max - min) / 2);
+
+ value = ((xPos - trackRect.x) * (max - min) / len + min);
+
+ // If this isn't a legal value, then we'll have to move to one now.
+ if (value > max)
+ value = max;
+ else if (value < min)
+ value = min;
+ return value;
+ }
+}
diff --git a/libjava/javax/swing/plaf/basic/BasicScrollPaneUI.java b/libjava/javax/swing/plaf/basic/BasicScrollPaneUI.java
index 2dac794..4f60fb4 100644
--- a/libjava/javax/swing/plaf/basic/BasicScrollPaneUI.java
+++ b/libjava/javax/swing/plaf/basic/BasicScrollPaneUI.java
@@ -41,14 +41,14 @@ package javax.swing.plaf.basic;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JComponent;
+import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
+import javax.swing.ScrollPaneLayout;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.ScrollPaneUI;
public class BasicScrollPaneUI extends ScrollPaneUI
{
- int min_w = 50;
- int min_h = 50;
public static ComponentUI createUI(final JComponent c)
{
@@ -61,33 +61,25 @@ public class BasicScrollPaneUI extends ScrollPaneUI
super.installUI(c);
}
+ public Dimension getMinimumSize(JComponent c)
+ {
+ JScrollPane p = (JScrollPane ) c;
+ ScrollPaneLayout sl = (ScrollPaneLayout) p.getLayout();
+ return sl.minimumLayoutSize(c);
+ }
public Dimension getPreferredSize(JComponent c)
{
JScrollPane p = (JScrollPane ) c;
-
- Dimension d = new Dimension(min_w,
- min_h);
-
- Dimension a = p.getViewport().getPreferredSize();
-
- if (a != null)
- {
- d.width = Math.max(d.width, a.width);
- d.height = Math.max(d.height, a.height);
- }
-
-
- System.out.println("BasicScrollPaneUI->preff->"+d);
- return d;
+ ScrollPaneLayout sl = (ScrollPaneLayout) p.getLayout();
+ return sl.preferredLayoutSize(c);
}
+
public void paint(Graphics g, JComponent c)
{
- System.out.println("BasicScrollPaneUI->paint()->"+c);
-
- JScrollPane p = (JScrollPane ) c;
- p.getViewport().paint(g);
+ // do nothing; the normal painting-of-children algorithm, along with
+ // ScrollPaneLayout, does all the relevant work.
}
}
diff --git a/libjava/javax/swing/plaf/basic/BasicSeparatorUI.java b/libjava/javax/swing/plaf/basic/BasicSeparatorUI.java
new file mode 100644
index 0000000..b7df0ac
--- /dev/null
+++ b/libjava/javax/swing/plaf/basic/BasicSeparatorUI.java
@@ -0,0 +1,266 @@
+/* BasicSeparatorUI.java
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.plaf.basic;
+
+import java.awt.Dimension;
+import java.awt.Color;
+import java.awt.Rectangle;
+import java.awt.Graphics;
+import java.awt.Insets;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.SeparatorUI;
+import javax.swing.UIDefaults;
+import javax.swing.UIManager;
+import javax.swing.JComponent;
+import javax.swing.JSeparator;
+import javax.swing.SwingUtilities;
+
+/**
+ * The Basic L&F UI delegate for JSeparator.
+ */
+public class BasicSeparatorUI extends SeparatorUI
+{
+ /** The shadow color. */
+ protected Color shadow;
+
+ /** The highlight color. */
+ protected Color highlight;
+
+ /**
+ * Creates a new UI delegate for the given JComponent.
+ *
+ * @param c The JComponent to create a delegate for.
+ *
+ * @return A new BasicSeparatorUI.
+ */
+ public static ComponentUI createUI(JComponent c)
+ {
+ return new BasicSeparatorUI();
+ }
+
+ /**
+ * This method installs the UI for the given JComponent.
+ * This can include installing defaults, listeners, and
+ * initializing any instance data.
+ *
+ * @param c The JComponent that is having this UI installed.
+ */
+ public void installUI(JComponent c)
+ {
+ super.installUI(c);
+
+ if (c instanceof JSeparator)
+ {
+ JSeparator s = (JSeparator) c;
+
+ installDefaults(s);
+ installListeners(s);
+ }
+ }
+
+ /**
+ * Uninstalls the UI for the given JComponent. This
+ * method reverses what was done when installing
+ * the UI on the JComponent.
+ *
+ * @param c The JComponent that is having this UI uninstalled.
+ */
+ public void uninstallUI(JComponent c)
+ {
+ if (c instanceof JSeparator)
+ {
+ JSeparator s = (JSeparator) c;
+
+ uninstallListeners(s);
+ uninstallDefaults(s);
+ }
+ }
+
+ /**
+ * This method installs the defaults that are given by
+ * the Basic L&F.
+ *
+ * @param s The JSeparator that is being installed.
+ */
+ protected void installDefaults(JSeparator s)
+ {
+ UIDefaults defaults = UIManager.getLookAndFeelDefaults();
+
+ shadow = defaults.getColor("Separator.shadow");
+ highlight = defaults.getColor("Separator.highlight");
+ }
+
+ /**
+ * This method removes the defaults that were given
+ * by the Basic L&F.
+ *
+ * @param s The JSeparator that is being uninstalled.
+ */
+ protected void uninstallDefaults(JSeparator s)
+ {
+ shadow = null;
+ highlight = null;
+ }
+
+ /**
+ * This method installs any listeners that need
+ * to be attached to the JSeparator or any of its
+ * components.
+ *
+ * @param s The JSeparator that is being installed.
+ */
+ protected void installListeners(JSeparator s)
+ {
+ // Separators don't receive events.
+ }
+
+ /**
+ * This method uninstalls any listeners that
+ * were installed during the install UI process.
+ *
+ * @param s The JSeparator that is being uninstalled.
+ */
+ protected void uninstallListeners(JSeparator s)
+ {
+ // Separators don't receive events.
+ }
+
+ /**
+ * The separator is made of two lines. The top line will be
+ * the highlight color (or left line if it's vertical). The bottom
+ * or right line will be the shadow color. The two lines will
+ * be centered inside the bounds box. If the separator is horizontal,
+ * then it will be vertically centered, or if it's vertical, it will
+ * be horizontally centered.
+ *
+ * @param g The Graphics object to paint with
+ * @param c The JComponent to paint.
+ */
+ public void paint(Graphics g, JComponent c)
+ {
+ Rectangle r = new Rectangle();
+ SwingUtilities.calculateInnerArea(c, r);
+ Color saved = g.getColor();
+
+ int midAB = r.width / 2 + r.x;
+ int midAD = r.height / 2 + r.y;
+
+ JSeparator s;
+ if (c instanceof JSeparator)
+ s = (JSeparator) c;
+ else
+ return;
+
+ if (s.getOrientation() == JSeparator.HORIZONTAL)
+ {
+ g.setColor(highlight);
+ g.drawLine(r.x, midAD, r.x + r.width, midAD);
+
+ g.setColor(shadow);
+ g.drawLine(r.x, midAD + 1, r.x + r.width, midAD + 1);
+ }
+ else
+ {
+ g.setColor(highlight);
+ g.drawLine(midAB, r.y, midAB, r.y + r.height);
+
+ g.setColor(shadow);
+ g.drawLine(midAB + 1, r.y, midAB + 1, r.y + r.height);
+ }
+ }
+
+ /**
+ * This method returns the preferred size of the
+ * JComponent.
+ *
+ * @param c The JComponent to measure.
+ *
+ * @return The preferred size.
+ */
+ public Dimension getPreferredSize(JComponent c)
+ {
+ Dimension dims = new Dimension(0, 0);
+ Insets insets = c.getInsets();
+
+ if (c instanceof JSeparator)
+ {
+ JSeparator s = (JSeparator) c;
+
+ if (s.getOrientation() == JSeparator.HORIZONTAL)
+ {
+ dims.height = 2;
+ dims.width = 40;
+ }
+ else
+ {
+ dims.width = 2;
+ dims.height = 40;
+ }
+ }
+ dims.width += insets.left + insets.right;
+ dims.height += insets.top + insets.bottom;
+
+ return dims;
+ }
+
+ /**
+ * This method returns the minimum size of the
+ * JComponent.
+ *
+ * @param c The JComponent to measure.
+ *
+ * @return The minimum size.
+ */
+ public Dimension getMinimumSize(JComponent c)
+ {
+ return getPreferredSize(c);
+ }
+
+ /**
+ * This method returns the maximum size of the
+ * JComponent.
+ *
+ * @param c The JComponent to measure.
+ *
+ * @return The maximum size.
+ */
+ public Dimension getMaximumSize(JComponent c)
+ {
+ return getPreferredSize(c);
+ }
+}
diff --git a/libjava/javax/swing/plaf/basic/BasicSliderUI.java b/libjava/javax/swing/plaf/basic/BasicSliderUI.java
new file mode 100644
index 0000000..2ee481e
--- /dev/null
+++ b/libjava/javax/swing/plaf/basic/BasicSliderUI.java
@@ -0,0 +1,2213 @@
+/* BasicSliderUI.java
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GNU Classpath.
+
+GNU Classpath is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU Classpath is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Classpath; see the file COPYING. If not, write to the
+Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+02111-1307 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version. */
+
+package javax.swing.plaf.basic;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.ComponentOrientation;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Insets;
+import java.awt.Point;
+import java.awt.Polygon;
+import java.awt.Rectangle;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ComponentListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.awt.event.InputEvent;
+import java.awt.event.MouseEvent;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JSlider;
+import javax.swing.KeyStroke;
+import javax.swing.SwingUtilities;
+import javax.swing.Timer;
+import javax.swing.UIDefaults;
+import javax.swing.UIManager;
+import javax.swing.BoundedRangeModel;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.MouseInputAdapter;
+import javax.swing.plaf.ComponentUI;
+import javax.swing.plaf.SliderUI;
+
+
+/**
+ * <p>
+ * BasicSliderUI.java This is the UI delegate in the Basic look and feel that
+ * paints JSliders.
+ * </p>
+ *
+ * <p>
+ * The UI delegate keeps track of 6 rectangles that place the various parts of
+ * the JSlider inside the component.
+ * </p>
+ *
+ * <p>
+ * The rectangles are organized as follows:
+ * </p>
+ * <pre>
+ * +-------------------------------------------------------+ <-- focusRect
+ * | |
+ * | +==+-------------------+==+--------------------+==+<------ contentRect
+ * | | | | |<---thumbRect | | |
+ * | | | TRACK | | |<--------- trackRect
+ * | | +-------------------+==+--------------------+ | |
+ * | | | | | |
+ * | | | TICKS GO HERE |<-------- tickRect
+ * | | | | | |
+ * | +==+-------------------------------------------+==+ |
+ * | | | | | |
+ * | | | | |<----- labelRect
+ * | | | LABELS GO HERE | | |
+ * | | | | | |
+ * | | | | | |
+ * | | | | | |
+ * | | | | | |
+ * | | | | |
+ * </pre>
+ *
+ * <p>
+ * The space between the contentRect and the focusRect are the FocusInsets.
+ * </p>
+ *
+ * <p>
+ * The space between the focusRect and the component bounds is the insetCache
+ * which are the component's insets.
+ * </p>
+ *
+ * <p>
+ * The top of the thumb is the top of the contentRect. The trackRect has to be
+ * as tall as the thumb.
+ * </p>
+ *
+ * <p>
+ * The trackRect and tickRect do not start from the left edge of the
+ * focusRect. They are trackBuffer away from each side of the focusRect. This
+ * is so that the thumb has room to move.
+ * </p>
+ *
+ * <p>
+ * The labelRect does start right against the contentRect's left and right
+ * edges and it gets all remaining space.
+ * </p>
+ */
+public class BasicSliderUI extends SliderUI
+{
+ /**
+ * Helper class that listens to the {@link JSlider}'s model for changes.
+ */
+ protected class ChangeHandler implements ChangeListener
+ {
+ /**
+ * Called when the slider's model has been altered. The UI delegate should
+ * recalculate any rectangles that are dependent on the model for their
+ * positions and repaint.
+ *
+ * @param e A static {@link ChangeEvent} passed from the model.
+ */
+ public void stateChanged(ChangeEvent e)
+ {
+ // Maximum, minimum, and extent values will be taken
+ // care of automatically when the slider is repainted.
+
+ // Only thing that needs recalculation is the thumb.
+ calculateThumbLocation();
+ slider.repaint();
+ }
+ }
+
+ /**
+ * Helper class that listens for resize events.
+ */
+ protected class ComponentHandler extends ComponentAdapter
+ {
+ /**
+ * Called when the size of the component changes. The UI delegate should
+ * recalculate any rectangles that are dependent on the model for their
+ * positions and repaint.
+ *
+ * @param e A {@link ComponentEvent}.
+ */
+ public void componentResized(ComponentEvent e)
+ {
+ calculateGeometry();
+
+ slider.revalidate();
+ slider.repaint();
+ }
+ }
+
+ /**
+ * Helper class that listens for focus events.
+ */
+ protected class FocusHandler implements FocusListener
+ {
+ /**
+ * Called when the {@link JSlider} has gained focus. It should repaint
+ * the slider with the focus drawn.
+ *
+ * @param e A {@link FocusEvent}.
+ */
+ public void focusGained(FocusEvent e)
+ {
+ // FIXME: implement.
+ }
+
+ /**
+ * Called when the {@link JSlider} has lost focus. It should repaint the
+ * slider without the focus drawn.
+ *
+ * @param e A {@link FocusEvent}.
+ */
+ public void focusLost(FocusEvent e)
+ {
+ // FIXME: implement.
+ }
+ }
+
+ /**
+ * Helper class that listens for changes to the properties of the {@link
+ * JSlider}.
+ */
+ protected class PropertyChangeHandler implements PropertyChangeListener
+ {
+ /**
+ * Called when one of the properties change. The UI should recalculate any
+ * rectangles if necessary and repaint.
+ *
+ * @param e A {@link PropertyChangeEvent}.
+ */
+ public void propertyChange(PropertyChangeEvent e)
+ {
+ // Check for orientation changes.
+ if (e.getPropertyName().equals(JSlider.ORIENTATION_CHANGED_PROPERTY))
+ recalculateIfOrientationChanged();
+ else if (e.getPropertyName().equals(JSlider.MODEL_CHANGED_PROPERTY))
+ {
+ BoundedRangeModel oldModel = (BoundedRangeModel) e.getOldValue();
+ oldModel.removeChangeListener(changeListener);
+ slider.getModel().addChangeListener(changeListener);
+ calculateThumbLocation();
+ }
+ // elif the componentOrientation changes (this is a bound property,
+ // just undocumented) we change leftToRightCache. In Sun's
+ // implementation, the LTR cache changes on a repaint. This is strange
+ // since there is no need to do so. We could events here and
+ // update the cache.
+
+ // elif the border/insets change, we recalculateInsets.
+ slider.repaint();
+ }
+ }
+
+ /**
+ * Helper class that listens to our swing timer. This class is responsible
+ * for listening to the timer and moving the thumb in the proper direction
+ * every interval.
+ */
+ protected class ScrollListener implements ActionListener
+ {
+ /** Indicates which direction the thumb should scroll. */
+ private transient int direction;
+
+ /** Indicates whether we should scroll in blocks or in units. */
+ private transient boolean block;
+
+ /**
+ * Creates a new ScrollListener object.
+ */
+ public ScrollListener()
+ {
+ direction = POSITIVE_SCROLL;
+ block = false;
+ }
+
+ /**
+ * Creates a new ScrollListener object.
+ *
+ * @param dir The direction to scroll in.
+ * @param block If movement will be in blocks.
+ */
+ public ScrollListener(int dir, boolean block)
+ {
+ direction = dir;
+ this.block = block;
+ }
+
+ /**
+ * Called every time the swing timer reaches its interval. If the thumb
+ * needs to move, then this method will move the thumb one block or unit
+ * in the direction desired. Otherwise, the timer can be stopped.
+ *
+ * @param e An {@link ActionEvent}.
+ */
+ public void actionPerformed(ActionEvent e)
+ {
+ if (! trackListener.shouldScroll(direction))
+ {
+ scrollTimer.stop();
+ return;
+ }
+
+ if (block)
+ scrollByBlock(direction);
+ else
+ scrollByUnit(direction);
+ }
+
+ /**
+ * Sets the direction to scroll in.
+ *
+ * @param direction The direction to scroll in.
+ */
+ public void setDirection(int direction)
+ {
+ this.direction = direction;
+ }
+
+ /**
+ * Sets whether movement will be in blocks.
+ *
+ * @param block If movement will be in blocks.
+ */
+ public void setScrollByBlock(boolean block)
+ {
+ this.block = block;
+ }
+ }
+
+ /**
+ * Helper class that listens for mouse events.
+ */
+ protected class TrackListener extends MouseInputAdapter
+ {
+ /** The current X position of the mouse. */
+ protected int currentMouseX;
+
+ /** The current Y position of the mouse. */
+ protected int currentMouseY;
+
+ /** The offset between the current slider value
+ and the cursor's position. */
+ protected int offset;
+
+ /**
+ * Called when the mouse has been dragged. This should find the mouse's
+ * current position and adjust the value of the {@link JSlider}
+ * accordingly.
+ *
+ * @param e A {@link MouseEvent}
+ */
+ public void mouseDragged(MouseEvent e)
+ {
+ currentMouseX = e.getX();
+ currentMouseY = e.getY();
+ if (slider.getValueIsAdjusting())
+ {
+ int value;
+ if (slider.getOrientation() == JSlider.HORIZONTAL)
+ value = valueForXPosition(currentMouseX) - offset;
+ else
+ value = valueForYPosition(currentMouseY) - offset;
+
+ slider.setValue(value);
+ }
+ }
+
+ /**
+ * Called when the mouse has moved over a component but no buttons have
+ * been pressed yet.
+ *
+ * @param e A {@link MouseEvent}
+ */
+ public void mouseMoved(MouseEvent e)
+ {
+ // Don't care that we're moved unless we're dragging.
+ }
+
+ /**
+ * Called when the mouse is pressed. When the press occurs on the thumb
+ * itself, the {@link JSlider} should have its value set to where the
+ * mouse was pressed. If the press occurs on the track, then the thumb
+ * should move one block towards the direction of the mouse.
+ *
+ * @param e A {@link MouseEvent}
+ */
+ public void mousePressed(MouseEvent e)
+ {
+ currentMouseX = e.getX();
+ currentMouseY = e.getY();
+
+ int value;
+ if (slider.getOrientation() == JSlider.HORIZONTAL)
+ value = valueForXPosition(currentMouseX);
+ else
+ value = valueForYPosition(currentMouseY);
+
+ if (slider.getSnapToTicks())
+ value = findClosestTick(value);
+
+ if (value == slider.getValue())
+ return;
+
+ // If the thumb is hit, then we don't need to set the timers to move it.
+ if (!thumbRect.contains(e.getPoint()))
+ {
+ // The mouse has hit some other part of the slider.
+ // The value moves no matter where in the slider you hit.
+ if (value > slider.getValue())
+ scrollDueToClickInTrack(POSITIVE_SCROLL);
+ else
+ scrollDueToClickInTrack(NEGATIVE_SCROLL);
+ }
+ else
+ {
+ slider.setValueIsAdjusting(true);
+ offset = value - slider.getValue();
+ }
+ }
+
+ /**
+ * Called when the mouse is released. This should stop the timer that
+ * scrolls the thumb.
+ *
+ * @param e A {@link MouseEvent}
+ */
+ public void mouseReleased(MouseEvent e)
+ {
+ currentMouseX = e.getX();
+ currentMouseY = e.getY();
+
+ if (slider.getValueIsAdjusting())
+ {
+ slider.setValueIsAdjusting(false);
+ if (slider.getSnapToTicks())
+ slider.setValue(findClosestTick(slider.getValue()));
+ }
+ if (scrollTimer != null)
+ scrollTimer.stop();
+ }
+
+ /**
+ * Indicates whether the thumb should scroll in the given direction.
+ *
+ * @param direction The direction to check.
+ *
+ * @return True if the thumb should move in that direction.
+ */
+ public boolean shouldScroll(int direction)
+ {
+ int value;
+ if (slider.getOrientation() == JSlider.HORIZONTAL)
+ value = valueForXPosition(currentMouseX);
+ else
+ value = valueForYPosition(currentMouseY);
+
+ if (direction == POSITIVE_SCROLL)
+ return (value > slider.getValue());
+ else
+ return (value < slider.getValue());
+ }
+ }
+
+ /** The preferred height of the thumb. */
+ private transient int thumbHeight;
+
+ /** The preferred width of the thumb. */
+ private transient int thumbWidth;
+
+ /** The preferred height of the tick rectangle. */
+ private transient int tickHeight;
+
+ /** Listener for changes from the model. */
+ protected ChangeListener changeListener;
+
+ /** Listener for changes to the {@link JSlider}. */
+ protected PropertyChangeListener propertyChangeListener;
+
+ /** Listener for the scrollTimer. */
+ protected ScrollListener scrollListener;
+
+ /** Listener for component resizing. */
+ protected ComponentListener componentListener;
+
+ /** Listener for focus handling. */
+ protected FocusListener focusListener;
+
+ /** Listener for mouse events. */
+ protected TrackListener trackListener;
+
+ /** The insets between the FocusRectangle and the ContentRectangle. */
+ protected Insets focusInsets;
+
+ /** The {@link JSlider}'s insets. */
+ protected Insets insetCache;
+
+ /** Rectangle describing content bounds. See diagram above. */
+ protected Rectangle contentRect;
+
+ /** Rectangle describing focus bounds. See diagram above. */
+ protected Rectangle focusRect;
+
+ /** Rectangle describing the thumb's bounds. See diagram above. */
+ protected Rectangle thumbRect;
+
+ /** Rectangle describing the tick bounds. See diagram above. */
+ protected Rectangle tickRect;
+
+ /** Rectangle describing the label bounds. See diagram above. */
+ protected Rectangle labelRect;
+
+ /** Rectangle describing the track bounds. See diagram above. */
+ protected Rectangle trackRect;
+
+ /** FIXME: use this somewhere. */
+ public static final int MAX_SCROLL = 2;
+
+ /** FIXME: use this somewhere. */
+ public static final int MIN_SCROLL = -2;
+
+ /** A constant describing scrolling towards the minimum. */
+ public static final int NEGATIVE_SCROLL = -1;
+
+ /** A constant describing scrolling towards the maximum. */
+ public static final int POSITIVE_SCROLL = 1;
+
+ /** The gap between the edges of the contentRect and trackRect. */
+ protected int trackBuffer;
+
+ /** Whether this slider is actually drawn left to right. */
+ protected boolean leftToRightCache;
+
+ /** A timer that periodically moves the thumb. */
+ protected Timer scrollTimer;
+
+ /** A reference to the {@link JSlider} that this UI was created for. */
+ protected JSlider slider;
+
+ /** The shadow color. */
+ private transient Color shadowColor;
+
+ /** The highlight color. */
+ private transient Color highlightColor;
+
+ /** The focus color. */
+ private transient Color focusColor;
+
+ /**
+ * Creates a new Basic look and feel Slider UI.
+ *
+ * @param b The {@link JSlider} that this UI was created for.
+ */
+ public BasicSliderUI(JSlider b)
+ {
+ super();
+ }
+
+ /**
+ * Gets the shadow color to be used for this slider. The shadow color is the
+ * color used for drawing the top and left edges of the track.
+ *
+ * @return The shadow color.
+ */
+ protected Color getShadowColor()
+ {
+ return shadowColor;
+ }
+
+ /**
+ * Gets the highlight color to be used for this slider. The highlight color
+ * is the color used for drawing the bottom and right edges of the track.
+ *
+ * @return The highlight color.
+ */
+ protected Color getHighlightColor()
+ {
+ return highlightColor;
+ }
+
+ /**
+ * Gets the focus color to be used for this slider. The focus color is the
+ * color used for drawing the focus rectangle when the component gains
+ * focus.
+ *
+ * @return The focus color.
+ */
+ protected Color getFocusColor()
+ {
+ return focusColor;
+ }
+
+ /**
+ * Factory method to create a BasicSliderUI for the given {@link
+ * JComponent}, which should be a {@link JSlider}.
+ *
+ * @param b The {@link JComponent} a UI is being created for.
+ *
+ * @return A BasicSliderUI for the {@link JComponent}.
+ */
+ public static ComponentUI createUI(JComponent b)
+ {
+ return new BasicSliderUI((JSlider) b);
+ }
+
+ /**
+ * Installs and initializes all fields for this UI delegate. Any properties
+ * of the UI that need to be initialized and/or set to defaults will be
+ * done now. It will also install any listeners necessary.
+ *
+ * @param c The {@link JComponent} that is having this UI installed.
+ */
+ public void installUI(JComponent c)
+ {
+ super.installUI(c);
+ if (c instanceof JSlider)
+ {
+ slider = (JSlider) c;
+
+ focusRect = new Rectangle();
+ contentRect = new Rectangle();
+ thumbRect = new Rectangle();
+ trackRect = new Rectangle();
+ tickRect = new Rectangle();
+ labelRect = new Rectangle();
+
+ insetCache = slider.getInsets();
+ leftToRightCache = ! slider.getInverted();
+
+ scrollTimer = new Timer();
+ scrollTimer.setDelay(200);
+ scrollTimer.setRepeats(true);
+
+ installDefaults(slider);
+ installListeners(slider);
+ installKeyboardActions(slider);
+
+ calculateFocusRect();
+
+ calculateContentRect();
+ calculateThumbSize();
+ calculateTrackBuffer();
+ calculateTrackRect();
+ calculateThumbLocation();
+
+ calculateTickRect();
+ calculateLabelRect();
+ }
+ }
+
+ /**
+ * Performs the opposite of installUI. Any properties or resources that need
+ * to be cleaned up will be done now. It will also uninstall any listeners
+ * it has. In addition, any properties of this UI will be nulled.
+ *
+ * @param c The {@link JComponent} that is having this UI uninstalled.
+ */
+ public void uninstallUI(JComponent c)
+ {
+ super.uninstallUI(c);
+
+ uninstallKeyboardActions(slider);
+ uninstallListeners(slider);
+
+ scrollTimer = null;
+
+ focusRect = null;
+ contentRect = null;
+ thumbRect = null;
+ trackRect = null;
+ tickRect = null;
+ labelRect = null;
+
+ focusInsets = null;
+ }
+
+ /**
+ * Initializes any default properties that this UI has from the defaults for
+ * the Basic look and feel.
+ *
+ * @param slider The {@link JSlider} that is having this UI installed.
+ */
+ protected void installDefaults(JSlider slider)
+ {
+ UIDefaults defaults = UIManager.getLookAndFeelDefaults();
+
+ slider.setForeground(defaults.getColor("Slider.foreground"));
+ slider.setBackground(defaults.getColor("Slider.background"));
+ shadowColor = defaults.getColor("Slider.shadow");
+ highlightColor = defaults.getColor("Slider.highlight");
+ focusColor = defaults.getColor("Slider.focus");
+ slider.setBorder(defaults.getBorder("Slider.border"));
+
+ thumbHeight = defaults.getInt("Slider.thumbHeight");
+ thumbWidth = defaults.getInt("Slider.thumbWidth");
+ tickHeight = defaults.getInt("Slider.tickHeight");
+
+ focusInsets = defaults.getInsets("Slider.focusInsets");
+ }
+
+ /**
+ * Creates a new {@link TrackListener}.
+ *
+ * @param slider The {@link JSlider} that this {@link TrackListener} is
+ * created for.
+ *
+ * @return A new {@link TrackListener}.
+ */
+ protected TrackListener createTrackListener(JSlider slider)
+ {
+ return new TrackListener();
+ }
+
+ /**
+ * Creates a new {@link ChangeListener}.
+ *
+ * @param slider The {@link JSlider} that this {@link ChangeListener} is
+ * created for.
+ *
+ * @return A new {@link ChangeListener}.
+ */
+ protected ChangeListener createChangeListener(JSlider slider)
+ {
+ return new ChangeHandler();
+ }
+
+ /**
+ * Creates a new {@link ComponentListener}.
+ *
+ * @param slider The {@link JSlider} that this {@link ComponentListener} is
+ * created for.
+ *
+ * @return A new {@link ComponentListener}.
+ */
+ protected ComponentListener createComponentListener(JSlider slider)
+ {
+ return new ComponentHandler();
+ }
+
+ /**
+ * Creates a new {@link FocusListener}.
+ *
+ * @param slider The {@link JSlider} that this {@link FocusListener} is
+ * created for.
+ *
+ * @return A new {@link FocusListener}.
+ */
+ protected FocusListener createFocusListener(JSlider slider)
+ {
+ return new FocusHandler();
+ }
+
+ /**
+ * Creates a new {@link ScrollListener}.
+ *
+ * @param slider The {@link JSlider} that this {@link ScrollListener} is
+ * created for.
+ *
+ * @return A new {@link ScrollListener}.
+ */
+ protected ScrollListener createScrollListener(JSlider slider)
+ {
+ return new ScrollListener();
+ }
+
+ /**
+ * Creates a new {@link PropertyChangeListener}.
+ *
+ * @param slider The {@link JSlider} that this {@link
+ * PropertyChangeListener} is created for.
+ *
+ * @return A new {@link PropertyChangeListener}.
+ */
+ protected PropertyChangeListener createPropertyChangeListener(JSlider slider)
+ {
+ return new PropertyChangeHandler();
+ }
+
+ /**
+ * Creates and registers all the listeners for this UI delegate. This
+ * includes creating the ScrollListener and registering it to the timer.
+ *
+ * @param slider The {@link JSlider} is having listeners installed.
+ */
+ protected void installListeners(JSlider slider)
+ {
+ propertyChangeListener = createPropertyChangeListener(slider);
+ componentListener = createComponentListener(slider);
+ trackListener = createTrackListener(slider);
+ focusListener = createFocusListener(slider);
+ changeListener = createChangeListener(slider);
+ scrollListener = createScrollListener(slider);
+
+ slider.addPropertyChangeListener(propertyChangeListener);
+ slider.addComponentListener(componentListener);
+ slider.addMouseListener(trackListener);
+ slider.addMouseMotionListener(trackListener);
+ slider.addFocusListener(focusListener);
+ slider.getModel().addChangeListener(changeListener);
+
+ scrollTimer.addActionListener(scrollListener);
+ }
+
+ /**
+ * Unregisters all the listeners that this UI delegate was using. In
+ * addition, it will also null any listeners that it was using.
+ *
+ * @param slider The {@link JSlider} that is having listeners removed.
+ */
+ protected void uninstallListeners(JSlider slider)
+ {
+ slider.removePropertyChangeListener(propertyChangeListener);
+ slider.removeComponentListener(componentListener);
+ slider.removeMouseListener(trackListener);
+ slider.removeMouseMotionListener(trackListener);
+ slider.removeFocusListener(focusListener);
+ slider.getModel().removeChangeListener(changeListener);
+
+ scrollTimer.removeActionListener(scrollListener);
+
+ propertyChangeListener = null;
+ componentListener = null;
+ trackListener = null;
+ focusListener = null;
+ changeListener = null;
+ scrollListener = null;
+ }
+
+ /**
+ * Installs any keyboard actions. The list of keys that need to be bound are
+ * listed in Basic look and feel's defaults.
+ *
+ * @param slider The {@link JSlider} that is having keyboard actions
+ * installed.
+ */
+ protected void installKeyboardActions(JSlider slider)
+ {
+ // FIXME: implement.
+ }
+
+ /**
+ * Uninstalls any keyboard actions. The list of keys used are listed in
+ * Basic look and feel's defaults.
+ *
+ * @param slider The {@link JSlider} that is having keyboard actions
+ * uninstalled.
+ */
+ protected void uninstallKeyboardActions(JSlider slider)
+ {
+ // FIXME: implement.
+ }
+
+ /* XXX: This is all after experimentation with SUN's implementation.
+
+ PreferredHorizontalSize seems to be 200x21.
+ PreferredVerticalSize seems to be 21x200.
+
+ MinimumHorizontalSize seems to be 36x21.
+ MinimumVerticalSize seems to be 21x36.
+
+ PreferredSize seems to be 200x63. Or Components.getBounds?
+
+ MinimumSize seems to be 36x63.
+
+ MaximumSize seems to be 32767x63.
+ */
+
+ /**
+ * This method returns the preferred size when the slider is
+ * horizontally oriented.
+ *
+ * @return The dimensions of the preferred horizontal size.
+ */
+ public Dimension getPreferredHorizontalSize()
+ {
+ Insets insets = slider.getInsets();
+
+ // The width should cover all the labels (which are usually the
+ // deciding factor of the width)
+ int width = getWidthOfWidestLabel() * (slider.getLabelTable() == null ?
+ 0 : slider.getLabelTable().size());
+
+ // If there are not enough labels.
+ // This number is pretty much arbitrary, but it looks nice.
+ if (width < 200)
+ width = 200;
+
+ // We can only draw inside of the focusRectangle, so we have to
+ // pad it with insets.
+ width += insets.left + insets.right + focusInsets.left +
+ focusInsets.right;
+
+ // Height is determined by the thumb, the ticks and the labels.
+ int height = thumbHeight;
+
+ if (slider.getPaintTicks() && slider.getMajorTickSpacing() > 0 ||
+ slider.getMinorTickSpacing() > 0)
+ height += tickHeight;
+
+ if (slider.getPaintLabels())
+ height += getHeightOfTallestLabel();
+
+ height += insets.top + insets.bottom + focusInsets.top +
+ focusInsets.bottom;
+
+ return new Dimension(width, height);
+ }
+
+ /**
+ * This method returns the preferred size when the slider is
+ * vertically oriented.
+ *
+ * @return The dimensions of the preferred vertical size.
+ */
+ public Dimension getPreferredVerticalSize()
+ {
+ Insets insets = slider.getInsets();
+
+ int height = getHeightOfTallestLabel() * (slider.getLabelTable() == null ?
+ 0 : slider.getLabelTable().size());
+
+ if (height < 200)
+ height = 200;
+
+ height += insets.top + insets.bottom + focusInsets.top +
+ focusInsets.bottom;
+
+ int width = thumbHeight;
+
+ if (slider.getPaintTicks() && slider.getMajorTickSpacing() > 0 ||
+ slider.getMinorTickSpacing() > 0)
+ width += tickHeight;
+
+ if (slider.getPaintLabels())
+ width += getWidthOfWidestLabel();
+
+ width += insets.left + insets.right + focusInsets.left +
+ focusInsets.right;
+
+ return new Dimension(width, height);
+ }
+
+ /**
+ * This method returns the minimum size when the slider is
+ * horizontally oriented.
+ *
+ * @return The dimensions of the minimum horizontal size.
+ */
+ public Dimension getMinimumHorizontalSize()
+ {
+ return getPreferredHorizontalSize();
+ }
+
+ /**
+ * This method returns the minimum size of the slider when it
+ * is vertically oriented.
+ *
+ * @return The dimensions of the minimum vertical size.
+ */
+ public Dimension getMinimumVerticalSize()
+ {
+ return getPreferredVerticalSize();
+ }
+
+ /**
+ * This method returns the preferred size of the component. If it returns
+ * null, then it is up to the Layout Manager to give the {@link JComponent}
+ * a size.
+ *
+ * @param c The {@link JComponent} to find the preferred size for.
+ *
+ * @return The dimensions of the preferred size.
+ */
+ public Dimension getPreferredSize(JComponent c)
+ {
+ if (slider.getOrientation() == JSlider.HORIZONTAL)
+ return getPreferredHorizontalSize();
+ else
+ return getPreferredVerticalSize();
+ }
+
+ /**
+ * This method returns the minimum size for this {@link JSlider} for this
+ * look and feel. If it returns null, then it is up to the Layout Manager
+ * to give the {@link JComponent} a size.
+ *
+ * @param c The {@link JComponent} to find the minimum size for.
+ *
+ * @return The dimensions of the minimum size.
+ */
+ public Dimension getMinimumSize(JComponent c)
+ {
+ if (slider.getOrientation() == JSlider.HORIZONTAL)
+ return getPreferredHorizontalSize();
+ else
+ return getPreferredVerticalSize();
+ }
+
+ /**
+ * This method returns the maximum size for this {@link JSlider} for this
+ * look and feel. If it returns null, then it is up to the Layout Manager
+ * to give the {@link JComponent} a size.
+ *
+ * @param c The {@link JComponent} to find a maximum size for.
+ *
+ * @return The dimensions of the maximum size.
+ */
+ public Dimension getMaximumSize(JComponent c)
+ {
+ if (slider.getOrientation() == JSlider.HORIZONTAL)
+ return getPreferredHorizontalSize();
+ else
+ return getPreferredVerticalSize();
+ }
+
+ /**
+ * This method calculates all the sizes of the rectangles by delegating
+ * to the helper methods calculateXXXRect.
+ */
+ protected void calculateGeometry()
+ {
+ calculateFocusRect();
+ calculateContentRect();
+ calculateThumbSize();
+ calculateTrackBuffer();
+ calculateTrackRect();
+ calculateTickRect();
+ calculateLabelRect();
+ calculateThumbLocation();
+ }
+
+ /**
+ * This method calculates the size and position of the focusRect. This
+ * method does not need to be called if the orientation changes.
+ */
+ protected void calculateFocusRect()
+ {
+ insetCache = slider.getInsets();
+ focusRect = SwingUtilities.calculateInnerArea(slider, focusRect);
+
+ if (focusRect.width < 0)
+ focusRect.width = 0;
+ if (focusRect.height < 0)
+ focusRect.height = 0;
+ }
+
+ /**
+ * This method calculates the size but not the position of the thumbRect. It
+ * must take into account the orientation of the slider.
+ */
+ protected void calculateThumbSize()
+ {
+ if (slider.getOrientation() == JSlider.HORIZONTAL)
+ {
+ if (thumbWidth > contentRect.width)
+ thumbRect.width = contentRect.width / 4;
+ else
+ thumbRect.width = thumbWidth;
+ if (thumbHeight > contentRect.height)
+ thumbRect.height = contentRect.height;
+ else
+ thumbRect.height = thumbHeight;
+ }
+ else
+ {
+ // The thumb gets flipped when inverted, so thumbWidth
+ // actually is the height and vice versa.
+ if (thumbWidth > contentRect.height)
+ thumbRect.height = contentRect.height / 4;
+ else
+ thumbRect.height = thumbWidth;
+ if (thumbHeight > contentRect.width)
+ thumbRect.width = contentRect.width;
+ else
+ thumbRect.width = thumbHeight;
+ }
+ }
+
+ /**
+ * This method calculates the size and position of the contentRect. This
+ * method does not need to be called if the orientation changes.
+ */
+ protected void calculateContentRect()
+ {
+ contentRect.x = focusRect.x + focusInsets.left;
+ contentRect.y = focusRect.y + focusInsets.top;
+ contentRect.width = focusRect.width - focusInsets.left - focusInsets.right;
+ contentRect.height = focusRect.height - focusInsets.top
+ - focusInsets.bottom;
+
+ if (contentRect.width < 0)
+ contentRect.width = 0;
+ if (contentRect.height < 0)
+ contentRect.height = 0;
+ }
+
+ /**
+ * Calculates the position of the thumbRect based on the current value of
+ * the slider. It must take into account the orientation of the slider.
+ */
+ protected void calculateThumbLocation()
+ {
+ int value = slider.getValue();
+
+ if (slider.getOrientation() == JSlider.HORIZONTAL)
+ {
+ thumbRect.x = xPositionForValue(value) - thumbRect.width / 2;
+ thumbRect.y = contentRect.y;
+ }
+ else
+ {
+ thumbRect.x = contentRect.x;
+ thumbRect.y = yPositionForValue(value) - thumbRect.height / 2;
+ }
+ }
+
+ /**
+ * Calculates the gap size between the left edge of the contentRect and the
+ * left edge of the trackRect.
+ */
+ protected void calculateTrackBuffer()
+ {
+ if (slider.getOrientation() == JSlider.HORIZONTAL)
+ trackBuffer = thumbRect.width;
+ else
+ trackBuffer = thumbRect.height;
+ }
+
+ /**
+ * This method returns the size of the thumbRect.
+ *
+ * @return The dimensions of the thumb.
+ */
+ protected Dimension getThumbSize()
+ {
+ // This is really just the bounds box for the thumb.
+ // The thumb will actually be pointed (like a rectangle + triangle at bottom)
+ return thumbRect.getSize();
+ }
+
+ /**
+ * Calculates the size and position of the trackRect. It must take into
+ * account the orientation of the slider.
+ */
+ protected void calculateTrackRect()
+ {
+ if (slider.getOrientation() == JSlider.HORIZONTAL)
+ {
+ trackRect.x = contentRect.x + trackBuffer;
+ trackRect.y = contentRect.y;
+ trackRect.width = contentRect.width - 2 * trackBuffer;
+ trackRect.height = thumbRect.height;
+ }
+ else
+ {
+ trackRect.x = contentRect.x;
+ trackRect.y = contentRect.y + trackBuffer;
+ trackRect.width = thumbRect.width;
+ trackRect.height = contentRect.height - 2 * trackBuffer;
+ }
+ }
+
+ /**
+ * This method returns the height of the tick area box if the slider is
+ * horizontal and the width of the tick area box is the slider is vertical.
+ * It not necessarily how long the ticks will be. If a gap between the edge
+ * of tick box and the actual tick is desired, then that will need to be
+ * handled in the tick painting methods.
+ *
+ * @return The height (or width if the slider is vertical) of the tick
+ * rectangle.
+ */
+ protected int getTickLength()
+ {
+ return tickHeight;
+ }
+
+ /**
+ * This method calculates the size and position of the tickRect. It must
+ * take into account the orientation of the slider.
+ */
+ protected void calculateTickRect()
+ {
+ if (slider.getOrientation() == JSlider.HORIZONTAL)
+ {
+ tickRect.x = trackRect.x;
+ tickRect.y = trackRect.y + trackRect.height;
+ tickRect.width = trackRect.width;
+ tickRect.height = getTickLength();
+
+ if (tickRect.y + tickRect.height > contentRect.y + contentRect.height)
+ tickRect.height = contentRect.y + contentRect.height - tickRect.y;
+ }
+ else
+ {
+ tickRect.x = trackRect.x + trackRect.width;
+ tickRect.y = trackRect.y;
+ tickRect.width = getTickLength();
+ tickRect.height = trackRect.height;
+
+ if (tickRect.x + tickRect.width > contentRect.x + contentRect.width)
+ tickRect.width = contentRect.x + contentRect.width - tickRect.x;
+ }
+ }
+
+ /**
+ * This method calculates the size and position of the labelRect. It must
+ * take into account the orientation of the slider.
+ */
+ protected void calculateLabelRect()
+ {
+ if (slider.getOrientation() == JSlider.HORIZONTAL)
+ {
+ labelRect.x = contentRect.x;
+ labelRect.y = tickRect.y + tickRect.height;
+ labelRect.width = contentRect.width;
+ labelRect.height = contentRect.height - labelRect.y;
+ }
+ else
+ {
+ labelRect.x = tickRect.x + tickRect.width;
+ labelRect.y = contentRect.y;
+ labelRect.width = contentRect.width - labelRect.x;
+ labelRect.height = contentRect.height;
+ }
+ }
+
+ /**
+ * This method returns the width of the widest label in the slider's label
+ * table.
+ *
+ * @return The width of the widest label or 0 if no label table exists.
+ */
+ protected int getWidthOfWidestLabel()
+ {
+ int widest = 0;
+ Component label;
+
+ if (slider.getLabelTable() == null)
+ return 0;
+
+ for (Enumeration list = slider.getLabelTable().elements();
+ list.hasMoreElements();)
+ {
+ Object comp = list.nextElement();
+ if (! (comp instanceof Component))
+ continue;
+ label = (Component) comp;
+ if (label.getWidth() > widest)
+ widest = label.getWidth();
+ }
+ return widest;
+ }
+
+ /**
+ * This method returns the height of the tallest label in the slider's label
+ * table.
+ *
+ * @return The height of the tallest label or 0 if no label table exists.
+ */
+ protected int getHeightOfTallestLabel()
+ {
+ int tallest = 0;
+ Component label;
+
+ if (slider.getLabelTable() == null)
+ return 0;
+
+ for (Enumeration list = slider.getLabelTable().elements();
+ list.hasMoreElements();)
+ {
+ Object comp = list.nextElement();
+ if (! (comp instanceof Component))
+ continue;
+ label = (Component) comp;
+ if (label.getHeight() > tallest)
+ tallest = label.getHeight();
+ }
+ return tallest;
+ }
+
+ /**
+ * This method returns the width of the label whose key has the highest
+ * value.
+ *
+ * @return The width of the high value label or 0 if no label table exists.
+ */
+ protected int getWidthOfHighValueLabel()
+ {
+ Component highValueLabel = getHighestValueLabel();
+ if (highValueLabel != null)
+ return highValueLabel.getWidth();
+ else
+ return 0;
+ }
+
+ /**
+ * This method returns the width of the label whose key has the lowest
+ * value.
+ *
+ * @return The width of the low value label or 0 if no label table exists.
+ */
+ protected int getWidthOfLowValueLabel()
+ {
+ Component lowValueLabel = getLowestValueLabel();
+ if (lowValueLabel != null)
+ return lowValueLabel.getWidth();
+ else
+ return 0;
+ }
+
+ /**
+ * This method returns the height of the label whose key has the highest
+ * value.
+ *
+ * @return The height of the high value label or 0 if no label table exists.
+ */
+ protected int getHeightOfHighValueLabel()
+ {
+ Component highValueLabel = getHighestValueLabel();
+ if (highValueLabel != null)
+ return highValueLabel.getHeight();
+ else
+ return 0;
+ }
+
+ /**
+ * This method returns the height of the label whose key has the lowest
+ * value.
+ *
+ * @return The height of the low value label or 0 if no label table exists.
+ */
+ protected int getHeightOfLowValueLabel()
+ {
+ Component lowValueLabel = getLowestValueLabel();
+ if (lowValueLabel != null)
+ return lowValueLabel.getHeight();
+ else
+ return 0;
+ }
+
+ /**
+ * This method returns whether the slider is to be drawn inverted.
+ *
+ * @return True is the slider is to be drawn inverted.
+ */
+ protected boolean drawInverted()
+ {
+ return ! (slider.getInverted() ^ leftToRightCache);
+ }
+
+ /**
+ * This method returns the label whose key has the lowest value.
+ *
+ * @return The low value label or null if no label table exists.
+ */
+ protected Component getLowestValueLabel()
+ {
+ Integer key = new Integer(Integer.MAX_VALUE);
+ Integer tmpKey;
+ Dictionary labelTable = slider.getLabelTable();
+
+ if (labelTable == null)
+ return null;
+
+ for (Enumeration list = labelTable.keys(); list.hasMoreElements();)
+ {
+ Object value = list.nextElement();
+ if (! (value instanceof Integer))
+ continue;
+ tmpKey = (Integer) value;
+ if (tmpKey.intValue() < key.intValue())
+ key = tmpKey;
+ }
+ Object comp = labelTable.get(key);
+ if (! (comp instanceof Component))
+ return null;
+ return (Component) comp;
+ }
+
+ /**
+ * This method returns the label whose key has the highest value.
+ *
+ * @return The high value label or null if no label table exists.
+ */
+ protected Component getHighestValueLabel()
+ {
+ Integer key = new Integer(Integer.MIN_VALUE);
+ Integer tmpKey;
+ Dictionary labelTable = slider.getLabelTable();
+
+ if (labelTable == null)
+ return null;
+
+ for (Enumeration list = labelTable.keys(); list.hasMoreElements();)
+ {
+ Object value = list.nextElement();
+ if (! (value instanceof Integer))
+ continue;
+ tmpKey = (Integer) value;
+ if (tmpKey.intValue() > key.intValue())
+ key = tmpKey;
+ }
+ Object comp = labelTable.get(key);
+ if (! (comp instanceof Component))
+ return null;
+ return (Component) comp;
+ }
+
+ /**
+ * This method is used to paint the {@link JSlider}. It delegates all its
+ * duties to the various paint methods like paintTicks(), paintTrack(),
+ * paintThumb(), etc.
+ *
+ * @param g The {@link Graphics} object to paint with.
+ * @param c The {@link JComponent} that is being painted.
+ */
+ public void paint(Graphics g, JComponent c)
+ {
+ // FIXME: Move this to propertyChangeEvent handler, when we get those.
+ leftToRightCache = slider.getComponentOrientation() != ComponentOrientation.RIGHT_TO_LEFT;
+ // FIXME: This next line is only here because the above line is here.
+ calculateThumbLocation();
+
+ if (slider.getPaintTrack())
+ paintTrack(g);
+ if (slider.getPaintTicks())
+ paintTicks(g);
+ if (slider.getPaintLabels())
+ paintLabels(g);
+
+ //FIXME: Paint focus.
+ paintThumb(g);
+ }
+
+ /**
+ * This method recalculates any rectangles that need to be recalculated
+ * after the insets of the component have changed.
+ */
+ protected void recalculateIfInsetsChanged()
+ {
+ // Examining a test program shows that either Sun calls private
+ // methods that we don't know about, or these don't do anything.
+ calculateFocusRect();
+
+ calculateContentRect();
+ calculateThumbSize();
+ calculateTrackBuffer();
+ calculateTrackRect();
+ calculateThumbLocation();
+
+ calculateTickRect();
+ calculateLabelRect();
+ }
+
+ /**
+ * This method recalculates any rectangles that need to be recalculated
+ * after the orientation of the slider changes.
+ */
+ protected void recalculateIfOrientationChanged()
+ {
+ // Examining a test program shows that either Sun calls private
+ // methods that we don't know about, or these don't do anything.
+ calculateThumbSize();
+ calculateTrackBuffer();
+ calculateTrackRect();
+ calculateThumbLocation();
+
+ calculateTickRect();
+ calculateLabelRect();
+ }
+
+ /**
+ * This method is called during a repaint if the slider has focus. It draws
+ * an outline of the focusRect using the color returned by
+ * getFocusColor().
+ *
+ * @param g The {@link Graphics} object to draw with.
+ */
+ public void paintFocus(Graphics g)
+ {
+ Color saved_color = g.getColor();
+
+ g.setColor(getFocusColor());
+
+ g.drawRect(focusRect.x, focusRect.y, focusRect.width, focusRect.height);
+
+ g.setColor(saved_color);
+ }
+
+ /**
+ * <p>
+ * This method is called during a repaint if the track is to be drawn. It
+ * draws a 3D rectangle to represent the track. The track is not the size
+ * of the trackRect. The top and left edges of the track should be outlined
+ * with the shadow color. The bottom and right edges should be outlined
+ * with the highlight color.
+ * </p>
+ * <pre>
+ * a---d
+ * | |
+ * | | a------------------------d
+ * | | | |
+ * | | b------------------------c
+ * | |
+ * | |
+ * b---c
+ * </pre>
+ *
+ * <p>
+ * The b-a-d path needs to be drawn with the shadow color and the b-c-d path
+ * needs to be drawn with the highlight color.
+ * </p>
+ *
+ * @param g The {@link Graphics} object to draw with.
+ */
+ public void paintTrack(Graphics g)
+ {
+ Color saved_color = g.getColor();
+ int width;
+ int height;
+
+ Point a = new Point(trackRect.x, trackRect.y);
+ Point b = new Point(a);
+ Point c = new Point(a);
+ Point d = new Point(a);
+
+ Polygon high;
+ Polygon shadow;
+
+ if (slider.getOrientation() == JSlider.HORIZONTAL)
+ {
+ width = trackRect.width;
+ height = (thumbRect.height / 4 == 0) ? 1 : thumbRect.height / 4;
+
+ a.translate(0, (trackRect.height / 2) - (height / 2));
+ b.translate(0, (trackRect.height / 2) + (height / 2));
+ c.translate(trackRect.width, (trackRect.height / 2) + (height / 2));
+ d.translate(trackRect.width, (trackRect.height / 2) - (height / 2));
+ }
+ else
+ {
+ width = (thumbRect.width / 4 == 0) ? 1 : thumbRect.width / 4;
+ height = trackRect.height;
+
+ a.translate((trackRect.width / 2) - (width / 2), 0);
+ b.translate((trackRect.width / 2) - (width / 2), trackRect.height);
+ c.translate((trackRect.width / 2) + (width / 2), trackRect.height);
+ d.translate((trackRect.width / 2) + (width / 2), 0);
+ }
+ high = new Polygon(new int[] { b.x, c.x, d.x },
+ new int[] { b.y, c.y, d.y }, 3);
+ shadow = new Polygon(new int[] { b.x, a.x, d.x },
+ new int[] { b.y, a.y, d.y }, 3);
+
+ g.setColor(getHighlightColor());
+ g.drawPolygon(high);
+ g.setColor(getShadowColor());
+ g.drawPolygon(shadow);
+
+ g.setColor(Color.GRAY);
+ g.fillRect(a.x + 1, a.y + 1, width - 2, height - 2);
+ g.setColor(saved_color);
+ }
+
+ /**
+ * This method is called during a repaint if the ticks are to be drawn. This
+ * method must still verify that the majorTickSpacing and minorTickSpacing
+ * are greater than zero before drawing the ticks.
+ *
+ * @param g The {@link Graphics} object to draw with.
+ */
+ public void paintTicks(Graphics g)
+ {
+ int max = slider.getMaximum();
+ int min = slider.getMinimum();
+ int majorSpace = slider.getMajorTickSpacing();
+ int minorSpace = slider.getMinorTickSpacing();
+
+ if (majorSpace > 0)
+ {
+ if (slider.getOrientation() == JSlider.HORIZONTAL)
+ {
+ double loc = tickRect.x;
+ double increment = (max == min) ? 0
+ : majorSpace * (double) tickRect.width / (max
+ - min);
+ if (drawInverted())
+ {
+ loc += tickRect.width;
+ increment *= -1;
+ }
+ for (int i = min; i <= max; i += majorSpace)
+ {
+ paintMajorTickForHorizSlider(g, tickRect, (int) loc);
+ loc += increment;
+ }
+ }
+ else
+ {
+ double loc = tickRect.height + tickRect.y;
+ double increment = (max == min) ? 0
+ : -majorSpace * (double) tickRect.height / (max
+ - min);
+ if (drawInverted())
+ {
+ loc = tickRect.y;
+ increment *= -1;
+ }
+ for (int i = min; i <= max; i += majorSpace)
+ {
+ paintMajorTickForVertSlider(g, tickRect, (int) loc);
+ loc += increment;
+ }
+ }
+ }
+ if (minorSpace > 0)
+ {
+ if (slider.getOrientation() == JSlider.HORIZONTAL)
+ {
+ double loc = tickRect.x;
+ double increment = (max == min) ? 0
+ : minorSpace * (double) tickRect.width / (max
+ - min);
+ if (drawInverted())
+ {
+ loc += tickRect.width;
+ increment *= -1;
+ }
+ for (int i = min; i <= max; i += minorSpace)
+ {
+ paintMinorTickForHorizSlider(g, tickRect, (int) loc);
+ loc += increment;
+ }
+ }
+ else
+ {
+ double loc = tickRect.height + tickRect.y;
+ double increment = (max == min) ? 0
+ : -minorSpace * (double) tickRect.height / (max
+ - min);
+ if (drawInverted())
+ {
+ loc = tickRect.y;
+ increment *= -1;
+ }
+ for (int i = min; i <= max; i += minorSpace)
+ {
+ paintMinorTickForVertSlider(g, tickRect, (int) loc);
+ loc += increment;
+ }
+ }
+ }
+ }
+
+ /* Minor ticks start at 1/4 of the height (or width) of the tickRect and extend
+ to 1/2 of the tickRect.
+
+ Major ticks start at 1/4 of the height and extend to 3/4.
+ */
+
+ /**
+ * This method paints a minor tick for a horizontal slider at the given x
+ * value. x represents the x coordinate to paint at.
+ *
+ * @param g The {@link Graphics} object to draw with.
+ * @param tickBounds The tickRect rectangle.
+ * @param x The x coordinate to draw the tick at.
+ */
+ protected void paintMinorTickForHorizSlider(Graphics g,
+ Rectangle tickBounds, int x)
+ {
+ int y = tickRect.y + tickRect.height / 4;
+
+ g.drawLine(x, y, x, y + tickRect.height / 4);
+ }
+
+ /**
+ * This method paints a major tick for a horizontal slider at the given x
+ * value. x represents the x coordinate to paint at.
+ *
+ * @param g The {@link Graphics} object to draw with.
+ * @param tickBounds The tickRect rectangle.
+ * @param x The x coordinate to draw the tick at.
+ */
+ protected void paintMajorTickForHorizSlider(Graphics g,
+ Rectangle tickBounds, int x)
+ {
+ int y = tickRect.y + tickRect.height / 4;
+
+ g.drawLine(x, y, x, y + tickRect.height / 2);
+ }
+
+ /**
+ * This method paints a minor tick for a vertical slider at the given y
+ * value. y represents the y coordinate to paint at.
+ *
+ * @param g The {@link Graphics} object to draw with.
+ * @param tickBounds The tickRect rectangle.
+ * @param y The y coordinate to draw the tick at.
+ */
+ protected void paintMinorTickForVertSlider(Graphics g, Rectangle tickBounds,
+ int y)
+ {
+ int x = tickRect.x + tickRect.width / 4;
+
+ g.drawLine(x, y, x + tickRect.width / 4, y);
+ }
+
+ /**
+ * This method paints a major tick for a vertical slider at the given y
+ * value. y represents the y coordinate to paint at.
+ *
+ * @param g The {@link Graphics} object to draw with.
+ * @param tickBounds The tickRect rectangle.
+ * @param y The y coordinate to draw the tick at.
+ */
+ protected void paintMajorTickForVertSlider(Graphics g, Rectangle tickBounds,
+ int y)
+ {
+ int x = tickRect.x + tickRect.width / 4;
+
+ g.drawLine(x, y, x + tickRect.width / 2, y);
+ }
+
+ /**
+ * This method paints all the labels from the slider's label table. This
+ * method must make sure that the label table is not null before painting
+ * the labels. Each entry in the label table is a (integer, component)
+ * pair. Every label is painted at the value of the integer.
+ *
+ * @param g The {@link Graphics} object to draw with.
+ */
+ public void paintLabels(Graphics g)
+ {
+ if (slider.getLabelTable() != null)
+ {
+ Dictionary table = slider.getLabelTable();
+ Integer tmpKey;
+ Object key;
+ Object element;
+ Component label;
+ if (slider.getOrientation() == JSlider.HORIZONTAL)
+ {
+ for (Enumeration list = table.keys(); list.hasMoreElements();)
+ {
+ key = list.nextElement();
+ if (! (key instanceof Integer))
+ continue;
+ tmpKey = (Integer) key;
+ element = table.get(tmpKey);
+ // We won't paint them if they're not
+ // JLabels so continue anyway
+ if (! (element instanceof JLabel))
+ continue;
+ label = (Component) element;
+ paintHorizontalLabel(g, tmpKey.intValue(), label);
+ }
+ }
+ else
+ {
+ for (Enumeration list = table.keys(); list.hasMoreElements();)
+ {
+ key = list.nextElement();
+ if (! (key instanceof Integer))
+ continue;
+ tmpKey = (Integer) key;
+ element = table.get(tmpKey);
+ // We won't paint them if they're not
+ // JLabels so continue anyway
+ if (! (element instanceof JLabel))
+ continue;
+ label = (Component) element;
+ paintVerticalLabel(g, tmpKey.intValue(), label);
+ }
+ }
+ }
+ }
+
+ /**
+ * This method paints the label on the horizontal slider at the value
+ * specified. The value is not a coordinate. It is a value within the range
+ * of the slider. If the value is not within the range of the slider, this
+ * method will do nothing. This method should not paint outside the
+ * boundaries of the labelRect.
+ *
+ * @param g The {@link Graphics} object to draw with.
+ * @param value The value to paint at.
+ * @param label The label to paint.
+ */
+ protected void paintHorizontalLabel(Graphics g, int value, Component label)
+ {
+ // This relies on clipping working properly or we'll end up
+ // painting all over the place. If our preferred size is ignored, then
+ // the labels may not fit inside the slider's bounds. Rather than mucking
+ // with font sizes and possible icon sizes, we'll set the bounds for
+ // the label and let it get clipped.
+
+ Dimension dim = label.getPreferredSize();
+ int w = (int) dim.getWidth();
+ int h = (int) dim.getHeight();
+
+ int max = slider.getMaximum();
+ int min = slider.getMinimum();
+
+ if (value > max || value < min)
+ return;
+
+ // value
+ // |
+ // ------------
+ // | |
+ // | |
+ // | |
+ // The label must move w/2 to the right to fit directly under the value.
+
+
+ int xpos = xPositionForValue(value) - w / 2;
+ int ypos = labelRect.y;
+
+ // We want to center the label around the xPositionForValue
+ // So we use xpos - w / 2. However, if value is min and the label
+ // is large, we run the risk of going out of bounds. So we bring it back
+ // to 0 if it becomes negative.
+ if (xpos < 0)
+ xpos = 0;
+
+ // If the label + starting x position is greater than
+ // the x space in the label rectangle, we reset it to the largest
+ // amount possible in the rectangle. This means ugliness.
+ if (xpos + w > labelRect.x + labelRect.width)
+ w = labelRect.x + labelRect.width - xpos;
+
+ // If the label is too tall. We reset it to the height of the label
+ // rectangle.
+ if (h > labelRect.height)
+ h = labelRect.height;
+
+ label.setBounds(xpos, ypos, w, h);
+ javax.swing.SwingUtilities.paintComponent(g, label, null, label.getBounds());
+ }
+
+ /**
+ * This method paints the label on the vertical slider at the value
+ * specified. The value is not a coordinate. It is a value within the range
+ * of the slider. If the value is not within the range of the slider, this
+ * method will do nothing. This method should not paint outside the
+ * boundaries of the labelRect.
+ *
+ * @param g The {@link Graphics} object to draw with.
+ * @param value The value to paint at.
+ * @param label The label to paint.
+ */
+ protected void paintVerticalLabel(Graphics g, int value, Component label)
+ {
+ Dimension dim = label.getPreferredSize();
+ int w = (int) dim.getWidth();
+ int h = (int) dim.getHeight();
+
+ int max = slider.getMaximum();
+ int min = slider.getMinimum();
+
+ if (value > max || value < min)
+ return;
+
+ int xpos = labelRect.x;
+ int ypos = yPositionForValue(value) - h / 2;
+
+ if (ypos < 0)
+ ypos = 0;
+
+ if (ypos + h > labelRect.y + labelRect.height)
+ h = labelRect.y + labelRect.height - ypos;
+
+ if (w > labelRect.width)
+ w = labelRect.width;
+
+ label.setBounds(xpos, ypos, w, h);
+ javax.swing.SwingUtilities.paintComponent(g, label, null, label.getBounds());
+ }
+
+ /**
+ * <p>
+ * This method paints a thumb. There are two types of thumb:
+ * </p>
+ * <pre>
+ * Vertical Horizontal
+ * a---b a-----b
+ * | | | \
+ * e c | c
+ * \ / | /
+ * d e-----d
+ * </pre>
+ *
+ * <p>
+ * In the case of vertical thumbs, we highlight the path b-a-e-d and shadow
+ * the path b-c-d. In the case of horizontal thumbs, we highlight the path
+ * c-b-a-e and shadow the path c-d-e. In both cases we fill the path
+ * a-b-c-d-e before shadows and highlights are drawn.
+ * </p>
+ *
+ * @param g The graphics object to paint with
+ */
+ public void paintThumb(Graphics g)
+ {
+ Color saved_color = g.getColor();
+
+ Polygon thumb = new Polygon();
+
+ Point a = new Point(thumbRect.x, thumbRect.y);
+ Point b = new Point(a);
+ Point c = new Point(a);
+ Point d = new Point(a);
+ Point e = new Point(a);
+
+ Polygon bright;
+ Polygon dark;
+ Polygon all;
+
+ // This will be in X-dimension if the slider is inverted and y if it isn't.
+ int turnPoint;
+
+ if (slider.getOrientation() == JSlider.HORIZONTAL)
+ {
+ turnPoint = thumbRect.height * 3 / 4;
+
+ b.translate(thumbRect.width, 0);
+ c.translate(thumbRect.width, turnPoint);
+ d.translate(thumbRect.width / 2, thumbRect.height);
+ e.translate(0, turnPoint);
+
+ bright = new Polygon(new int[] { b.x, a.x, e.x, d.x },
+ new int[] { b.y, a.y, e.y, d.y }, 4);
+
+ dark = new Polygon(new int[] { b.x, c.x, d.x },
+ new int[] { b.y, c.y, d.y }, 3);
+ all = new Polygon(new int[] { a.x + 1, b.x, c.x, d.x, e.x + 1 },
+ new int[] { a.y + 1, b.y + 1, c.y, d.y + 1, e.y }, 5);
+ }
+ else
+ {
+ turnPoint = thumbRect.width * 3 / 4;
+
+ b.translate(turnPoint, 0);
+ c.translate(thumbRect.width, thumbRect.height / 2);
+ d.translate(turnPoint, thumbRect.height);
+ e.translate(0, thumbRect.height);
+
+ bright = new Polygon(new int[] { c.x, b.x, a.x, e.x },
+ new int[] { c.y, b.y, a.y, e.y }, 4);
+
+ dark = new Polygon(new int[] { c.x, d.x, e.x + 1 },
+ new int[] { c.y, d.y, e.y }, 3);
+
+ all = new Polygon(new int[] { a.x + 1, b.x, c.x - 1, d.x, e.x + 1 },
+ new int[] { a.y + 1, b.y + 1, c.y, d.y, e.y }, 5);
+ }
+
+ g.setColor(Color.WHITE);
+ g.drawPolygon(bright);
+
+ g.setColor(Color.BLACK);
+ g.drawPolygon(dark);
+
+ g.setColor(Color.GRAY);
+ g.fillPolygon(all);
+
+ g.setColor(saved_color);
+ }
+
+ /**
+ * This method sets the position of the thumbRect.
+ *
+ * @param x The new x position.
+ * @param y The new y position.
+ */
+ public void setThumbLocation(int x, int y)
+ {
+ thumbRect.x = x;
+ thumbRect.y = y;
+ }
+
+ /**
+ * This method is used to move the thumb one block in the direction
+ * specified. If the slider snaps to ticks, this method is responsible for
+ * snapping it to a tick after the thumb has been moved.
+ *
+ * @param direction The direction to move in.
+ */
+ public void scrollByBlock(int direction)
+ {
+ // The direction is -1 for backwards and 1 for forwards.
+ int unit = direction * (slider.getMaximum() - slider.getMinimum()) / 10;
+
+ int moveTo = slider.getValue() + unit;
+
+ if (slider.getSnapToTicks())
+ moveTo = findClosestTick(moveTo);
+
+ slider.setValue(moveTo);
+ }
+
+ /**
+ * This method is used to move the thumb one unit in the direction
+ * specified. If the slider snaps to ticks, this method is responsible for
+ * snapping it to a tick after the thumb has been moved.
+ *
+ * @param direction The direction to move in.
+ */
+ public void scrollByUnit(int direction)
+ {
+ // The direction is -1 for backwards and 1 for forwards.
+ int moveTo = slider.getValue() + direction;
+
+ if (slider.getSnapToTicks())
+ moveTo = findClosestTick(moveTo);
+
+ slider.setValue(moveTo);
+ }
+
+ /**
+ * This method is called when there has been a click in the track and the
+ * thumb needs to be scrolled on regular intervals. This method is only
+ * responsible for starting the timer and not for stopping it.
+ *
+ * @param dir The direction to move in.
+ */
+ protected void scrollDueToClickInTrack(int dir)
+ {
+ scrollTimer.stop();
+
+ scrollListener.setDirection(dir);
+ scrollListener.setScrollByBlock(true);
+
+ scrollTimer.start();
+ }
+
+ /**
+ * This method returns the X coordinate for the value passed in.
+ *
+ * @param value The value to calculate an x coordinate for.
+ *
+ * @return The x coordinate for the value.
+ */
+ protected int xPositionForValue(int value)
+ {
+ int min = slider.getMinimum();
+ int max = slider.getMaximum();
+ int extent = slider.getExtent();
+ int len = trackRect.width;
+
+ int xPos = (max == min) ? 0 : (value - min) * len / (max - min);
+
+ if (! drawInverted())
+ xPos += trackRect.x;
+ else
+ {
+ xPos = trackRect.width - xPos;
+ xPos += trackRect.x;
+ }
+ return xPos;
+ }
+
+ /**
+ * This method returns the y coordinate for the value passed in.
+ *
+ * @param value The value to calculate a y coordinate for.
+ *
+ * @return The y coordinate for the value.
+ */
+ protected int yPositionForValue(int value)
+ {
+ int min = slider.getMinimum();
+ int max = slider.getMaximum();
+ int extent = slider.getExtent();
+ int len = trackRect.height;
+
+ int yPos = (max == min) ? 0 : (value - min) * len / (max - min);
+
+ if (! drawInverted())
+ {
+ yPos = trackRect.height - yPos;
+ yPos += trackRect.y;
+ }
+ else
+ yPos += trackRect.y;
+ return yPos;
+ }
+
+ /**
+ * This method returns the value in the slider's range given the y
+ * coordinate. If the value is out of range, it will return the closest
+ * legal value.
+ *
+ * @param yPos The y coordinate to calculate a value for.
+ *
+ * @return The value for the y coordinate.
+ */
+ public int valueForYPosition(int yPos)
+ {
+ int min = slider.getMinimum();
+ int max = slider.getMaximum();
+ int len = trackRect.height;
+
+ int value;
+
+ // If the length is 0, you shouldn't be able to even see where the slider is.
+ // This really shouldn't ever happen, but just in case, we'll return the middle.
+ if (len == 0)
+ return ((max - min) / 2);
+
+ if (! drawInverted())
+ value = ((len - (yPos - trackRect.y)) * (max - min) / len + min);
+ else
+ value = ((yPos - trackRect.y) * (max - min) / len + min);
+
+ // If this isn't a legal value, then we'll have to move to one now.
+ if (value > max)
+ value = max;
+ else if (value < min)
+ value = min;
+ return value;
+ }
+
+ /**
+ * This method returns the value in the slider's range given the x
+ * coordinate. If the value is out of range, it will return the closest
+ * legal value.
+ *
+ * @param xPos The x coordinate to calculate a value for.
+ *
+ * @return The value for the x coordinate.
+ */
+ public int valueForXPosition(int xPos)
+ {
+ int min = slider.getMinimum();
+ int max = slider.getMaximum();
+ int len = trackRect.width;
+
+ int value;
+
+ // If the length is 0, you shouldn't be able to even see where the slider is.
+ // This really shouldn't ever happen, but just in case, we'll return the middle.
+ if (len == 0)
+ return ((max - min) / 2);
+
+ if (! drawInverted())
+ value = ((xPos - trackRect.x) * (max - min) / len + min);
+ else
+ value = ((len - (xPos - trackRect.x)) * (max - min) / len + min);
+
+ // If this isn't a legal value, then we'll have to move to one now.
+ if (value > max)
+ value = max;
+ else if (value < min)
+ value = min;
+ return value;
+ }
+
+ /**
+ * This method finds the closest value that has a tick associated with it.
+ *
+ * @param value The value to search from.
+ *
+ * @return The closest value that has a tick associated with it.
+ */
+ private int findClosestTick(int value)
+ {
+ int min = slider.getMinimum();
+ int max = slider.getMaximum();
+ int majorSpace = slider.getMajorTickSpacing();
+ int minorSpace = slider.getMinorTickSpacing();
+
+ // The default value to return is value + minor or
+ // value + major.
+ // Initializing at min - value leaves us with a default
+ // return value of min, which always has tick marks
+ // (if ticks are painted).
+ int minor = min - value;
+ int major = min - value;
+
+ // If there are no major tick marks or minor tick marks
+ // e.g. snap is set to true but no ticks are set, then
+ // we can just return the value.
+ if (majorSpace <= 0 && minorSpace <= 0)
+ return value;
+
+ // First check the major ticks.
+ if (majorSpace > 0)
+ {
+ int lowerBound = (value - min) / majorSpace;
+ int majLower = majorSpace * lowerBound + min;
+ int majHigher = majorSpace * (lowerBound + 1) + min;
+
+ if (majHigher <= max && majHigher - value <= value - majLower)
+ major = majHigher - value;
+ else
+ major = majLower - value;
+ }
+
+ if (minorSpace > 0)
+ {
+ int lowerBound = value / minorSpace;
+ int minLower = minorSpace * lowerBound;
+ int minHigher = minorSpace * (lowerBound + 1);
+
+ if (minHigher <= max && minHigher - value <= value - minLower)
+ minor = minHigher - value;
+ else
+ minor = minLower - value;
+ }
+
+ // Give preference to minor ticks
+ if (Math.abs(minor) > Math.abs(major))
+ return value + major;
+ else
+ return value + minor;
+ }
+}
diff --git a/libjava/javax/swing/plaf/basic/BasicViewportUI.java b/libjava/javax/swing/plaf/basic/BasicViewportUI.java
index 963747c..62e51e1 100644
--- a/libjava/javax/swing/plaf/basic/BasicViewportUI.java
+++ b/libjava/javax/swing/plaf/basic/BasicViewportUI.java
@@ -38,36 +38,110 @@ 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.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.ViewportUI;
public class BasicViewportUI extends ViewportUI
{
- public static ComponentUI createUI(final JComponent c)
+ ChangeListener changeListener;
+ Image backingStoreImage;
+ int backingStoreWidth = -1;
+ int backingStoreHeight = -1;
+
+ class ChangeHandler implements ChangeListener
+ {
+ public void stateChanged(ChangeEvent event)
{
- return new BasicViewportUI();
+ JViewport v = (JViewport)event.source;
+ v.repaint();
}
+ }
-
- public void installUI(final JComponent c)
- {
- super.installUI(c);
- }
+ void installDefaults(JComponent c)
+ {
+ }
+
+ void uninstallDefaults(JComponent c)
+ {
+ }
+
+ void installListeners(JComponent c)
+ {
+ ((JViewport)c).addChangeListener(changeListener);
+ }
+
+ void uninstallListeners(JComponent c)
+ {
+ ((JViewport)c).removeChangeListener(changeListener);
+ }
+
+ public BasicViewportUI()
+ {
+ changeListener = new ChangeHandler();
+ }
+
+ public static ComponentUI createUI(JComponent c)
+ {
+ return new BasicViewportUI();
+ }
+
+ public void installUI(JComponent c)
+ {
+ super.installUI(c);
+ installListeners(c);
+ }
+
+ public void uninstallUI(JComponent c)
+ {
+ uninstallListeners(c);
+ }
- public Dimension getPreferredSize(JComponent c)
- {
- Dimension d = new Dimension(100,100);
- System.out.println("BasicViewportUI->preff->"+d);
- return d;
- }
+ public Dimension getPreferredSize(JComponent c)
+ {
+ // FIXME: integrate with Scrollable
+ Dimension d = new Dimension(100,100);
+ return d;
+ }
- public void paint(Graphics g, JComponent c)
- {
- System.out.println("BasicViewportUI->paint->"+c);
- }
+ public void paint(Graphics g, JComponent c)
+ {
+
+ JViewport v = (JViewport)c;
+ Component view = v.getView();
+
+ if (view == null)
+ return;
+
+ Point pos = v.getViewPosition();
+ Rectangle viewBounds = view.getBounds();
+
+ 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();
+ view.paint(g2);
+ g2 = null;
+ g.drawImage(backingStoreImage,
+ -pos.x, -pos.y,
+ (ImageObserver)null);
+ }
}