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.SwingConstants;
62 import javax.swing.SwingUtilities;
63 import javax.swing.Timer;
64 import javax.swing.UIDefaults;
65 import javax.swing.UIManager;
66 import javax.swing.event.ChangeEvent;
67 import javax.swing.event.ChangeListener;
68 import javax.swing.plaf.ComponentUI;
69 import javax.swing.plaf.ScrollBarUI;
72 * The Basic Look and Feel UI delegate for JScrollBar.
74 public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
78 * A helper class that listens to the two JButtons on each end of the
81 protected class ArrowButtonListener extends MouseAdapter
84 * Move the thumb in the direction specified by the button's arrow. If
85 * this button is held down, then it should keep moving the thumb.
87 * @param e The MouseEvent fired by the JButton.
89 public void mousePressed(MouseEvent e)
92 scrollListener.setScrollByBlock(false);
93 if (e.getSource() == incrButton)
94 scrollListener.setDirection(POSITIVE_SCROLL);
96 scrollListener.setDirection(NEGATIVE_SCROLL);
101 * Stops the thumb when the JButton is released.
103 * @param e The MouseEvent fired by the JButton.
105 public void mouseReleased(MouseEvent e)
112 * A helper class that listens to the ScrollBar's model for ChangeEvents.
114 protected class ModelListener implements ChangeListener
117 * Called when the model changes.
119 * @param e The ChangeEvent fired by the model.
121 public void stateChanged(ChangeEvent e)
123 // System.err.println(this + ".stateChanged()");
124 calculatePreferredSize();
131 * A helper class that listens to the ScrollBar's properties.
133 public class PropertyChangeHandler implements PropertyChangeListener
136 * Called when one of the ScrollBar's properties change.
138 * @param e The PropertyChangeEvent fired by the ScrollBar.
140 public void propertyChange(PropertyChangeEvent e)
142 if (e.getPropertyName().equals("model"))
144 ((BoundedRangeModel) e.getOldValue()).removeChangeListener(modelListener);
145 scrollbar.getModel().addChangeListener(modelListener);
148 else if (e.getPropertyName().equals("orientation"))
150 incrButton.removeMouseListener(buttonListener);
151 decrButton.removeMouseListener(buttonListener);
152 int orientation = scrollbar.getOrientation();
155 case (JScrollBar.HORIZONTAL):
156 incrButton = createIncreaseButton(EAST);
157 decrButton = createDecreaseButton(WEST);
160 incrButton = createIncreaseButton(SOUTH);
161 decrButton = createDecreaseButton(NORTH);
164 incrButton.addMouseListener(buttonListener);
165 decrButton.addMouseListener(buttonListener);
166 calculatePreferredSize();
173 * A helper class that listens for events from the timer that is used to
176 protected class ScrollListener implements ActionListener
178 /** The direction the thumb moves in. */
179 private transient int direction;
181 /** Whether movement will be in blocks. */
182 private transient boolean block;
185 * Creates a new ScrollListener object. The default is scrolling
186 * positively with block movement.
188 public ScrollListener()
190 direction = POSITIVE_SCROLL;
195 * Creates a new ScrollListener object using the given direction and
198 * @param dir The direction to move in.
199 * @param block Whether movement will be in blocks.
201 public ScrollListener(int dir, boolean block)
208 * Sets the direction to scroll in.
210 * @param direction The direction to scroll in.
212 public void setDirection(int direction)
214 this.direction = direction;
218 * Sets whether scrolling will be done in blocks.
220 * @param block Whether scrolling will be in blocks.
222 public void setScrollByBlock(boolean block)
228 * Called every time the timer reaches its interval.
230 * @param e The ActionEvent fired by the timer.
232 public void actionPerformed(ActionEvent e)
236 // Only need to check it if it's block scrolling
237 // We only block scroll if the click occurs
239 if (! trackListener.shouldScroll(direction))
241 trackHighlight = NO_HIGHLIGHT;
245 scrollByBlock(direction);
248 scrollByUnit(direction);
253 * Helper class that listens for movement on the track.
255 protected class TrackListener extends MouseAdapter
256 implements MouseMotionListener
258 /** The current X coordinate of the mouse. */
259 protected int currentMouseX;
261 /** The current Y coordinate of the mouse. */
262 protected int currentMouseY;
265 * The offset between the current mouse cursor and the current value of
268 protected int offset;
271 * This method is called when the mouse is being dragged.
273 * @param e The MouseEvent given.
275 public void mouseDragged(MouseEvent e)
277 currentMouseX = e.getX();
278 currentMouseY = e.getY();
279 if (scrollbar.getValueIsAdjusting())
282 if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL)
283 value = valueForXPosition(currentMouseX) - offset;
285 value = valueForYPosition(currentMouseY) - offset;
287 scrollbar.setValue(value);
292 * This method is called when the mouse is moved.
294 * @param e The MouseEvent given.
296 public void mouseMoved(MouseEvent e)
298 // Not interested in where the mouse
299 // is unless it is being dragged.
303 * This method is called when the mouse is pressed. When it is pressed,
304 * the thumb should move in blocks towards the cursor.
306 * @param e The MouseEvent given.
308 public void mousePressed(MouseEvent e)
310 currentMouseX = e.getX();
311 currentMouseY = e.getY();
314 if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL)
315 value = valueForXPosition(currentMouseX);
317 value = valueForYPosition(currentMouseY);
319 if (value == scrollbar.getValue())
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);
340 // We'd like to keep track of where the cursor
341 // is inside the thumb.
342 // This works because the scrollbar's value represents
343 // "lower" edge of the thumb. The value at which
344 // the cursor is at must be greater or equal
346 scrollbar.setValueIsAdjusting(true);
347 offset = value - scrollbar.getValue();
353 * This method is called when the mouse is released. It should stop
354 * movement on the thumb
356 * @param e The MouseEvent given.
358 public void mouseReleased(MouseEvent e)
360 trackHighlight = NO_HIGHLIGHT;
363 if (scrollbar.getValueIsAdjusting())
364 scrollbar.setValueIsAdjusting(false);
369 * A helper method that decides whether we should keep scrolling in the
372 * @param direction The direction to check for.
374 * @return Whether the thumb should keep scrolling.
376 public boolean shouldScroll(int direction)
379 if (scrollbar.getOrientation() == HORIZONTAL)
380 value = valueForXPosition(currentMouseX);
382 value = valueForYPosition(currentMouseY);
384 if (direction == POSITIVE_SCROLL)
385 return (value > scrollbar.getValue());
387 return (value < scrollbar.getValue());
391 /** The listener that listens to the JButtons. */
392 protected ArrowButtonListener buttonListener;
394 /** The listener that listens to the model. */
395 protected ModelListener modelListener;
397 /** The listener that listens to the scrollbar for property changes. */
398 protected PropertyChangeListener propertyChangeListener;
400 /** The listener that listens to the timer. */
401 protected ScrollListener scrollListener;
403 /** The listener that listens for MouseEvents on the track. */
404 protected TrackListener trackListener;
406 /** The JButton that decrements the scrollbar's value. */
407 protected JButton decrButton;
409 /** The JButton that increments the scrollbar's value. */
410 protected JButton incrButton;
412 /** The dimensions of the maximum thumb size. */
413 protected Dimension maximumThumbSize;
415 /** The dimensions of the minimum thumb size. */
416 protected Dimension minimumThumbSize;
418 /** The color of the thumb. */
419 protected Color thumbColor;
421 /** The outer shadow of the thumb. */
422 protected Color thumbDarkShadowColor;
424 /** The top and left edge color for the thumb. */
425 protected Color thumbHighlightColor;
427 /** The outer light shadow for the thumb. */
428 protected Color thumbLightShadowColor;
430 /** The color that is used when the mouse press occurs in the track. */
431 protected Color trackHighlightColor;
433 /** The color of the track. */
434 protected Color trackColor;
436 /** The size and position of the track. */
437 protected Rectangle trackRect;
439 /** The size and position of the thumb. */
440 protected Rectangle thumbRect;
442 /** Indicates that the decrease highlight should be painted. */
443 protected static final int DECREASE_HIGHLIGHT = 1;
445 /** Indicates that the increase highlight should be painted. */
446 protected static final int INCREASE_HIGHLIGHT = 2;
448 /** Indicates that no highlight should be painted. */
449 protected static final int NO_HIGHLIGHT = 0;
451 /** Indicates that the scrolling direction is positive. */
452 private static final int POSITIVE_SCROLL = 1;
454 /** Indicates that the scrolling direction is negative. */
455 private static final int NEGATIVE_SCROLL = -1;
457 /** The cached preferred size for the scrollbar. */
458 private transient Dimension preferredSize;
460 /** The current highlight status. */
461 protected int trackHighlight;
463 /** FIXME: Use this for something (presumably mouseDragged) */
464 protected boolean isDragging;
466 /** The timer used to move the thumb when the mouse is held. */
467 protected Timer scrollTimer;
469 /** The scrollbar this UI is acting for. */
470 protected JScrollBar scrollbar;
473 * This method adds a component to the layout.
475 * @param name The name to associate with the component that is added.
476 * @param child The Component to add.
478 public void addLayoutComponent(String name, Component child)
480 // You should not be adding stuff to this component.
481 // The contents are fixed.
485 * This method configures the scrollbar's colors. This can be done by
486 * looking up the standard colors from the Look and Feel defaults.
488 protected void configureScrollBarColors()
490 UIDefaults defaults = UIManager.getLookAndFeelDefaults();
492 trackColor = defaults.getColor("ScrollBar.track");
493 trackHighlightColor = defaults.getColor("ScrollBar.trackHighlight");
494 thumbColor = defaults.getColor("ScrollBar.thumb");
495 thumbHighlightColor = defaults.getColor("ScrollBar.thumbHighlight");
496 thumbDarkShadowColor = defaults.getColor("ScrollBar.thumbDarkShadow");
497 thumbLightShadowColor = defaults.getColor("ScrollBar.thumbShadow");
501 * This method creates an ArrowButtonListener.
503 * @return A new ArrowButtonListener.
505 protected ArrowButtonListener createArrowButtonListener()
507 return new ArrowButtonListener();
511 * This method creates a new JButton with the appropriate icon for the
514 * @param orientation The orientation this JButton uses.
516 * @return The increase JButton.
518 protected JButton createIncreaseButton(int orientation)
520 if (incrButton == null)
521 incrButton = new BasicArrowButton(orientation);
523 ((BasicArrowButton) incrButton).setDirection(orientation);
528 * This method creates a new JButton with the appropriate icon for the
531 * @param orientation The orientation this JButton uses.
533 * @return The decrease JButton.
535 protected JButton createDecreaseButton(int orientation)
537 if (decrButton == null)
538 decrButton = new BasicArrowButton(orientation);
540 ((BasicArrowButton) decrButton).setDirection(orientation);
545 * This method creates a new ModelListener.
547 * @return A new ModelListener.
549 protected ModelListener createModelListener()
551 return new ModelListener();
555 * This method creates a new PropertyChangeListener.
557 * @return A new PropertyChangeListener.
559 protected PropertyChangeListener createPropertyChangeListener()
561 return new PropertyChangeHandler();
565 * This method creates a new ScrollListener.
567 * @return A new ScrollListener.
569 protected ScrollListener createScrollListener()
571 return new ScrollListener();
575 * This method creates a new TrackListener.
577 * @return A new TrackListener.
579 protected TrackListener createTrackListener()
581 return new TrackListener();
585 * This method returns a new BasicScrollBarUI.
587 * @param c The JComponent to create a UI for.
589 * @return A new BasicScrollBarUI.
591 public static ComponentUI createUI(JComponent c)
593 return new BasicScrollBarUI();
597 * This method returns the maximum size for this JComponent.
599 * @param c The JComponent to measure the maximum size for.
601 * @return The maximum size for the component.
603 public Dimension getMaximumSize(JComponent c)
605 return getPreferredSize(c);
609 * This method returns the maximum thumb size.
611 * @return The maximum thumb size.
613 protected Dimension getMaximumThumbSize()
615 return maximumThumbSize;
619 * This method returns the minimum size for this JComponent.
621 * @param c The JComponent to measure the minimum size for.
623 * @return The minimum size for the component.
625 public Dimension getMinimumSize(JComponent c)
627 return getPreferredSize(c);
631 * This method returns the minimum thumb size.
633 * @return The minimum thumb size.
635 protected Dimension getMinimumThumbSize()
637 return minimumThumbSize;
641 * This method calculates the preferred size since calling
642 * getPreferredSize() returns a cached value.
643 * This is package-private to avoid an accessor method.
645 void calculatePreferredSize()
647 // System.err.println(this + ".calculatePreferredSize()");
652 if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL)
654 width += incrButton.getPreferredSize().getWidth();
655 width += decrButton.getPreferredSize().getWidth();
657 width += (scrollbar.getMaximum() - scrollbar.getMinimum());
659 height = Math.max(incrButton.getPreferredSize().height,
660 decrButton.getPreferredSize().height);
661 height = Math.max(getMinimumThumbSize().height, height);
662 height = Math.min(getMaximumThumbSize().height, height);
666 height += incrButton.getPreferredSize().getHeight();
667 height += decrButton.getPreferredSize().getHeight();
669 height += (scrollbar.getMaximum() - scrollbar.getMinimum());
671 width = Math.max(incrButton.getPreferredSize().width,
672 decrButton.getPreferredSize().width);
673 width = Math.max(getMinimumThumbSize().width, width);
674 width = Math.min(getMaximumThumbSize().width, width);
677 Insets insets = scrollbar.getInsets();
679 height += insets.top + insets.bottom;
680 width += insets.left + insets.right;
682 preferredSize = new Dimension(width, height);
686 * This method returns a cached value of the preferredSize. The only
687 * restrictions are: If the scrollbar is horizontal, the height should be
688 * the maximum of the height of the JButtons and the minimum width of the
689 * thumb. For vertical scrollbars, the calculation is similar (swap width
690 * for height and vice versa).
692 * @param c The JComponent to measure.
694 * @return The preferredSize.
696 public Dimension getPreferredSize(JComponent c)
698 calculatePreferredSize();
699 return preferredSize;
703 * This method returns the thumb's bounds based on the current value of the
704 * scrollbar. This method updates the cached value and returns that.
706 * @return The thumb bounds.
708 protected Rectangle getThumbBounds()
710 int max = scrollbar.getMaximum();
711 int min = scrollbar.getMinimum();
712 int value = scrollbar.getValue();
713 int extent = scrollbar.getVisibleAmount();
715 // System.err.println(this + ".getThumbBounds()");
718 thumbRect.x = trackRect.x;
719 thumbRect.y = trackRect.y;
720 if (scrollbar.getOrientation() == HORIZONTAL)
722 thumbRect.width = getMinimumThumbSize().width;
723 thumbRect.height = trackRect.height;
727 thumbRect.width = trackRect.width;
728 thumbRect.height = getMinimumThumbSize().height;
733 if (scrollbar.getOrientation() == HORIZONTAL)
735 thumbRect.x = trackRect.x;
736 thumbRect.x += (value - min) * trackRect.width / (max - min);
737 thumbRect.y = trackRect.y;
739 thumbRect.width = Math.max(extent * trackRect.width / (max - min),
740 getMinimumThumbSize().width);
741 thumbRect.height = trackRect.height;
745 thumbRect.x = trackRect.x;
746 thumbRect.y = trackRect.y + value * trackRect.height / (max - min);
748 thumbRect.width = trackRect.width;
749 thumbRect.height = Math.max(extent * trackRect.height / (max - min),
750 getMinimumThumbSize().height);
756 * This method calculates the bounds of the track. This method updates the
757 * cached value and returns it.
759 * @return The track's bounds.
761 protected Rectangle getTrackBounds()
763 SwingUtilities.calculateInnerArea(scrollbar, trackRect);
765 if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL)
767 trackRect.width -= incrButton.getPreferredSize().getWidth();
768 trackRect.width -= decrButton.getPreferredSize().getWidth();
770 trackRect.x += decrButton.getPreferredSize().getWidth();
774 trackRect.height -= incrButton.getPreferredSize().getHeight();
775 trackRect.height -= decrButton.getPreferredSize().getHeight();
777 trackRect.y += incrButton.getPreferredSize().getHeight();
783 * This method installs any addition Components that are a part of or
784 * related to this scrollbar.
786 protected void installComponents()
788 int orientation = scrollbar.getOrientation();
791 case (JScrollBar.HORIZONTAL):
792 incrButton = createIncreaseButton(EAST);
793 decrButton = createDecreaseButton(WEST);
796 incrButton = createIncreaseButton(SOUTH);
797 decrButton = createDecreaseButton(NORTH);
800 scrollbar.add(incrButton);
801 scrollbar.add(decrButton);
805 * This method installs the defaults for the scrollbar specified by the
806 * Basic Look and Feel.
808 protected void installDefaults()
810 UIDefaults defaults = UIManager.getLookAndFeelDefaults();
812 scrollbar.setForeground(defaults.getColor("ScrollBar.foreground"));
813 scrollbar.setBackground(defaults.getColor("ScrollBar.background"));
814 scrollbar.setBorder(defaults.getBorder("ScrollBar.border"));
815 scrollbar.setOpaque(true);
816 scrollbar.setLayout(this);
818 thumbColor = defaults.getColor("ScrollBar.thumb");
819 thumbDarkShadowColor = defaults.getColor("ScrollBar.thumbDarkShadow");
820 thumbHighlightColor = defaults.getColor("ScrollBar.thumbHighlight");
821 thumbLightShadowColor = defaults.getColor("ScrollBar.thumbShadow");
823 maximumThumbSize = defaults.getDimension("ScrollBar.maximumThumbSize");
824 minimumThumbSize = defaults.getDimension("ScrollBar.minimumThumbSize");
828 * This method installs the keyboard actions for the scrollbar.
830 protected void installKeyboardActions()
836 * This method installs any listeners for the scrollbar. This method also
837 * installs listeners for things such as the JButtons and the timer.
839 protected void installListeners()
841 scrollListener = createScrollListener();
842 trackListener = createTrackListener();
843 buttonListener = createArrowButtonListener();
844 modelListener = createModelListener();
845 propertyChangeListener = createPropertyChangeListener();
847 scrollbar.addMouseMotionListener(trackListener);
848 scrollbar.addMouseListener(trackListener);
850 incrButton.addMouseListener(buttonListener);
851 decrButton.addMouseListener(buttonListener);
853 scrollbar.addPropertyChangeListener(propertyChangeListener);
854 scrollbar.getModel().addChangeListener(modelListener);
856 scrollTimer.addActionListener(scrollListener);
860 * This method installs the UI for the component. This can include setting
861 * up listeners, defaults, and components. This also includes initializing
864 * @param c The JComponent to install.
866 public void installUI(JComponent c)
869 if (c instanceof JScrollBar)
871 scrollbar = (JScrollBar) c;
873 trackRect = new Rectangle();
874 thumbRect = new Rectangle();
876 scrollTimer = new Timer(200, null);
877 scrollTimer.setRepeats(true);
881 configureScrollBarColors();
884 calculatePreferredSize();
889 * This method lays out the scrollbar.
891 * @param scrollbarContainer The Container to layout.
893 public void layoutContainer(Container scrollbarContainer)
895 if (scrollbarContainer instanceof JScrollBar)
897 if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL)
898 layoutHScrollbar((JScrollBar) scrollbarContainer);
900 layoutVScrollbar((JScrollBar) scrollbarContainer);
905 * This method lays out the scrollbar horizontally.
907 * @param sb The JScrollBar to layout.
909 protected void layoutHScrollbar(JScrollBar sb)
911 // All we have to do is layout the 2 buttons?
912 Rectangle vr = new Rectangle();
913 SwingUtilities.calculateInnerArea(scrollbar, vr);
915 // Update the rectangles.
919 Dimension incrDims = incrButton.getPreferredSize();
920 Dimension decrDims = decrButton.getPreferredSize();
922 decrButton.setBounds(vr.x, vr.y, decrDims.width, trackRect.height);
923 incrButton.setBounds(trackRect.x + trackRect.width, vr.y, incrDims.width,
928 * This method lays out the scrollbar vertically.
930 * @param sb The JScrollBar to layout.
932 protected void layoutVScrollbar(JScrollBar sb)
934 Rectangle vr = new Rectangle();
935 SwingUtilities.calculateInnerArea(scrollbar, vr);
941 Dimension incrDims = incrButton.getPreferredSize();
942 Dimension decrDims = decrButton.getPreferredSize();
944 decrButton.setBounds(vr.x, vr.y, trackRect.width, decrDims.height);
945 incrButton.setBounds(vr.x, trackRect.y + trackRect.height,
946 trackRect.width, incrDims.height);
950 * This method returns the minimum size required for the layout.
952 * @param scrollbarContainer The Container that is laid out.
954 * @return The minimum size.
956 public Dimension minimumLayoutSize(Container scrollbarContainer)
958 return preferredLayoutSize(scrollbarContainer);
962 * This method is called when the component is painted.
964 * @param g The Graphics object to paint with.
965 * @param c The JComponent to paint.
967 public void paint(Graphics g, JComponent c)
969 paintTrack(g, c, getTrackBounds());
970 paintThumb(g, c, getThumbBounds());
972 if (trackHighlight == INCREASE_HIGHLIGHT)
973 paintIncreaseHighlight(g);
974 else if (trackHighlight == DECREASE_HIGHLIGHT)
975 paintDecreaseHighlight(g);
979 * This method is called when repainting and the mouse is pressed in the
980 * track. It paints the track below the thumb with the trackHighlight
983 * @param g The Graphics object to paint with.
985 protected void paintDecreaseHighlight(Graphics g)
987 Color saved = g.getColor();
989 g.setColor(trackHighlightColor);
990 if (scrollbar.getOrientation() == HORIZONTAL)
991 g.fillRect(trackRect.x, trackRect.y, thumbRect.x - trackRect.x,
994 g.fillRect(trackRect.x, trackRect.y, trackRect.width,
995 thumbRect.y - trackRect.y);
1000 * This method is called when repainting and the mouse is pressed in the
1001 * track. It paints the track above the thumb with the trackHighlight
1004 * @param g The Graphics objet to paint with.
1006 protected void paintIncreaseHighlight(Graphics g)
1008 Color saved = g.getColor();
1010 g.setColor(trackHighlightColor);
1011 if (scrollbar.getOrientation() == HORIZONTAL)
1012 g.fillRect(thumbRect.x + thumbRect.width, trackRect.y,
1013 trackRect.x + trackRect.width - thumbRect.x - thumbRect.width,
1016 g.fillRect(trackRect.x, thumbRect.y + thumbRect.height, trackRect.width,
1017 trackRect.y + trackRect.height - thumbRect.y
1018 - thumbRect.height);
1023 * This method paints the thumb.
1025 * @param g The Graphics object to paint with.
1026 * @param c The Component that is being painted.
1027 * @param thumbBounds The thumb bounds.
1029 protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds)
1031 g.setColor(thumbColor);
1032 g.fillRect(thumbBounds.x, thumbBounds.y, thumbBounds.width,
1033 thumbBounds.height);
1035 BasicGraphicsUtils.drawBezel(g, thumbBounds.x, thumbBounds.y,
1036 thumbBounds.width, thumbBounds.height,
1037 false, false, thumbDarkShadowColor,
1038 thumbDarkShadowColor, thumbHighlightColor,
1039 thumbHighlightColor);
1043 * This method paints the track.
1045 * @param g The Graphics object to paint with.
1046 * @param c The JComponent being painted.
1047 * @param trackBounds The track's bounds.
1049 protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds)
1051 Color saved = g.getColor();
1052 g.setColor(trackColor);
1053 g.fill3DRect(trackBounds.x, trackBounds.y, trackBounds.width,
1054 trackBounds.height, false);
1059 * This method returns the preferred size for the layout.
1061 * @param scrollbarContainer The Container to find a size for.
1063 * @return The preferred size for the layout.
1065 public Dimension preferredLayoutSize(Container scrollbarContainer)
1067 if (scrollbarContainer instanceof JComponent)
1068 return getPreferredSize((JComponent) scrollbarContainer);
1074 * This method removes a child component from the layout.
1076 * @param child The child to remove.
1078 public void removeLayoutComponent(Component child)
1080 // You should not be removing stuff from this component.
1084 * The method scrolls the thumb by a block in the direction specified.
1086 * @param direction The direction to scroll.
1088 protected void scrollByBlock(int direction)
1090 scrollbar.setValue(scrollbar.getValue()
1091 + scrollbar.getBlockIncrement(direction));
1095 * The method scrolls the thumb by a unit in the direction specified.
1097 * @param direction The direction to scroll.
1099 protected void scrollByUnit(int direction)
1101 scrollbar.setValue(scrollbar.getValue()
1102 + scrollbar.getUnitIncrement(direction));
1106 * This method sets the thumb's bounds.
1108 * @param x The X position of the thumb.
1109 * @param y The Y position of the thumb.
1110 * @param width The width of the thumb.
1111 * @param height The height of the thumb.
1113 protected void setThumbBounds(int x, int y, int width, int height)
1117 thumbRect.width = width;
1118 thumbRect.height = height;
1122 * This method uninstalls any components that are a part of or related to
1125 protected void uninstallComponents()
1127 scrollbar.remove(incrButton);
1128 scrollbar.remove(decrButton);
1134 * This method uninstalls any defaults that this scrollbar acquired from the
1135 * Basic Look and Feel defaults.
1137 protected void uninstallDefaults()
1139 scrollbar.setForeground(null);
1140 scrollbar.setBackground(null);
1141 scrollbar.setBorder(null);
1145 * This method uninstalls any keyboard actions this scrollbar acquired
1148 protected void uninstallKeyboardActions()
1150 // FIXME: implement.
1154 * This method uninstalls any listeners that were registered during install.
1156 protected void uninstallListeners()
1158 scrollTimer.removeActionListener(scrollListener);
1160 scrollbar.getModel().removeChangeListener(modelListener);
1161 scrollbar.removePropertyChangeListener(propertyChangeListener);
1163 decrButton.removeMouseListener(buttonListener);
1164 incrButton.removeMouseListener(buttonListener);
1166 scrollbar.removeMouseListener(trackListener);
1167 scrollbar.removeMouseMotionListener(trackListener);
1169 propertyChangeListener = null;
1170 modelListener = null;
1171 buttonListener = null;
1172 trackListener = null;
1173 scrollListener = null;
1177 * This method uninstalls the UI. This includes removing any defaults,
1178 * listeners, and components that this UI may have initialized. It also
1179 * nulls any instance data.
1181 * @param c The Component to uninstall for.
1183 public void uninstallUI(JComponent c)
1185 uninstallDefaults();
1186 uninstallListeners();
1187 uninstallComponents();
1195 trackHighlightColor = null;
1197 thumbHighlightColor = null;
1198 thumbDarkShadowColor = null;
1199 thumbLightShadowColor = null;
1205 * This method returns the value in the scrollbar's range given the y
1206 * coordinate. If the value is out of range, it will return the closest
1208 * This is package-private to avoid an accessor method.
1210 * @param yPos The y coordinate to calculate a value for.
1212 * @return The value for the y coordinate.
1214 int valueForYPosition(int yPos)
1216 int min = scrollbar.getMinimum();
1217 int max = scrollbar.getMaximum();
1218 int len = trackRect.height;
1222 // If the length is 0, you shouldn't be able to even see where the thumb is.
1223 // This really shouldn't ever happen, but just in case, we'll return the middle.
1225 return ((max - min) / 2);
1227 value = ((yPos - trackRect.y) * (max - min) / len + min);
1229 // If this isn't a legal value, then we'll have to move to one now.
1232 else if (value < min)
1238 * This method returns the value in the scrollbar's range given the x
1239 * coordinate. If the value is out of range, it will return the closest
1241 * This is package-private to avoid an accessor method.
1243 * @param xPos The x coordinate to calculate a value for.
1245 * @return The value for the x coordinate.
1247 int valueForXPosition(int xPos)
1249 int min = scrollbar.getMinimum();
1250 int max = scrollbar.getMaximum();
1251 int len = trackRect.width;
1255 // If the length is 0, you shouldn't be able to even see where the slider is.
1256 // This really shouldn't ever happen, but just in case, we'll return the middle.
1258 return ((max - min) / 2);
1260 value = ((xPos - trackRect.x) * (max - min) / len + min);
1262 // If this isn't a legal value, then we'll have to move to one now.
1265 else if (value < min)