Merge from mainline (gomp-merge-2005-02-26).
[official-gcc.git] / libjava / javax / swing / plaf / basic / BasicScrollBarUI.java
blob36939b21da029036bccf0291f65c2d864f7116f9
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)
9 any later version.
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., 59 Temple Place, Suite 330, Boston, MA
19 02111-1307 USA.
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
24 combination.
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.Point;
49 import java.awt.Polygon;
50 import java.awt.Rectangle;
51 import java.awt.event.ActionEvent;
52 import java.awt.event.ActionListener;
53 import java.awt.event.MouseAdapter;
54 import java.awt.event.MouseEvent;
55 import java.awt.event.MouseMotionListener;
56 import java.beans.PropertyChangeEvent;
57 import java.beans.PropertyChangeListener;
59 import javax.swing.BoundedRangeModel;
60 import javax.swing.JButton;
61 import javax.swing.JComponent;
62 import javax.swing.JScrollBar;
63 import javax.swing.SwingConstants;
64 import javax.swing.SwingUtilities;
65 import javax.swing.Timer;
66 import javax.swing.UIDefaults;
67 import javax.swing.UIManager;
68 import javax.swing.event.ChangeEvent;
69 import javax.swing.event.ChangeListener;
70 import javax.swing.plaf.ComponentUI;
71 import javax.swing.plaf.ScrollBarUI;
73 /**
74 * The Basic Look and Feel UI delegate for JScrollBar.
76 public class BasicScrollBarUI extends ScrollBarUI implements LayoutManager,
77 SwingConstants
79 /**
80 * A helper class that listens to the two JButtons on each end of the
81 * JScrollBar.
83 protected class ArrowButtonListener extends MouseAdapter
85 /**
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)
93 scrollTimer.stop();
94 scrollListener.setScrollByBlock(false);
95 if (e.getSource() == incrButton)
96 scrollListener.setDirection(POSITIVE_SCROLL);
97 else
98 scrollListener.setDirection(NEGATIVE_SCROLL);
99 scrollTimer.start();
103 * Stops the thumb when the JButton is released.
105 * @param e The MouseEvent fired by the JButton.
107 public void mouseReleased(MouseEvent e)
109 scrollTimer.stop();
114 * A helper class that listens to the ScrollBar's model for ChangeEvents.
116 protected class ModelListener implements ChangeListener
119 * Called when the model changes.
121 * @param e The ChangeEvent fired by the model.
123 public void stateChanged(ChangeEvent e)
125 // System.err.println(this + ".stateChanged()");
126 calculatePreferredSize();
127 layoutContainer(scrollbar);
128 getThumbBounds();
129 scrollbar.repaint();
134 * A helper class that listens to the ScrollBar's properties.
136 public class PropertyChangeHandler implements PropertyChangeListener
139 * Called when one of the ScrollBar's properties change.
141 * @param e The PropertyChangeEvent fired by the ScrollBar.
143 public void propertyChange(PropertyChangeEvent e)
145 if (e.getPropertyName().equals("model"))
147 ((BoundedRangeModel) e.getOldValue()).removeChangeListener(modelListener);
148 scrollbar.getModel().addChangeListener(modelListener);
149 getThumbBounds();
151 else if (e.getPropertyName().equals("orientation"))
153 incrButton.removeMouseListener(buttonListener);
154 decrButton.removeMouseListener(buttonListener);
155 incrButton = createIncreaseButton(scrollbar.getOrientation());
156 decrButton = createDecreaseButton(scrollbar.getOrientation());
157 incrButton.addMouseListener(buttonListener);
158 decrButton.addMouseListener(buttonListener);
159 calculatePreferredSize();
160 layoutContainer(scrollbar);
162 layoutContainer(scrollbar);
163 scrollbar.repaint();
168 * A helper class that listens for events from the timer that is used to
169 * move the thumb.
171 protected class ScrollListener implements ActionListener
173 /** The direction the thumb moves in. */
174 private transient int direction;
176 /** Whether movement will be in blocks. */
177 private transient boolean block;
180 * Creates a new ScrollListener object. The default is scrolling
181 * positively with block movement.
183 public ScrollListener()
185 direction = POSITIVE_SCROLL;
186 block = true;
190 * Creates a new ScrollListener object using the given direction and
191 * block.
193 * @param dir The direction to move in.
194 * @param block Whether movement will be in blocks.
196 public ScrollListener(int dir, boolean block)
198 direction = dir;
199 this.block = block;
203 * Sets the direction to scroll in.
205 * @param direction The direction to scroll in.
207 public void setDirection(int direction)
209 this.direction = direction;
213 * Sets whether scrolling will be done in blocks.
215 * @param block Whether scrolling will be in blocks.
217 public void setScrollByBlock(boolean block)
219 this.block = block;
223 * Called every time the timer reaches its interval.
225 * @param e The ActionEvent fired by the timer.
227 public void actionPerformed(ActionEvent e)
229 if (block)
231 // Only need to check it if it's block scrolling
232 // We only block scroll if the click occurs
233 // in the track.
234 if (! trackListener.shouldScroll(direction))
236 trackHighlight = NO_HIGHLIGHT;
237 scrollbar.repaint();
238 return;
240 scrollByBlock(direction);
242 else
243 scrollByUnit(direction);
248 * Helper class that listens for movement on the track.
250 protected class TrackListener extends MouseAdapter
251 implements MouseMotionListener
253 /** The current X coordinate of the mouse. */
254 protected int currentMouseX;
256 /** The current Y coordinate of the mouse. */
257 protected int currentMouseY;
260 * The offset between the current mouse cursor and the current value of
261 * the scrollbar.
263 protected int offset;
266 * This method is called when the mouse is being dragged.
268 * @param e The MouseEvent given.
270 public void mouseDragged(MouseEvent e)
272 currentMouseX = e.getX();
273 currentMouseY = e.getY();
274 if (scrollbar.getValueIsAdjusting())
276 int value;
277 if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL)
278 value = valueForXPosition(currentMouseX) - offset;
279 else
280 value = valueForYPosition(currentMouseY) - offset;
282 scrollbar.setValue(value);
287 * This method is called when the mouse is moved.
289 * @param e The MouseEvent given.
291 public void mouseMoved(MouseEvent e)
293 // Not interested in where the mouse
294 // is unless it is being dragged.
298 * This method is called when the mouse is pressed. When it is pressed,
299 * the thumb should move in blocks towards the cursor.
301 * @param e The MouseEvent given.
303 public void mousePressed(MouseEvent e)
305 currentMouseX = e.getX();
306 currentMouseY = e.getY();
308 int value;
309 if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL)
310 value = valueForXPosition(currentMouseX);
311 else
312 value = valueForYPosition(currentMouseY);
314 if (value == scrollbar.getValue())
315 return;
317 if (! thumbRect.contains(e.getPoint()))
319 scrollTimer.stop();
320 scrollListener.setScrollByBlock(true);
321 if (value > scrollbar.getValue())
323 trackHighlight = INCREASE_HIGHLIGHT;
324 scrollListener.setDirection(POSITIVE_SCROLL);
326 else
328 trackHighlight = DECREASE_HIGHLIGHT;
329 scrollListener.setDirection(NEGATIVE_SCROLL);
331 scrollTimer.start();
333 else
335 // We'd like to keep track of where the cursor
336 // is inside the thumb.
337 // This works because the scrollbar's value represents
338 // "lower" edge of the thumb. The value at which
339 // the cursor is at must be greater or equal
340 // to that value.
341 scrollbar.setValueIsAdjusting(true);
342 offset = value - scrollbar.getValue();
344 scrollbar.repaint();
348 * This method is called when the mouse is released. It should stop
349 * movement on the thumb
351 * @param e The MouseEvent given.
353 public void mouseReleased(MouseEvent e)
355 trackHighlight = NO_HIGHLIGHT;
356 scrollTimer.stop();
358 if (scrollbar.getValueIsAdjusting())
359 scrollbar.setValueIsAdjusting(false);
360 scrollbar.repaint();
364 * A helper method that decides whether we should keep scrolling in the
365 * given direction.
367 * @param direction The direction to check for.
369 * @return Whether the thumb should keep scrolling.
371 public boolean shouldScroll(int direction)
373 int value;
374 if (scrollbar.getOrientation() == HORIZONTAL)
375 value = valueForXPosition(currentMouseX);
376 else
377 value = valueForYPosition(currentMouseY);
379 if (direction == POSITIVE_SCROLL)
380 return (value > scrollbar.getValue());
381 else
382 return (value < scrollbar.getValue());
386 /** The listener that listens to the JButtons. */
387 protected ArrowButtonListener buttonListener;
389 /** The listener that listens to the model. */
390 protected ModelListener modelListener;
392 /** The listener that listens to the scrollbar for property changes. */
393 protected PropertyChangeListener propertyChangeListener;
395 /** The listener that listens to the timer. */
396 protected ScrollListener scrollListener;
398 /** The listener that listens for MouseEvents on the track. */
399 protected TrackListener trackListener;
401 /** The JButton that decrements the scrollbar's value. */
402 protected JButton decrButton;
404 /** The JButton that increments the scrollbar's value. */
405 protected JButton incrButton;
407 /** The dimensions of the maximum thumb size. */
408 protected Dimension maximumThumbSize;
410 /** The dimensions of the minimum thumb size. */
411 protected Dimension minimumThumbSize;
413 /** The color of the thumb. */
414 protected Color thumbColor;
416 /** The outer shadow of the thumb. */
417 protected Color thumbDarkShadowColor;
419 /** The top and left edge color for the thumb. */
420 protected Color thumbHighlightColor;
422 /** The outer light shadow for the thumb. */
423 protected Color thumbLightShadowColor;
425 /** The color that is used when the mouse press occurs in the track. */
426 protected Color trackHighlightColor;
428 /** The color of the track. */
429 protected Color trackColor;
431 /** The size and position of the track. */
432 protected Rectangle trackRect;
434 /** The size and position of the thumb. */
435 protected Rectangle thumbRect;
437 /** Indicates that the decrease highlight should be painted. */
438 protected static final int DECREASE_HIGHLIGHT = 1;
440 /** Indicates that the increase highlight should be painted. */
441 protected static final int INCREASE_HIGHLIGHT = 2;
443 /** Indicates that no highlight should be painted. */
444 protected static final int NO_HIGHLIGHT = 0;
446 /** Indicates that the scrolling direction is positive. */
447 private static final int POSITIVE_SCROLL = 1;
449 /** Indicates that the scrolling direction is negative. */
450 private static final int NEGATIVE_SCROLL = -1;
452 /** The cached preferred size for the scrollbar. */
453 private transient Dimension preferredSize;
455 /** The current highlight status. */
456 protected int trackHighlight;
458 /** FIXME: Use this for something (presumably mouseDragged) */
459 protected boolean isDragging;
461 /** The timer used to move the thumb when the mouse is held. */
462 protected Timer scrollTimer;
464 /** The scrollbar this UI is acting for. */
465 protected JScrollBar scrollbar;
468 * This method adds a component to the layout.
470 * @param name The name to associate with the component that is added.
471 * @param child The Component to add.
473 public void addLayoutComponent(String name, Component child)
475 // You should not be adding stuff to this component.
476 // The contents are fixed.
480 * This method configures the scrollbar's colors. This can be done by
481 * looking up the standard colors from the Look and Feel defaults.
483 protected void configureScrollBarColors()
485 UIDefaults defaults = UIManager.getLookAndFeelDefaults();
487 trackColor = defaults.getColor("ScrollBar.track");
488 trackHighlightColor = defaults.getColor("ScrollBar.trackHighlight");
489 thumbColor = defaults.getColor("ScrollBar.thumb");
490 thumbHighlightColor = defaults.getColor("ScrollBar.thumbHighlight");
491 thumbDarkShadowColor = defaults.getColor("ScrollBar.thumbDarkShadow");
492 thumbLightShadowColor = defaults.getColor("ScrollBar.thumbLightShadow");
496 * This method creates an ArrowButtonListener.
498 * @return A new ArrowButtonListener.
500 protected ArrowButtonListener createArrowButtonListener()
502 return new ArrowButtonListener();
506 * This method creates a new JButton with the appropriate icon for the
507 * orientation.
509 * @param orientation The orientation this JButton uses.
511 * @return The increase JButton.
513 protected JButton createIncreaseButton(int orientation)
515 if (incrButton == null)
516 incrButton = new BasicArrowButton((orientation == SwingConstants.HORIZONTAL)
517 ? SwingConstants.EAST
518 : SwingConstants.SOUTH);
519 else
521 if (orientation == SwingConstants.HORIZONTAL)
522 ((BasicArrowButton) incrButton).setDirection(SwingConstants.EAST);
523 else
524 ((BasicArrowButton) incrButton).setDirection(SwingConstants.SOUTH);
526 return incrButton;
530 * This method creates a new JButton with the appropriate icon for the
531 * orientation.
533 * @param orientation The orientation this JButton uses.
535 * @return The decrease JButton.
537 protected JButton createDecreaseButton(int orientation)
539 if (decrButton == null)
540 decrButton = new BasicArrowButton((orientation == SwingConstants.HORIZONTAL)
541 ? SwingConstants.WEST
542 : SwingConstants.NORTH);
543 else
545 if (orientation == SwingConstants.HORIZONTAL)
546 ((BasicArrowButton) decrButton).setDirection(SwingConstants.WEST);
547 else
548 ((BasicArrowButton) decrButton).setDirection(SwingConstants.NORTH);
550 return decrButton;
554 * This method creates a new ModelListener.
556 * @return A new ModelListener.
558 protected ModelListener createModelListener()
560 return new ModelListener();
564 * This method creates a new PropertyChangeListener.
566 * @return A new PropertyChangeListener.
568 protected PropertyChangeListener createPropertyChangeListener()
570 return new PropertyChangeHandler();
574 * This method creates a new ScrollListener.
576 * @return A new ScrollListener.
578 protected ScrollListener createScrollListener()
580 return new ScrollListener();
584 * This method creates a new TrackListener.
586 * @return A new TrackListener.
588 protected TrackListener createTrackListener()
590 return new TrackListener();
594 * This method returns a new BasicScrollBarUI.
596 * @param c The JComponent to create a UI for.
598 * @return A new BasicScrollBarUI.
600 public static ComponentUI createUI(JComponent c)
602 return new BasicScrollBarUI();
606 * This method returns the maximum size for this JComponent.
608 * @param c The JComponent to measure the maximum size for.
610 * @return The maximum size for the component.
612 public Dimension getMaximumSize(JComponent c)
614 return getPreferredSize(c);
618 * This method returns the maximum thumb size.
620 * @return The maximum thumb size.
622 protected Dimension getMaximumThumbSize()
624 return maximumThumbSize;
628 * This method returns the minimum size for this JComponent.
630 * @param c The JComponent to measure the minimum size for.
632 * @return The minimum size for the component.
634 public Dimension getMinimumSize(JComponent c)
636 return getPreferredSize(c);
640 * This method returns the minimum thumb size.
642 * @return The minimum thumb size.
644 protected Dimension getMinimumThumbSize()
646 return minimumThumbSize;
650 * This method calculates the preferred size since calling
651 * getPreferredSize() returns a cached value.
653 private void calculatePreferredSize()
655 // System.err.println(this + ".calculatePreferredSize()");
656 int height;
657 int width;
658 height = width = 0;
660 if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL)
662 width += incrButton.getPreferredSize().getWidth();
663 width += decrButton.getPreferredSize().getWidth();
665 width += (scrollbar.getMaximum() - scrollbar.getMinimum());
667 height = Math.max(incrButton.getPreferredSize().height,
668 decrButton.getPreferredSize().height);
669 height = Math.max(getMinimumThumbSize().height, height);
670 height = Math.max(20, height);
671 height = Math.min(getMaximumThumbSize().height, height);
673 else
675 height += incrButton.getPreferredSize().getHeight();
676 height += decrButton.getPreferredSize().getHeight();
678 height += (scrollbar.getMaximum() - scrollbar.getMinimum());
680 width = Math.max(incrButton.getPreferredSize().width,
681 decrButton.getPreferredSize().width);
682 width = Math.max(getMinimumThumbSize().width, width);
683 width = Math.max(20, width);
684 width = Math.min(getMaximumThumbSize().width, width);
687 Insets insets = scrollbar.getInsets();
689 height += insets.top + insets.bottom;
690 width += insets.left + insets.right;
692 preferredSize = new Dimension(width, height);
696 * This method returns a cached value of the preferredSize. The only
697 * restrictions are: If the scrollbar is horizontal, the height should be
698 * the maximum of the height of the JButtons and the minimum width of the
699 * thumb. For vertical scrollbars, the calculation is similar (swap width
700 * for height and vice versa).
702 * @param c The JComponent to measure.
704 * @return The preferredSize.
706 public Dimension getPreferredSize(JComponent c)
708 calculatePreferredSize();
709 return preferredSize;
713 * This method returns the thumb's bounds based on the current value of the
714 * scrollbar. This method updates the cached value and returns that.
716 * @return The thumb bounds.
718 protected Rectangle getThumbBounds()
720 int max = scrollbar.getMaximum();
721 int min = scrollbar.getMinimum();
722 int value = scrollbar.getValue();
723 int extent = scrollbar.getVisibleAmount();
725 // System.err.println(this + ".getThumbBounds()");
726 if (max == min)
728 thumbRect.x = trackRect.x;
729 thumbRect.y = trackRect.y;
730 if (scrollbar.getOrientation() == HORIZONTAL)
732 thumbRect.width = getMinimumThumbSize().width;
733 thumbRect.height = trackRect.height;
735 else
737 thumbRect.width = trackRect.width;
738 thumbRect.height = getMinimumThumbSize().height;
740 return thumbRect;
743 if (scrollbar.getOrientation() == HORIZONTAL)
745 thumbRect.x = trackRect.x;
746 thumbRect.x += (value - min) * trackRect.width / (max - min);
747 thumbRect.y = trackRect.y;
749 thumbRect.width = extent * trackRect.width / (max - min);
750 thumbRect.height = trackRect.height;
752 else
754 thumbRect.x = trackRect.x;
755 thumbRect.y = trackRect.y + value * trackRect.height / (max - min);
757 thumbRect.width = trackRect.width;
758 thumbRect.height = extent * trackRect.height / (max - min);
760 return thumbRect;
764 * This method calculates the bounds of the track. This method updates the
765 * cached value and returns it.
767 * @return The track's bounds.
769 protected Rectangle getTrackBounds()
771 SwingUtilities.calculateInnerArea(scrollbar, trackRect);
773 if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL)
775 trackRect.width -= incrButton.getPreferredSize().getWidth();
776 trackRect.width -= decrButton.getPreferredSize().getWidth();
778 trackRect.x += decrButton.getPreferredSize().getWidth();
780 else
782 trackRect.height -= incrButton.getPreferredSize().getHeight();
783 trackRect.height -= decrButton.getPreferredSize().getHeight();
785 trackRect.y += incrButton.getPreferredSize().getHeight();
787 return trackRect;
791 * This method installs any addition Components that are a part of or
792 * related to this scrollbar.
794 protected void installComponents()
796 incrButton = createIncreaseButton(scrollbar.getOrientation());
797 scrollbar.add(incrButton);
798 decrButton = createDecreaseButton(scrollbar.getOrientation());
799 scrollbar.add(decrButton);
803 * This method installs the defaults for the scrollbar specified by the
804 * Basic Look and Feel.
806 protected void installDefaults()
808 UIDefaults defaults = UIManager.getLookAndFeelDefaults();
810 scrollbar.setForeground(defaults.getColor("ScrollBar.foreground"));
811 scrollbar.setBackground(defaults.getColor("ScrollBar.background"));
812 scrollbar.setBorder(defaults.getBorder("ScrollBar.border"));
813 scrollbar.setOpaque(true);
815 maximumThumbSize = defaults.getDimension("ScrollBar.maximumThumbSize");
816 minimumThumbSize = defaults.getDimension("ScrollBar.minimumThumbSize");
820 * This method installs the keyboard actions for the scrollbar.
822 protected void installKeyboardActions()
824 // FIXME: implement.
828 * This method installs any listeners for the scrollbar. This method also
829 * installs listeners for things such as the JButtons and the timer.
831 protected void installListeners()
833 scrollListener = createScrollListener();
834 trackListener = createTrackListener();
835 buttonListener = createArrowButtonListener();
836 modelListener = createModelListener();
837 propertyChangeListener = createPropertyChangeListener();
839 scrollbar.addMouseMotionListener(trackListener);
840 scrollbar.addMouseListener(trackListener);
842 incrButton.addMouseListener(buttonListener);
843 decrButton.addMouseListener(buttonListener);
845 scrollbar.addPropertyChangeListener(propertyChangeListener);
846 scrollbar.getModel().addChangeListener(modelListener);
848 scrollTimer.addActionListener(scrollListener);
852 * This method installs the UI for the component. This can include setting
853 * up listeners, defaults, and components. This also includes initializing
854 * any data objects.
856 * @param c The JComponent to install.
858 public void installUI(JComponent c)
860 super.installUI(c);
861 if (c instanceof JScrollBar)
863 scrollbar = (JScrollBar) c;
865 trackRect = new Rectangle();
866 thumbRect = new Rectangle();
868 scrollTimer = new Timer(200, null);
869 scrollTimer.setRepeats(true);
871 installComponents();
872 installListeners();
873 installDefaults();
874 configureScrollBarColors();
876 calculatePreferredSize();
877 layoutContainer(scrollbar);
882 * This method lays out the scrollbar.
884 * @param scrollbarContainer The Container to layout.
886 public void layoutContainer(Container scrollbarContainer)
888 if (scrollbarContainer instanceof JScrollBar)
890 if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL)
891 layoutHScrollbar((JScrollBar) scrollbarContainer);
892 else
893 layoutVScrollbar((JScrollBar) scrollbarContainer);
898 * This method lays out the scrollbar horizontally.
900 * @param sb The JScrollBar to layout.
902 protected void layoutHScrollbar(JScrollBar sb)
904 // All we have to do is layout the 2 buttons?
905 Rectangle vr = new Rectangle();
906 SwingUtilities.calculateInnerArea(scrollbar, vr);
908 // Update the rectangles.
909 getTrackBounds();
910 getThumbBounds();
912 Dimension incrDims = incrButton.getPreferredSize();
913 Dimension decrDims = decrButton.getPreferredSize();
915 decrButton.setBounds(vr.x, vr.y, decrDims.width, trackRect.height);
916 incrButton.setBounds(trackRect.x + trackRect.width, vr.y, incrDims.width,
917 trackRect.height);
921 * This method lays out the scrollbar vertically.
923 * @param sb The JScrollBar to layout.
925 protected void layoutVScrollbar(JScrollBar sb)
927 Rectangle vr = new Rectangle();
928 SwingUtilities.calculateInnerArea(scrollbar, vr);
930 // Update rectangles
931 getTrackBounds();
932 getThumbBounds();
934 Dimension incrDims = incrButton.getPreferredSize();
935 Dimension decrDims = decrButton.getPreferredSize();
937 decrButton.setBounds(vr.x, vr.y, trackRect.width, decrDims.height);
938 incrButton.setBounds(vr.x, trackRect.y + trackRect.height,
939 trackRect.width, incrDims.height);
943 * This method returns the minimum size required for the layout.
945 * @param scrollbarContainer The Container that is laid out.
947 * @return The minimum size.
949 public Dimension minimumLayoutSize(Container scrollbarContainer)
951 return preferredLayoutSize(scrollbarContainer);
955 * This method is called when the component is painted.
957 * @param g The Graphics object to paint with.
958 * @param c The JComponent to paint.
960 public void paint(Graphics g, JComponent c)
962 layoutContainer(scrollbar);
963 paintTrack(g, c, getTrackBounds());
964 paintThumb(g, c, getThumbBounds());
966 if (trackHighlight == INCREASE_HIGHLIGHT)
967 paintIncreaseHighlight(g);
968 else if (trackHighlight == DECREASE_HIGHLIGHT)
969 paintDecreaseHighlight(g);
973 * This method is called when repainting and the mouse is pressed in the
974 * track. It paints the track below the thumb with the trackHighlight
975 * color.
977 * @param g The Graphics object to paint with.
979 protected void paintDecreaseHighlight(Graphics g)
981 Color saved = g.getColor();
983 g.setColor(trackHighlightColor);
984 if (scrollbar.getOrientation() == HORIZONTAL)
985 g.fillRect(trackRect.x, trackRect.y, thumbRect.x - trackRect.x,
986 trackRect.height);
987 else
988 g.fillRect(trackRect.x, trackRect.y, trackRect.width,
989 thumbRect.y - trackRect.y);
990 g.setColor(saved);
994 * This method is called when repainting and the mouse is pressed in the
995 * track. It paints the track above the thumb with the trackHighlight
996 * color.
998 * @param g The Graphics objet to paint with.
1000 protected void paintIncreaseHighlight(Graphics g)
1002 Color saved = g.getColor();
1004 g.setColor(trackHighlightColor);
1005 if (scrollbar.getOrientation() == HORIZONTAL)
1006 g.fillRect(thumbRect.x + thumbRect.width, trackRect.y,
1007 trackRect.x + trackRect.width - thumbRect.x - thumbRect.width,
1008 trackRect.height);
1009 else
1010 g.fillRect(trackRect.x, thumbRect.y + thumbRect.height, trackRect.width,
1011 trackRect.y + trackRect.height - thumbRect.y
1012 - thumbRect.height);
1013 g.setColor(saved);
1017 * This method paints the thumb.
1019 * @param g The Graphics object to paint with.
1020 * @param c The Component that is being painted.
1021 * @param thumbBounds The thumb bounds.
1023 protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds)
1025 Color saved = g.getColor();
1026 Point x;
1027 Point y;
1028 Point z;
1029 Polygon lines;
1031 g.setColor(thumbHighlightColor);
1032 x = new Point(thumbBounds.x + 1, thumbBounds.y + 1);
1033 y = new Point(x);
1034 y.translate(thumbBounds.width - 2, 0);
1035 z = new Point(x);
1036 z.translate(0, thumbBounds.height - 2);
1038 lines = new Polygon(new int[] { x.x, y.x, z.x },
1039 new int[] { x.y, y.y, z.y }, 3);
1041 g.drawPolygon(lines);
1043 g.setColor(thumbLightShadowColor);
1044 x = new Point(thumbBounds.x + thumbBounds.width - 1,
1045 thumbBounds.y + thumbBounds.height - 1);
1046 y = new Point(x);
1047 y.translate(-(thumbBounds.width - 2), 0);
1048 z = new Point(x);
1049 z.translate(0, -(thumbBounds.height - 2));
1051 lines = new Polygon(new int[] { x.x, y.x, z.x },
1052 new int[] { x.y, y.y, z.y }, 3);
1053 g.drawPolygon(lines);
1055 g.setColor(thumbDarkShadowColor);
1056 x = new Point(thumbBounds.x + thumbBounds.width,
1057 thumbBounds.y + thumbBounds.height);
1058 y = new Point(x);
1059 y.translate(-thumbBounds.width, 0);
1060 z = new Point(x);
1061 z.translate(0, -thumbBounds.height);
1063 lines = new Polygon(new int[] { x.x, y.x, z.x },
1064 new int[] { x.y, y.y, z.y }, 3);
1065 g.drawPolygon(lines);
1067 g.setColor(thumbColor);
1068 g.fillRect(thumbBounds.x, thumbBounds.y, thumbBounds.width,
1069 thumbBounds.height);
1071 g.setColor(saved);
1075 * This method paints the track.
1077 * @param g The Graphics object to paint with.
1078 * @param c The JComponent being painted.
1079 * @param trackBounds The track's bounds.
1081 protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds)
1083 Color saved = g.getColor();
1084 g.setColor(trackColor);
1085 g.fill3DRect(trackBounds.x, trackBounds.y, trackBounds.width,
1086 trackBounds.height, false);
1087 g.setColor(saved);
1091 * This method returns the preferred size for the layout.
1093 * @param scrollbarContainer The Container to find a size for.
1095 * @return The preferred size for the layout.
1097 public Dimension preferredLayoutSize(Container scrollbarContainer)
1099 if (scrollbarContainer instanceof JComponent)
1100 return getPreferredSize((JComponent) scrollbarContainer);
1101 else
1102 return null;
1106 * This method removes a child component from the layout.
1108 * @param child The child to remove.
1110 public void removeLayoutComponent(Component child)
1112 // You should not be removing stuff from this component.
1116 * The method scrolls the thumb by a block in the direction specified.
1118 * @param direction The direction to scroll.
1120 protected void scrollByBlock(int direction)
1122 scrollbar.setValue(scrollbar.getValue()
1123 + scrollbar.getBlockIncrement(direction));
1127 * The method scrolls the thumb by a unit in the direction specified.
1129 * @param direction The direction to scroll.
1131 protected void scrollByUnit(int direction)
1133 scrollbar.setValue(scrollbar.getValue()
1134 + scrollbar.getUnitIncrement(direction));
1138 * This method sets the thumb's bounds.
1140 * @param x The X position of the thumb.
1141 * @param y The Y position of the thumb.
1142 * @param width The width of the thumb.
1143 * @param height The height of the thumb.
1145 protected void setThumbBounds(int x, int y, int width, int height)
1147 thumbRect.x = x;
1148 thumbRect.y = y;
1149 thumbRect.width = width;
1150 thumbRect.height = height;
1154 * This method uninstalls any components that are a part of or related to
1155 * this scrollbar.
1157 protected void uninstallComponents()
1159 scrollbar.remove(incrButton);
1160 scrollbar.remove(decrButton);
1161 incrButton = null;
1162 decrButton = null;
1166 * This method uninstalls any defaults that this scrollbar acquired from the
1167 * Basic Look and Feel defaults.
1169 protected void uninstallDefaults()
1171 scrollbar.setForeground(null);
1172 scrollbar.setBackground(null);
1173 scrollbar.setBorder(null);
1177 * This method uninstalls any keyboard actions this scrollbar acquired
1178 * during install.
1180 protected void uninstallKeyboardActions()
1182 // FIXME: implement.
1186 * This method uninstalls any listeners that were registered during install.
1188 protected void uninstallListeners()
1190 scrollTimer.removeActionListener(scrollListener);
1192 scrollbar.getModel().removeChangeListener(modelListener);
1193 scrollbar.removePropertyChangeListener(propertyChangeListener);
1195 decrButton.removeMouseListener(buttonListener);
1196 incrButton.removeMouseListener(buttonListener);
1198 scrollbar.removeMouseListener(trackListener);
1199 scrollbar.removeMouseMotionListener(trackListener);
1201 propertyChangeListener = null;
1202 modelListener = null;
1203 buttonListener = null;
1204 trackListener = null;
1205 scrollListener = null;
1209 * This method uninstalls the UI. This includes removing any defaults,
1210 * listeners, and components that this UI may have initialized. It also
1211 * nulls any instance data.
1213 * @param c The Component to uninstall for.
1215 public void uninstallUI(JComponent c)
1217 uninstallDefaults();
1218 uninstallListeners();
1219 uninstallComponents();
1221 scrollTimer = null;
1223 thumbRect = null;
1224 trackRect = null;
1226 trackColor = null;
1227 trackHighlightColor = null;
1228 thumbColor = null;
1229 thumbHighlightColor = null;
1230 thumbDarkShadowColor = null;
1231 thumbLightShadowColor = null;
1233 scrollbar = null;
1237 * This method returns the value in the scrollbar's range given the y
1238 * coordinate. If the value is out of range, it will return the closest
1239 * legal value.
1241 * @param yPos The y coordinate to calculate a value for.
1243 * @return The value for the y coordinate.
1245 private int valueForYPosition(int yPos)
1247 int min = scrollbar.getMinimum();
1248 int max = scrollbar.getMaximum();
1249 int len = trackRect.height;
1251 int value;
1253 // If the length is 0, you shouldn't be able to even see where the thumb is.
1254 // This really shouldn't ever happen, but just in case, we'll return the middle.
1255 if (len == 0)
1256 return ((max - min) / 2);
1258 value = ((yPos - trackRect.y) * (max - min) / len + min);
1260 // If this isn't a legal value, then we'll have to move to one now.
1261 if (value > max)
1262 value = max;
1263 else if (value < min)
1264 value = min;
1265 return value;
1269 * This method returns the value in the scrollbar's range given the x
1270 * coordinate. If the value is out of range, it will return the closest
1271 * legal value.
1273 * @param xPos The x coordinate to calculate a value for.
1275 * @return The value for the x coordinate.
1277 private int valueForXPosition(int xPos)
1279 int min = scrollbar.getMinimum();
1280 int max = scrollbar.getMaximum();
1281 int len = trackRect.width;
1283 int value;
1285 // If the length is 0, you shouldn't be able to even see where the slider is.
1286 // This really shouldn't ever happen, but just in case, we'll return the middle.
1287 if (len == 0)
1288 return ((max - min) / 2);
1290 value = ((xPos - trackRect.x) * (max - min) / len + min);
1292 // If this isn't a legal value, then we'll have to move to one now.
1293 if (value > max)
1294 value = max;
1295 else if (value < min)
1296 value = min;
1297 return value;