1 /* BasicScrollBarUI.java --
2 Copyright (C) 2004, 2005 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package javax
.swing
.plaf
.basic
;
41 import java
.awt
.Color
;
42 import java
.awt
.Component
;
43 import java
.awt
.Container
;
44 import java
.awt
.Dimension
;
45 import java
.awt
.Graphics
;
46 import java
.awt
.Insets
;
47 import java
.awt
.LayoutManager
;
48 import java
.awt
.Rectangle
;
49 import java
.awt
.event
.ActionEvent
;
50 import java
.awt
.event
.ActionListener
;
51 import java
.awt
.event
.MouseAdapter
;
52 import java
.awt
.event
.MouseEvent
;
53 import java
.awt
.event
.MouseMotionListener
;
54 import java
.beans
.PropertyChangeEvent
;
55 import java
.beans
.PropertyChangeListener
;
57 import javax
.swing
.BoundedRangeModel
;
58 import javax
.swing
.JButton
;
59 import javax
.swing
.JComponent
;
60 import javax
.swing
.JScrollBar
;
61 import javax
.swing
.LookAndFeel
;
62 import javax
.swing
.SwingConstants
;
63 import javax
.swing
.SwingUtilities
;
64 import javax
.swing
.Timer
;
65 import javax
.swing
.UIDefaults
;
66 import javax
.swing
.UIManager
;
67 import javax
.swing
.event
.ChangeEvent
;
68 import javax
.swing
.event
.ChangeListener
;
69 import javax
.swing
.plaf
.ComponentUI
;
70 import javax
.swing
.plaf
.ScrollBarUI
;
73 * The Basic Look and Feel UI delegate for JScrollBar.
75 public class BasicScrollBarUI
extends ScrollBarUI
implements LayoutManager
,
79 * A helper class that listens to the two JButtons on each end of the
82 protected class ArrowButtonListener
extends MouseAdapter
86 * Move the thumb in the direction specified by the button's arrow. If
87 * this button is held down, then it should keep moving the thumb.
89 * @param e The MouseEvent fired by the JButton.
91 public void mousePressed(MouseEvent e
)
94 scrollListener
.setScrollByBlock(false);
95 if (e
.getSource() == incrButton
)
96 scrollListener
.setDirection(POSITIVE_SCROLL
);
97 else if (e
.getSource() == decrButton
)
98 scrollListener
.setDirection(NEGATIVE_SCROLL
);
99 scrollTimer
.setDelay(100);
104 * Stops the thumb when the JButton is released.
106 * @param e The MouseEvent fired by the JButton.
108 public void mouseReleased(MouseEvent e
)
111 scrollTimer
.setDelay(300);
112 if (e
.getSource() == incrButton
)
113 scrollByUnit(POSITIVE_SCROLL
);
114 else if (e
.getSource() == decrButton
)
115 scrollByUnit(NEGATIVE_SCROLL
);
120 * A helper class that listens to the ScrollBar's model for ChangeEvents.
122 protected class ModelListener
implements ChangeListener
125 * Called when the model changes.
127 * @param e The ChangeEvent fired by the model.
129 public void stateChanged(ChangeEvent e
)
131 calculatePreferredSize();
138 * A helper class that listens to the ScrollBar's properties.
140 public class PropertyChangeHandler
implements PropertyChangeListener
143 * Called when one of the ScrollBar's properties change.
145 * @param e The PropertyChangeEvent fired by the ScrollBar.
147 public void propertyChange(PropertyChangeEvent e
)
149 if (e
.getPropertyName().equals("model"))
151 ((BoundedRangeModel
) e
.getOldValue()).removeChangeListener(modelListener
);
152 scrollbar
.getModel().addChangeListener(modelListener
);
155 else if (e
.getPropertyName().equals("orientation"))
157 uninstallListeners();
158 uninstallComponents();
164 else if (e
.getPropertyName().equals("enabled"))
166 Boolean b
= (Boolean
) e
.getNewValue();
167 if (incrButton
!= null)
168 incrButton
.setEnabled(b
.booleanValue());
169 if (decrButton
!= null)
170 decrButton
.setEnabled(b
.booleanValue());
176 * A helper class that listens for events from the timer that is used to
179 protected class ScrollListener
implements ActionListener
181 /** The direction the thumb moves in. */
182 private transient int direction
;
184 /** Whether movement will be in blocks. */
185 private transient boolean block
;
188 * Creates a new ScrollListener object. The default is scrolling
189 * positively with block movement.
191 public ScrollListener()
193 direction
= POSITIVE_SCROLL
;
198 * Creates a new ScrollListener object using the given direction and
201 * @param dir The direction to move in.
202 * @param block Whether movement will be in blocks.
204 public ScrollListener(int dir
, boolean block
)
211 * Sets the direction to scroll in.
213 * @param direction The direction to scroll in.
215 public void setDirection(int direction
)
217 this.direction
= direction
;
221 * Sets whether scrolling will be done in blocks.
223 * @param block Whether scrolling will be in blocks.
225 public void setScrollByBlock(boolean block
)
231 * Called every time the timer reaches its interval.
233 * @param e The ActionEvent fired by the timer.
235 public void actionPerformed(ActionEvent e
)
239 // Only need to check it if it's block scrolling
240 // We only block scroll if the click occurs
242 if (!trackListener
.shouldScroll(direction
))
244 trackHighlight
= NO_HIGHLIGHT
;
248 scrollByBlock(direction
);
251 scrollByUnit(direction
);
256 * Helper class that listens for movement on the track.
258 protected class TrackListener
extends MouseAdapter
259 implements MouseMotionListener
261 /** The current X coordinate of the mouse. */
262 protected int currentMouseX
;
264 /** The current Y coordinate of the mouse. */
265 protected int currentMouseY
;
268 * The offset between the current mouse cursor and the current value of
271 protected int offset
;
274 * This method is called when the mouse is being dragged.
276 * @param e The MouseEvent given.
278 public void mouseDragged(MouseEvent e
)
280 currentMouseX
= e
.getX();
281 currentMouseY
= e
.getY();
282 if (scrollbar
.getValueIsAdjusting())
285 if (scrollbar
.getOrientation() == SwingConstants
.HORIZONTAL
)
286 value
= valueForXPosition(currentMouseX
) - offset
;
288 value
= valueForYPosition(currentMouseY
) - offset
;
290 scrollbar
.setValue(value
);
295 * This method is called when the mouse is moved.
297 * @param e The MouseEvent given.
299 public void mouseMoved(MouseEvent e
)
301 // Not interested in where the mouse
302 // is unless it is being dragged.
306 * This method is called when the mouse is pressed. When it is pressed,
307 * the thumb should move in blocks towards the cursor.
309 * @param e The MouseEvent given.
311 public void mousePressed(MouseEvent e
)
313 currentMouseX
= e
.getX();
314 currentMouseY
= e
.getY();
317 if (scrollbar
.getOrientation() == SwingConstants
.HORIZONTAL
)
318 value
= valueForXPosition(currentMouseX
);
320 value
= valueForYPosition(currentMouseY
);
322 if (! thumbRect
.contains(e
.getPoint()))
325 scrollListener
.setScrollByBlock(true);
326 if (value
> scrollbar
.getValue())
328 trackHighlight
= INCREASE_HIGHLIGHT
;
329 scrollListener
.setDirection(POSITIVE_SCROLL
);
333 trackHighlight
= DECREASE_HIGHLIGHT
;
334 scrollListener
.setDirection(NEGATIVE_SCROLL
);
336 scrollTimer
.setDelay(100);
341 // We'd like to keep track of where the cursor
342 // is inside the thumb.
343 // This works because the scrollbar's value represents
344 // "lower" edge of the thumb. The value at which
345 // the cursor is at must be greater or equal
348 scrollListener
.setScrollByBlock(false);
349 scrollbar
.setValueIsAdjusting(true);
350 offset
= value
- scrollbar
.getValue();
356 * This method is called when the mouse is released. It should stop
357 * movement on the thumb
359 * @param e The MouseEvent given.
361 public void mouseReleased(MouseEvent e
)
364 scrollTimer
.setDelay(300);
365 currentMouseX
= e
.getX();
366 currentMouseY
= e
.getY();
368 if (shouldScroll(POSITIVE_SCROLL
))
369 scrollByBlock(POSITIVE_SCROLL
);
370 else if (shouldScroll(NEGATIVE_SCROLL
))
371 scrollByBlock(NEGATIVE_SCROLL
);
373 trackHighlight
= NO_HIGHLIGHT
;
374 scrollListener
.setScrollByBlock(false);
375 scrollbar
.setValueIsAdjusting(true);
380 * A helper method that decides whether we should keep scrolling in the
383 * @param direction The direction to check for.
385 * @return Whether the thumb should keep scrolling.
387 public boolean shouldScroll(int direction
)
390 if (scrollbar
.getOrientation() == HORIZONTAL
)
391 value
= valueForXPosition(currentMouseX
);
393 value
= valueForYPosition(currentMouseY
);
395 if (thumbRect
.contains(currentMouseX
, currentMouseY
))
398 if (direction
== POSITIVE_SCROLL
)
399 return (value
> scrollbar
.getValue());
401 return (value
< scrollbar
.getValue());
405 /** The listener that listens to the JButtons. */
406 protected ArrowButtonListener buttonListener
;
408 /** The listener that listens to the model. */
409 protected ModelListener modelListener
;
411 /** The listener that listens to the scrollbar for property changes. */
412 protected PropertyChangeListener propertyChangeListener
;
414 /** The listener that listens to the timer. */
415 protected ScrollListener scrollListener
;
417 /** The listener that listens for MouseEvents on the track. */
418 protected TrackListener trackListener
;
420 /** The JButton that decrements the scrollbar's value. */
421 protected JButton decrButton
;
423 /** The JButton that increments the scrollbar's value. */
424 protected JButton incrButton
;
426 /** The dimensions of the maximum thumb size. */
427 protected Dimension maximumThumbSize
;
429 /** The dimensions of the minimum thumb size. */
430 protected Dimension minimumThumbSize
;
432 /** The color of the thumb. */
433 protected Color thumbColor
;
435 /** The outer shadow of the thumb. */
436 protected Color thumbDarkShadowColor
;
438 /** The top and left edge color for the thumb. */
439 protected Color thumbHighlightColor
;
441 /** The outer light shadow for the thumb. */
442 protected Color thumbLightShadowColor
;
444 /** The color that is used when the mouse press occurs in the track. */
445 protected Color trackHighlightColor
;
447 /** The color of the track. */
448 protected Color trackColor
;
450 /** The size and position of the track. */
451 protected Rectangle trackRect
;
453 /** The size and position of the thumb. */
454 protected Rectangle thumbRect
;
456 /** Indicates that the decrease highlight should be painted. */
457 protected static final int DECREASE_HIGHLIGHT
= 1;
459 /** Indicates that the increase highlight should be painted. */
460 protected static final int INCREASE_HIGHLIGHT
= 2;
462 /** Indicates that no highlight should be painted. */
463 protected static final int NO_HIGHLIGHT
= 0;
465 /** Indicates that the scrolling direction is positive. */
466 private static final int POSITIVE_SCROLL
= 1;
468 /** Indicates that the scrolling direction is negative. */
469 private static final int NEGATIVE_SCROLL
= -1;
471 /** The cached preferred size for the scrollbar. */
472 private transient Dimension preferredSize
;
474 /** The current highlight status. */
475 protected int trackHighlight
;
477 /** FIXME: Use this for something (presumably mouseDragged) */
478 protected boolean isDragging
;
480 /** The timer used to move the thumb when the mouse is held. */
481 protected Timer scrollTimer
;
483 /** The scrollbar this UI is acting for. */
484 protected JScrollBar scrollbar
;
487 * This method adds a component to the layout.
489 * @param name The name to associate with the component that is added.
490 * @param child The Component to add.
492 public void addLayoutComponent(String name
, Component child
)
494 // You should not be adding stuff to this component.
495 // The contents are fixed.
499 * This method configures the scrollbar's colors. This can be done by
500 * looking up the standard colors from the Look and Feel defaults.
502 protected void configureScrollBarColors()
504 UIDefaults defaults
= UIManager
.getLookAndFeelDefaults();
506 trackColor
= defaults
.getColor("ScrollBar.track");
507 trackHighlightColor
= defaults
.getColor("ScrollBar.trackHighlight");
508 thumbColor
= defaults
.getColor("ScrollBar.thumb");
509 thumbHighlightColor
= defaults
.getColor("ScrollBar.thumbHighlight");
510 thumbDarkShadowColor
= defaults
.getColor("ScrollBar.thumbDarkShadow");
511 thumbLightShadowColor
= defaults
.getColor("ScrollBar.thumbShadow");
515 * This method creates an ArrowButtonListener.
517 * @return A new ArrowButtonListener.
519 protected ArrowButtonListener
createArrowButtonListener()
521 return new ArrowButtonListener();
525 * This method creates a new JButton with the appropriate icon for the
528 * @param orientation The orientation this JButton uses.
530 * @return The increase JButton.
532 protected JButton
createIncreaseButton(int orientation
)
534 return new BasicArrowButton(orientation
);
538 * This method creates a new JButton with the appropriate icon for the
541 * @param orientation The orientation this JButton uses.
543 * @return The decrease JButton.
545 protected JButton
createDecreaseButton(int orientation
)
547 return new BasicArrowButton(orientation
);
551 * This method creates a new ModelListener.
553 * @return A new ModelListener.
555 protected ModelListener
createModelListener()
557 return new ModelListener();
561 * This method creates a new PropertyChangeListener.
563 * @return A new PropertyChangeListener.
565 protected PropertyChangeListener
createPropertyChangeListener()
567 return new PropertyChangeHandler();
571 * This method creates a new ScrollListener.
573 * @return A new ScrollListener.
575 protected ScrollListener
createScrollListener()
577 return new ScrollListener();
581 * This method creates a new TrackListener.
583 * @return A new TrackListener.
585 protected TrackListener
createTrackListener()
587 return new TrackListener();
591 * This method returns a new BasicScrollBarUI.
593 * @param c The JComponent to create a UI for.
595 * @return A new BasicScrollBarUI.
597 public static ComponentUI
createUI(JComponent c
)
599 return new BasicScrollBarUI();
603 * This method returns the maximum size for this JComponent.
605 * @param c The JComponent to measure the maximum size for.
607 * @return The maximum size for the component.
609 public Dimension
getMaximumSize(JComponent c
)
611 return new Dimension(Integer
.MAX_VALUE
, Integer
.MAX_VALUE
);
615 * This method returns the maximum thumb size.
617 * @return The maximum thumb size.
619 protected Dimension
getMaximumThumbSize()
621 return maximumThumbSize
;
625 * This method returns the minimum size for this JComponent.
627 * @param c The JComponent to measure the minimum size for.
629 * @return The minimum size for the component.
631 public Dimension
getMinimumSize(JComponent c
)
633 return getPreferredSize(c
);
637 * This method returns the minimum thumb size.
639 * @return The minimum thumb size.
641 protected Dimension
getMinimumThumbSize()
643 return minimumThumbSize
;
647 * This method calculates the preferred size since calling
648 * getPreferredSize() returns a cached value.
649 * This is package-private to avoid an accessor method.
651 void calculatePreferredSize()
657 if (scrollbar
.getOrientation() == SwingConstants
.HORIZONTAL
)
659 width
+= incrButton
.getPreferredSize().getWidth();
660 width
+= decrButton
.getPreferredSize().getWidth();
662 width
+= (scrollbar
.getMaximum() - scrollbar
.getMinimum());
664 height
= Math
.max(incrButton
.getPreferredSize().height
,
665 decrButton
.getPreferredSize().height
);
666 height
= Math
.max(getMinimumThumbSize().height
, height
);
667 height
= Math
.min(getMaximumThumbSize().height
, height
);
671 height
+= incrButton
.getPreferredSize().getHeight();
672 height
+= decrButton
.getPreferredSize().getHeight();
674 height
+= (scrollbar
.getMaximum() - scrollbar
.getMinimum());
676 width
= Math
.max(incrButton
.getPreferredSize().width
,
677 decrButton
.getPreferredSize().width
);
678 width
= Math
.max(getMinimumThumbSize().width
, width
);
679 width
= Math
.min(getMaximumThumbSize().width
, width
);
682 Insets insets
= scrollbar
.getInsets();
684 height
+= insets
.top
+ insets
.bottom
;
685 width
+= insets
.left
+ insets
.right
;
687 preferredSize
= new Dimension(width
, height
);
691 * This method returns a cached value of the preferredSize. The only
692 * restrictions are: If the scrollbar is horizontal, the height should be
693 * the maximum of the height of the JButtons and the minimum width of the
694 * thumb. For vertical scrollbars, the calculation is similar (swap width
695 * for height and vice versa).
697 * @param c The JComponent to measure.
699 * @return The preferredSize.
701 public Dimension
getPreferredSize(JComponent c
)
703 calculatePreferredSize();
704 return preferredSize
;
708 * This method returns the thumb's bounds based on the current value of the
709 * scrollbar. This method updates the cached value and returns that.
711 * @return The thumb bounds.
713 protected Rectangle
getThumbBounds()
719 * This method calculates the bounds of the track. This method updates the
720 * cached value and returns it.
722 * @return The track's bounds.
724 protected Rectangle
getTrackBounds()
730 * This method installs any addition Components that are a part of or
731 * related to this scrollbar.
733 protected void installComponents()
735 if (incrButton
!= null)
736 scrollbar
.add(incrButton
);
737 if (decrButton
!= null)
738 scrollbar
.add(decrButton
);
742 * This method installs the defaults for the scrollbar specified by the
743 * Basic Look and Feel.
745 protected void installDefaults()
747 int orientation
= scrollbar
.getOrientation();
750 case (JScrollBar
.HORIZONTAL
):
751 incrButton
= createIncreaseButton(EAST
);
752 decrButton
= createDecreaseButton(WEST
);
755 incrButton
= createIncreaseButton(SOUTH
);
756 decrButton
= createDecreaseButton(NORTH
);
760 LookAndFeel
.installColors(scrollbar
, "ScrollBar.background",
761 "ScrollBar.foreground");
762 LookAndFeel
.installBorder(scrollbar
, "ScrollBar.border");
763 scrollbar
.setOpaque(true);
764 scrollbar
.setLayout(this);
766 thumbColor
= UIManager
.getColor("ScrollBar.thumb");
767 thumbDarkShadowColor
= UIManager
.getColor("ScrollBar.thumbDarkShadow");
768 thumbHighlightColor
= UIManager
.getColor("ScrollBar.thumbHighlight");
769 thumbLightShadowColor
= UIManager
.getColor("ScrollBar.thumbShadow");
771 maximumThumbSize
= UIManager
.getDimension("ScrollBar.maximumThumbSize");
772 minimumThumbSize
= UIManager
.getDimension("ScrollBar.minimumThumbSize");
776 * This method installs the keyboard actions for the scrollbar.
778 protected void installKeyboardActions()
784 * This method installs any listeners for the scrollbar. This method also
785 * installs listeners for things such as the JButtons and the timer.
787 protected void installListeners()
789 scrollListener
= createScrollListener();
790 trackListener
= createTrackListener();
791 buttonListener
= createArrowButtonListener();
792 modelListener
= createModelListener();
793 propertyChangeListener
= createPropertyChangeListener();
795 scrollbar
.addMouseMotionListener(trackListener
);
796 scrollbar
.addMouseListener(trackListener
);
798 incrButton
.addMouseListener(buttonListener
);
799 decrButton
.addMouseListener(buttonListener
);
801 scrollbar
.addPropertyChangeListener(propertyChangeListener
);
802 scrollbar
.getModel().addChangeListener(modelListener
);
804 scrollTimer
.addActionListener(scrollListener
);
808 * This method installs the UI for the component. This can include setting
809 * up listeners, defaults, and components. This also includes initializing
812 * @param c The JComponent to install.
814 public void installUI(JComponent c
)
817 if (c
instanceof JScrollBar
)
819 scrollbar
= (JScrollBar
) c
;
821 trackRect
= new Rectangle();
822 thumbRect
= new Rectangle();
824 scrollTimer
= new Timer(300, null);
828 configureScrollBarColors();
831 calculatePreferredSize();
836 * This method lays out the scrollbar.
838 * @param scrollbarContainer The Container to layout.
840 public void layoutContainer(Container scrollbarContainer
)
842 if (scrollbarContainer
instanceof JScrollBar
)
844 if (scrollbar
.getOrientation() == SwingConstants
.HORIZONTAL
)
845 layoutHScrollbar((JScrollBar
) scrollbarContainer
);
847 layoutVScrollbar((JScrollBar
) scrollbarContainer
);
852 * This method lays out the scrollbar horizontally.
854 * @param sb The JScrollBar to layout.
856 protected void layoutHScrollbar(JScrollBar sb
)
858 Rectangle vr
= new Rectangle();
859 SwingUtilities
.calculateInnerArea(scrollbar
, vr
);
861 Dimension incrDims
= incrButton
.getPreferredSize();
862 Dimension decrDims
= decrButton
.getPreferredSize();
864 // calculate and update the track bounds
865 SwingUtilities
.calculateInnerArea(scrollbar
, trackRect
);
866 trackRect
.width
-= incrDims
.getWidth();
867 trackRect
.width
-= decrDims
.getWidth();
868 trackRect
.x
+= decrDims
.getWidth();
872 decrButton
.setBounds(vr
.x
, vr
.y
, decrDims
.width
, trackRect
.height
);
873 incrButton
.setBounds(trackRect
.x
+ trackRect
.width
, vr
.y
, incrDims
.width
,
878 * This method lays out the scrollbar vertically.
880 * @param sb The JScrollBar to layout.
882 protected void layoutVScrollbar(JScrollBar sb
)
884 Rectangle vr
= new Rectangle();
885 SwingUtilities
.calculateInnerArea(scrollbar
, vr
);
887 Dimension incrDims
= incrButton
.getPreferredSize();
888 Dimension decrDims
= decrButton
.getPreferredSize();
891 SwingUtilities
.calculateInnerArea(scrollbar
, trackRect
);
892 trackRect
.height
-= incrDims
.getHeight();
893 trackRect
.height
-= decrDims
.getHeight();
894 trackRect
.y
+= decrDims
.getHeight();
898 decrButton
.setBounds(vr
.x
, vr
.y
, trackRect
.width
, decrDims
.height
);
899 incrButton
.setBounds(vr
.x
, trackRect
.y
+ trackRect
.height
,
900 trackRect
.width
, incrDims
.height
);
904 * Updates the thumb rect.
906 void updateThumbRect()
908 int max
= scrollbar
.getMaximum();
909 int min
= scrollbar
.getMinimum();
910 int value
= scrollbar
.getValue();
911 int extent
= scrollbar
.getVisibleAmount();
912 if (max
- extent
<= min
)
914 if (scrollbar
.getOrientation() == JScrollBar
.HORIZONTAL
)
916 thumbRect
.x
= trackRect
.x
;
917 thumbRect
.y
= trackRect
.y
;
918 thumbRect
.width
= getMinimumThumbSize().width
;
919 thumbRect
.height
= trackRect
.height
;
923 thumbRect
.x
= trackRect
.x
;
924 thumbRect
.y
= trackRect
.y
;
925 thumbRect
.width
= trackRect
.width
;
926 thumbRect
.height
= getMinimumThumbSize().height
;
931 if (scrollbar
.getOrientation() == JScrollBar
.HORIZONTAL
)
933 thumbRect
.x
= trackRect
.x
;
934 thumbRect
.width
= Math
.max(extent
* trackRect
.width
/ (max
- min
),
935 getMinimumThumbSize().width
);
936 int availableWidth
= trackRect
.width
- thumbRect
.width
;
937 thumbRect
.x
+= (value
- min
) * availableWidth
/ (max
- min
- extent
);
938 thumbRect
.y
= trackRect
.y
;
939 thumbRect
.height
= trackRect
.height
;
943 thumbRect
.x
= trackRect
.x
;
944 thumbRect
.height
= Math
.max(extent
* trackRect
.height
/ (max
- min
),
945 getMinimumThumbSize().height
);
946 int availableHeight
= trackRect
.height
- thumbRect
.height
;
947 thumbRect
.y
= trackRect
.y
948 + (value
- min
) * availableHeight
/ (max
- min
- extent
);
949 thumbRect
.width
= trackRect
.width
;
956 * This method returns the minimum size required for the layout.
958 * @param scrollbarContainer The Container that is laid out.
960 * @return The minimum size.
962 public Dimension
minimumLayoutSize(Container scrollbarContainer
)
964 return preferredLayoutSize(scrollbarContainer
);
968 * This method is called when the component is painted.
970 * @param g The Graphics object to paint with.
971 * @param c The JComponent to paint.
973 public void paint(Graphics g
, JComponent c
)
975 paintTrack(g
, c
, getTrackBounds());
976 paintThumb(g
, c
, getThumbBounds());
978 if (trackHighlight
== INCREASE_HIGHLIGHT
)
979 paintIncreaseHighlight(g
);
980 else if (trackHighlight
== DECREASE_HIGHLIGHT
)
981 paintDecreaseHighlight(g
);
985 * This method is called when repainting and the mouse is pressed in the
986 * track. It paints the track below the thumb with the trackHighlight
989 * @param g The Graphics object to paint with.
991 protected void paintDecreaseHighlight(Graphics g
)
993 Color saved
= g
.getColor();
995 g
.setColor(trackHighlightColor
);
996 if (scrollbar
.getOrientation() == HORIZONTAL
)
997 g
.fillRect(trackRect
.x
, trackRect
.y
, thumbRect
.x
- trackRect
.x
,
1000 g
.fillRect(trackRect
.x
, trackRect
.y
, trackRect
.width
,
1001 thumbRect
.y
- trackRect
.y
);
1006 * This method is called when repainting and the mouse is pressed in the
1007 * track. It paints the track above the thumb with the trackHighlight
1010 * @param g The Graphics objet to paint with.
1012 protected void paintIncreaseHighlight(Graphics g
)
1014 Color saved
= g
.getColor();
1016 g
.setColor(trackHighlightColor
);
1017 if (scrollbar
.getOrientation() == HORIZONTAL
)
1018 g
.fillRect(thumbRect
.x
+ thumbRect
.width
, trackRect
.y
,
1019 trackRect
.x
+ trackRect
.width
- thumbRect
.x
- thumbRect
.width
,
1022 g
.fillRect(trackRect
.x
, thumbRect
.y
+ thumbRect
.height
, trackRect
.width
,
1023 trackRect
.y
+ trackRect
.height
- thumbRect
.y
1024 - thumbRect
.height
);
1029 * This method paints the thumb.
1031 * @param g The Graphics object to paint with.
1032 * @param c The Component that is being painted.
1033 * @param thumbBounds The thumb bounds.
1035 protected void paintThumb(Graphics g
, JComponent c
, Rectangle thumbBounds
)
1037 g
.setColor(thumbColor
);
1038 g
.fillRect(thumbBounds
.x
, thumbBounds
.y
, thumbBounds
.width
,
1039 thumbBounds
.height
);
1041 BasicGraphicsUtils
.drawBezel(g
, thumbBounds
.x
, thumbBounds
.y
,
1042 thumbBounds
.width
, thumbBounds
.height
,
1043 false, false, thumbDarkShadowColor
,
1044 thumbDarkShadowColor
, thumbHighlightColor
,
1045 thumbHighlightColor
);
1049 * This method paints the track.
1051 * @param g The Graphics object to paint with.
1052 * @param c The JComponent being painted.
1053 * @param trackBounds The track's bounds.
1055 protected void paintTrack(Graphics g
, JComponent c
, Rectangle trackBounds
)
1057 Color saved
= g
.getColor();
1058 g
.setColor(trackColor
);
1059 g
.fill3DRect(trackBounds
.x
, trackBounds
.y
, trackBounds
.width
,
1060 trackBounds
.height
, false);
1065 * This method returns the preferred size for the layout.
1067 * @param scrollbarContainer The Container to find a size for.
1069 * @return The preferred size for the layout.
1071 public Dimension
preferredLayoutSize(Container scrollbarContainer
)
1073 if (scrollbarContainer
instanceof JComponent
)
1074 return getPreferredSize((JComponent
) scrollbarContainer
);
1080 * This method removes a child component from the layout.
1082 * @param child The child to remove.
1084 public void removeLayoutComponent(Component child
)
1086 // You should not be removing stuff from this component.
1090 * The method scrolls the thumb by a block in the direction specified.
1092 * @param direction The direction to scroll.
1094 protected void scrollByBlock(int direction
)
1096 scrollbar
.setValue(scrollbar
.getValue()
1097 + scrollbar
.getBlockIncrement(direction
));
1101 * The method scrolls the thumb by a unit in the direction specified.
1103 * @param direction The direction to scroll.
1105 protected void scrollByUnit(int direction
)
1107 scrollbar
.setValue(scrollbar
.getValue()
1108 + scrollbar
.getUnitIncrement(direction
));
1112 * This method sets the thumb's bounds.
1114 * @param x The X position of the thumb.
1115 * @param y The Y position of the thumb.
1116 * @param width The width of the thumb.
1117 * @param height The height of the thumb.
1119 protected void setThumbBounds(int x
, int y
, int width
, int height
)
1123 thumbRect
.width
= width
;
1124 thumbRect
.height
= height
;
1128 * This method uninstalls any components that are a part of or related to
1131 protected void uninstallComponents()
1133 if (incrButton
!= null)
1134 scrollbar
.remove(incrButton
);
1135 if (decrButton
!= null)
1136 scrollbar
.remove(decrButton
);
1140 * This method uninstalls any defaults that this scrollbar acquired from the
1141 * Basic Look and Feel defaults.
1143 protected void uninstallDefaults()
1145 scrollbar
.setForeground(null);
1146 scrollbar
.setBackground(null);
1147 LookAndFeel
.uninstallBorder(scrollbar
);
1153 * This method uninstalls any keyboard actions this scrollbar acquired
1156 protected void uninstallKeyboardActions()
1158 // FIXME: implement.
1162 * This method uninstalls any listeners that were registered during install.
1164 protected void uninstallListeners()
1166 if (scrollTimer
!= null)
1167 scrollTimer
.removeActionListener(scrollListener
);
1169 if (scrollbar
!= null)
1171 scrollbar
.getModel().removeChangeListener(modelListener
);
1172 scrollbar
.removePropertyChangeListener(propertyChangeListener
);
1173 scrollbar
.removeMouseListener(trackListener
);
1174 scrollbar
.removeMouseMotionListener(trackListener
);
1177 if (decrButton
!= null)
1178 decrButton
.removeMouseListener(buttonListener
);
1179 if (incrButton
!= null)
1180 incrButton
.removeMouseListener(buttonListener
);
1182 propertyChangeListener
= null;
1183 modelListener
= null;
1184 buttonListener
= null;
1185 trackListener
= null;
1186 scrollListener
= null;
1190 * This method uninstalls the UI. This includes removing any defaults,
1191 * listeners, and components that this UI may have initialized. It also
1192 * nulls any instance data.
1194 * @param c The Component to uninstall for.
1196 public void uninstallUI(JComponent c
)
1198 uninstallListeners();
1199 uninstallDefaults();
1200 uninstallComponents();
1208 trackHighlightColor
= null;
1210 thumbHighlightColor
= null;
1211 thumbDarkShadowColor
= null;
1212 thumbLightShadowColor
= null;
1218 * This method returns the value in the scrollbar's range given the y
1219 * coordinate. If the value is out of range, it will return the closest
1221 * This is package-private to avoid an accessor method.
1223 * @param yPos The y coordinate to calculate a value for.
1225 * @return The value for the y coordinate.
1227 int valueForYPosition(int yPos
)
1229 int min
= scrollbar
.getMinimum();
1230 int max
= scrollbar
.getMaximum();
1231 int len
= trackRect
.height
;
1235 // If the length is 0, you shouldn't be able to even see where the thumb is.
1236 // This really shouldn't ever happen, but just in case, we'll return the middle.
1238 return ((max
- min
) / 2);
1240 value
= ((yPos
- trackRect
.y
) * (max
- min
) / len
+ min
);
1242 // If this isn't a legal value, then we'll have to move to one now.
1245 else if (value
< min
)
1251 * This method returns the value in the scrollbar's range given the x
1252 * coordinate. If the value is out of range, it will return the closest
1254 * This is package-private to avoid an accessor method.
1256 * @param xPos The x coordinate to calculate a value for.
1258 * @return The value for the x coordinate.
1260 int valueForXPosition(int xPos
)
1262 int min
= scrollbar
.getMinimum();
1263 int max
= scrollbar
.getMaximum();
1264 int len
= trackRect
.width
;
1268 // If the length is 0, you shouldn't be able to even see where the slider is.
1269 // This really shouldn't ever happen, but just in case, we'll return the middle.
1271 return ((max
- min
) / 2);
1273 value
= ((xPos
- trackRect
.x
) * (max
- min
) / len
+ min
);
1275 // If this isn't a legal value, then we'll have to move to one now.
1278 else if (value
< min
)