Imported GNU Classpath 0.90
[official-gcc.git] / libjava / classpath / javax / swing / plaf / basic / BasicScrollBarUI.java
blobf2448548472363fa007d989e473f52e63a2867c3
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., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 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 gnu.classpath.NotImplementedException;
43 import java.awt.Color;
44 import java.awt.Component;
45 import java.awt.Container;
46 import java.awt.Dimension;
47 import java.awt.Graphics;
48 import java.awt.Insets;
49 import java.awt.LayoutManager;
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.LookAndFeel;
64 import javax.swing.SwingConstants;
65 import javax.swing.SwingUtilities;
66 import javax.swing.Timer;
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
86 /**
87 * Move the thumb in the direction specified by the button's arrow. If
88 * this button is held down, then it should keep moving the thumb.
90 * @param e The MouseEvent fired by the JButton.
92 public void mousePressed(MouseEvent e)
94 scrollTimer.stop();
95 scrollListener.setScrollByBlock(false);
96 if (e.getSource() == incrButton)
97 scrollListener.setDirection(POSITIVE_SCROLL);
98 else if (e.getSource() == decrButton)
99 scrollListener.setDirection(NEGATIVE_SCROLL);
100 scrollTimer.setDelay(100);
101 scrollTimer.start();
105 * Stops the thumb when the JButton is released.
107 * @param e The MouseEvent fired by the JButton.
109 public void mouseReleased(MouseEvent e)
111 scrollTimer.stop();
112 scrollTimer.setDelay(300);
113 if (e.getSource() == incrButton)
114 scrollByUnit(POSITIVE_SCROLL);
115 else if (e.getSource() == decrButton)
116 scrollByUnit(NEGATIVE_SCROLL);
121 * A helper class that listens to the ScrollBar's model for ChangeEvents.
123 protected class ModelListener implements ChangeListener
126 * Called when the model changes.
128 * @param e The ChangeEvent fired by the model.
130 public void stateChanged(ChangeEvent e)
132 calculatePreferredSize();
133 updateThumbRect();
134 scrollbar.repaint();
139 * A helper class that listens to the ScrollBar's properties.
141 public class PropertyChangeHandler implements PropertyChangeListener
144 * Called when one of the ScrollBar's properties change.
146 * @param e The PropertyChangeEvent fired by the ScrollBar.
148 public void propertyChange(PropertyChangeEvent e)
150 if (e.getPropertyName().equals("model"))
152 ((BoundedRangeModel) e.getOldValue()).removeChangeListener(modelListener);
153 scrollbar.getModel().addChangeListener(modelListener);
154 updateThumbRect();
156 else if (e.getPropertyName().equals("orientation"))
158 uninstallListeners();
159 uninstallComponents();
160 uninstallDefaults();
161 installDefaults();
162 installComponents();
163 installListeners();
165 else if (e.getPropertyName().equals("enabled"))
167 Boolean b = (Boolean) e.getNewValue();
168 if (incrButton != null)
169 incrButton.setEnabled(b.booleanValue());
170 if (decrButton != null)
171 decrButton.setEnabled(b.booleanValue());
177 * A helper class that listens for events from the timer that is used to
178 * move the thumb.
180 protected class ScrollListener implements ActionListener
182 /** The direction the thumb moves in. */
183 private transient int direction;
185 /** Whether movement will be in blocks. */
186 private transient boolean block;
189 * Creates a new ScrollListener object. The default is scrolling
190 * positively with block movement.
192 public ScrollListener()
194 direction = POSITIVE_SCROLL;
195 block = true;
199 * Creates a new ScrollListener object using the given direction and
200 * block.
202 * @param dir The direction to move in.
203 * @param block Whether movement will be in blocks.
205 public ScrollListener(int dir, boolean block)
207 direction = dir;
208 this.block = block;
212 * Sets the direction to scroll in.
214 * @param direction The direction to scroll in.
216 public void setDirection(int direction)
218 this.direction = direction;
222 * Sets whether scrolling will be done in blocks.
224 * @param block Whether scrolling will be in blocks.
226 public void setScrollByBlock(boolean block)
228 this.block = block;
232 * Called every time the timer reaches its interval.
234 * @param e The ActionEvent fired by the timer.
236 public void actionPerformed(ActionEvent e)
238 if (block)
240 // Only need to check it if it's block scrolling
241 // We only block scroll if the click occurs
242 // in the track.
243 if (!trackListener.shouldScroll(direction))
245 trackHighlight = NO_HIGHLIGHT;
246 scrollbar.repaint();
247 return;
249 scrollByBlock(direction);
251 else
252 scrollByUnit(direction);
257 * Helper class that listens for movement on the track.
259 protected class TrackListener extends MouseAdapter
260 implements MouseMotionListener
262 /** The current X coordinate of the mouse. */
263 protected int currentMouseX;
265 /** The current Y coordinate of the mouse. */
266 protected int currentMouseY;
269 * The offset between the current mouse cursor and the current value of
270 * the scrollbar.
272 protected int offset;
275 * This method is called when the mouse is being dragged.
277 * @param e The MouseEvent given.
279 public void mouseDragged(MouseEvent e)
281 currentMouseX = e.getX();
282 currentMouseY = e.getY();
283 if (scrollbar.getValueIsAdjusting())
285 int value;
286 if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL)
287 value = valueForXPosition(currentMouseX) - offset;
288 else
289 value = valueForYPosition(currentMouseY) - offset;
291 scrollbar.setValue(value);
296 * This method is called when the mouse is moved.
298 * @param e The MouseEvent given.
300 public void mouseMoved(MouseEvent e)
302 // Not interested in where the mouse
303 // is unless it is being dragged.
307 * This method is called when the mouse is pressed. When it is pressed,
308 * the thumb should move in blocks towards the cursor.
310 * @param e The MouseEvent given.
312 public void mousePressed(MouseEvent e)
314 currentMouseX = e.getX();
315 currentMouseY = e.getY();
317 int value;
318 if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL)
319 value = valueForXPosition(currentMouseX);
320 else
321 value = valueForYPosition(currentMouseY);
323 if (! thumbRect.contains(e.getPoint()))
325 scrollTimer.stop();
326 scrollListener.setScrollByBlock(true);
327 if (value > scrollbar.getValue())
329 trackHighlight = INCREASE_HIGHLIGHT;
330 scrollListener.setDirection(POSITIVE_SCROLL);
332 else
334 trackHighlight = DECREASE_HIGHLIGHT;
335 scrollListener.setDirection(NEGATIVE_SCROLL);
337 scrollTimer.setDelay(100);
338 scrollTimer.start();
340 else
342 // We'd like to keep track of where the cursor
343 // is inside the thumb.
344 // This works because the scrollbar's value represents
345 // "lower" edge of the thumb. The value at which
346 // the cursor is at must be greater or equal
347 // to that value.
349 scrollListener.setScrollByBlock(false);
350 scrollbar.setValueIsAdjusting(true);
351 offset = value - scrollbar.getValue();
353 scrollbar.repaint();
357 * This method is called when the mouse is released. It should stop
358 * movement on the thumb
360 * @param e The MouseEvent given.
362 public void mouseReleased(MouseEvent e)
364 scrollTimer.stop();
365 scrollTimer.setDelay(300);
366 currentMouseX = e.getX();
367 currentMouseY = e.getY();
369 if (shouldScroll(POSITIVE_SCROLL))
370 scrollByBlock(POSITIVE_SCROLL);
371 else if (shouldScroll(NEGATIVE_SCROLL))
372 scrollByBlock(NEGATIVE_SCROLL);
374 trackHighlight = NO_HIGHLIGHT;
375 scrollListener.setScrollByBlock(false);
376 scrollbar.setValueIsAdjusting(true);
377 scrollbar.repaint();
381 * A helper method that decides whether we should keep scrolling in the
382 * given direction.
384 * @param direction The direction to check for.
386 * @return Whether the thumb should keep scrolling.
388 boolean shouldScroll(int direction)
390 int value;
391 if (scrollbar.getOrientation() == HORIZONTAL)
392 value = valueForXPosition(currentMouseX);
393 else
394 value = valueForYPosition(currentMouseY);
396 if (thumbRect.contains(currentMouseX, currentMouseY))
397 return false;
399 if (direction == POSITIVE_SCROLL)
400 return (value > scrollbar.getValue());
401 else
402 return (value < scrollbar.getValue());
406 /** The listener that listens to the JButtons. */
407 protected ArrowButtonListener buttonListener;
409 /** The listener that listens to the model. */
410 protected ModelListener modelListener;
412 /** The listener that listens to the scrollbar for property changes. */
413 protected PropertyChangeListener propertyChangeListener;
415 /** The listener that listens to the timer. */
416 protected ScrollListener scrollListener;
418 /** The listener that listens for MouseEvents on the track. */
419 protected TrackListener trackListener;
421 /** The JButton that decrements the scrollbar's value. */
422 protected JButton decrButton;
424 /** The JButton that increments the scrollbar's value. */
425 protected JButton incrButton;
427 /** The dimensions of the maximum thumb size. */
428 protected Dimension maximumThumbSize;
430 /** The dimensions of the minimum thumb size. */
431 protected Dimension minimumThumbSize;
433 /** The color of the thumb. */
434 protected Color thumbColor;
436 /** The outer shadow of the thumb. */
437 protected Color thumbDarkShadowColor;
439 /** The top and left edge color for the thumb. */
440 protected Color thumbHighlightColor;
442 /** The outer light shadow for the thumb. */
443 protected Color thumbLightShadowColor;
445 /** The color that is used when the mouse press occurs in the track. */
446 protected Color trackHighlightColor;
448 /** The color of the track. */
449 protected Color trackColor;
451 /** The size and position of the track. */
452 protected Rectangle trackRect;
454 /** The size and position of the thumb. */
455 protected Rectangle thumbRect;
457 /** Indicates that the decrease highlight should be painted. */
458 protected static final int DECREASE_HIGHLIGHT = 1;
460 /** Indicates that the increase highlight should be painted. */
461 protected static final int INCREASE_HIGHLIGHT = 2;
463 /** Indicates that no highlight should be painted. */
464 protected static final int NO_HIGHLIGHT = 0;
466 /** Indicates that the scrolling direction is positive. */
467 private static final int POSITIVE_SCROLL = 1;
469 /** Indicates that the scrolling direction is negative. */
470 private static final int NEGATIVE_SCROLL = -1;
472 /** The cached preferred size for the scrollbar. */
473 private transient Dimension preferredSize;
475 /** The current highlight status. */
476 protected int trackHighlight;
478 /** FIXME: Use this for something (presumably mouseDragged) */
479 protected boolean isDragging;
481 /** The timer used to move the thumb when the mouse is held. */
482 protected Timer scrollTimer;
484 /** The scrollbar this UI is acting for. */
485 protected JScrollBar scrollbar;
488 * This method adds a component to the layout.
490 * @param name The name to associate with the component that is added.
491 * @param child The Component to add.
493 public void addLayoutComponent(String name, Component child)
495 // You should not be adding stuff to this component.
496 // The contents are fixed.
500 * This method configures the scrollbar's colors. This can be done by
501 * looking up the standard colors from the Look and Feel defaults.
503 protected void configureScrollBarColors()
505 trackColor = UIManager.getColor("ScrollBar.track");
506 trackHighlightColor = UIManager.getColor("ScrollBar.trackHighlight");
507 thumbColor = UIManager.getColor("ScrollBar.thumb");
508 thumbHighlightColor = UIManager.getColor("ScrollBar.thumbHighlight");
509 thumbDarkShadowColor = UIManager.getColor("ScrollBar.thumbDarkShadow");
510 thumbLightShadowColor = UIManager.getColor("ScrollBar.thumbShadow");
514 * This method creates an ArrowButtonListener.
516 * @return A new ArrowButtonListener.
518 protected ArrowButtonListener createArrowButtonListener()
520 return new ArrowButtonListener();
524 * This method creates a new JButton with the appropriate icon for the
525 * orientation.
527 * @param orientation The orientation this JButton uses.
529 * @return The increase JButton.
531 protected JButton createIncreaseButton(int orientation)
533 return new BasicArrowButton(orientation);
537 * This method creates a new JButton with the appropriate icon for the
538 * orientation.
540 * @param orientation The orientation this JButton uses.
542 * @return The decrease JButton.
544 protected JButton createDecreaseButton(int orientation)
546 return new BasicArrowButton(orientation);
550 * This method creates a new ModelListener.
552 * @return A new ModelListener.
554 protected ModelListener createModelListener()
556 return new ModelListener();
560 * This method creates a new PropertyChangeListener.
562 * @return A new PropertyChangeListener.
564 protected PropertyChangeListener createPropertyChangeListener()
566 return new PropertyChangeHandler();
570 * This method creates a new ScrollListener.
572 * @return A new ScrollListener.
574 protected ScrollListener createScrollListener()
576 return new ScrollListener();
580 * This method creates a new TrackListener.
582 * @return A new TrackListener.
584 protected TrackListener createTrackListener()
586 return new TrackListener();
590 * This method returns a new BasicScrollBarUI.
592 * @param c The JComponent to create a UI for.
594 * @return A new BasicScrollBarUI.
596 public static ComponentUI createUI(JComponent c)
598 return new BasicScrollBarUI();
602 * This method returns the maximum size for this JComponent.
604 * @param c The JComponent to measure the maximum size for.
606 * @return The maximum size for the component.
608 public Dimension getMaximumSize(JComponent c)
610 return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
614 * This method returns the maximum thumb size.
616 * @return The maximum thumb size.
618 protected Dimension getMaximumThumbSize()
620 return maximumThumbSize;
624 * This method returns the minimum size for this JComponent.
626 * @param c The JComponent to measure the minimum size for.
628 * @return The minimum size for the component.
630 public Dimension getMinimumSize(JComponent c)
632 return getPreferredSize(c);
636 * This method returns the minimum thumb size.
638 * @return The minimum thumb size.
640 protected Dimension getMinimumThumbSize()
642 return minimumThumbSize;
646 * This method calculates the preferred size since calling
647 * getPreferredSize() returns a cached value.
648 * This is package-private to avoid an accessor method.
650 void calculatePreferredSize()
652 int height;
653 int width;
654 height = width = 0;
656 if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL)
658 width += incrButton.getPreferredSize().getWidth();
659 width += decrButton.getPreferredSize().getWidth();
660 width += 16;
661 height = UIManager.getInt("ScrollBar.width");
663 else
665 height += incrButton.getPreferredSize().getHeight();
666 height += decrButton.getPreferredSize().getHeight();
667 height += 16;
668 width = UIManager.getInt("ScrollBar.width");
671 Insets insets = scrollbar.getInsets();
673 height += insets.top + insets.bottom;
674 width += insets.left + insets.right;
676 preferredSize = new Dimension(width, height);
680 * This method returns a cached value of the preferredSize. The only
681 * restrictions are: If the scrollbar is horizontal, the height should be
682 * the maximum of the height of the JButtons and the minimum width of the
683 * thumb. For vertical scrollbars, the calculation is similar (swap width
684 * for height and vice versa).
686 * @param c The JComponent to measure.
688 * @return The preferredSize.
690 public Dimension getPreferredSize(JComponent c)
692 calculatePreferredSize();
693 return preferredSize;
697 * This method returns the thumb's bounds based on the current value of the
698 * scrollbar. This method updates the cached value and returns that.
700 * @return The thumb bounds.
702 protected Rectangle getThumbBounds()
704 return thumbRect;
708 * This method calculates the bounds of the track. This method updates the
709 * cached value and returns it.
711 * @return The track's bounds.
713 protected Rectangle getTrackBounds()
715 return trackRect;
719 * This method installs any addition Components that are a part of or
720 * related to this scrollbar.
722 protected void installComponents()
724 int orientation = scrollbar.getOrientation();
725 switch (orientation)
727 case (JScrollBar.HORIZONTAL):
728 incrButton = createIncreaseButton(EAST);
729 decrButton = createDecreaseButton(WEST);
730 break;
731 default:
732 incrButton = createIncreaseButton(SOUTH);
733 decrButton = createDecreaseButton(NORTH);
734 break;
737 if (incrButton != null)
738 scrollbar.add(incrButton);
739 if (decrButton != null)
740 scrollbar.add(decrButton);
744 * This method installs the defaults for the scrollbar specified by the
745 * Basic Look and Feel.
747 protected void installDefaults()
749 LookAndFeel.installColors(scrollbar, "ScrollBar.background",
750 "ScrollBar.foreground");
751 LookAndFeel.installBorder(scrollbar, "ScrollBar.border");
752 scrollbar.setOpaque(true);
753 scrollbar.setLayout(this);
755 thumbColor = UIManager.getColor("ScrollBar.thumb");
756 thumbDarkShadowColor = UIManager.getColor("ScrollBar.thumbDarkShadow");
757 thumbHighlightColor = UIManager.getColor("ScrollBar.thumbHighlight");
758 thumbLightShadowColor = UIManager.getColor("ScrollBar.thumbShadow");
760 maximumThumbSize = UIManager.getDimension("ScrollBar.maximumThumbSize");
761 minimumThumbSize = UIManager.getDimension("ScrollBar.minimumThumbSize");
765 * This method installs the keyboard actions for the scrollbar.
767 protected void installKeyboardActions()
768 throws NotImplementedException
770 // FIXME: implement.
774 * This method installs any listeners for the scrollbar. This method also
775 * installs listeners for things such as the JButtons and the timer.
777 protected void installListeners()
779 scrollListener = createScrollListener();
780 trackListener = createTrackListener();
781 buttonListener = createArrowButtonListener();
782 modelListener = createModelListener();
783 propertyChangeListener = createPropertyChangeListener();
785 scrollbar.addMouseMotionListener(trackListener);
786 scrollbar.addMouseListener(trackListener);
788 incrButton.addMouseListener(buttonListener);
789 decrButton.addMouseListener(buttonListener);
791 scrollbar.addPropertyChangeListener(propertyChangeListener);
792 scrollbar.getModel().addChangeListener(modelListener);
794 scrollTimer.addActionListener(scrollListener);
798 * This method installs the UI for the component. This can include setting
799 * up listeners, defaults, and components. This also includes initializing
800 * any data objects.
802 * @param c The JComponent to install.
804 public void installUI(JComponent c)
806 super.installUI(c);
807 if (c instanceof JScrollBar)
809 scrollbar = (JScrollBar) c;
811 trackRect = new Rectangle();
812 thumbRect = new Rectangle();
814 scrollTimer = new Timer(300, null);
816 installDefaults();
817 installComponents();
818 configureScrollBarColors();
819 installListeners();
821 calculatePreferredSize();
826 * This method lays out the scrollbar.
828 * @param scrollbarContainer The Container to layout.
830 public void layoutContainer(Container scrollbarContainer)
832 if (scrollbarContainer instanceof JScrollBar)
834 if (scrollbar.getOrientation() == SwingConstants.HORIZONTAL)
835 layoutHScrollbar((JScrollBar) scrollbarContainer);
836 else
837 layoutVScrollbar((JScrollBar) scrollbarContainer);
842 * This method lays out the scrollbar horizontally.
844 * @param sb The JScrollBar to layout.
846 protected void layoutHScrollbar(JScrollBar sb)
848 Rectangle vr = new Rectangle();
849 SwingUtilities.calculateInnerArea(scrollbar, vr);
851 Dimension incrDims = incrButton.getPreferredSize();
852 Dimension decrDims = decrButton.getPreferredSize();
854 // calculate and update the track bounds
855 SwingUtilities.calculateInnerArea(scrollbar, trackRect);
856 trackRect.width -= incrDims.getWidth();
857 trackRect.width -= decrDims.getWidth();
858 trackRect.x += decrDims.getWidth();
860 updateThumbRect();
862 decrButton.setBounds(vr.x, vr.y, decrDims.width, trackRect.height);
863 incrButton.setBounds(trackRect.x + trackRect.width, vr.y, incrDims.width,
864 trackRect.height);
868 * This method lays out the scrollbar vertically.
870 * @param sb The JScrollBar to layout.
872 protected void layoutVScrollbar(JScrollBar sb)
874 Rectangle vr = new Rectangle();
875 SwingUtilities.calculateInnerArea(scrollbar, vr);
877 Dimension incrDims = incrButton.getPreferredSize();
878 Dimension decrDims = decrButton.getPreferredSize();
880 // Update rectangles
881 SwingUtilities.calculateInnerArea(scrollbar, trackRect);
882 trackRect.height -= incrDims.getHeight();
883 trackRect.height -= decrDims.getHeight();
884 trackRect.y += decrDims.getHeight();
886 updateThumbRect();
888 decrButton.setBounds(vr.x, vr.y, trackRect.width, decrDims.height);
889 incrButton.setBounds(vr.x, trackRect.y + trackRect.height,
890 trackRect.width, incrDims.height);
894 * Updates the thumb rect.
896 void updateThumbRect()
898 int max = scrollbar.getMaximum();
899 int min = scrollbar.getMinimum();
900 int value = scrollbar.getValue();
901 int extent = scrollbar.getVisibleAmount();
902 if (max - extent <= min)
904 if (scrollbar.getOrientation() == JScrollBar.HORIZONTAL)
906 thumbRect.x = trackRect.x;
907 thumbRect.y = trackRect.y;
908 thumbRect.width = getMinimumThumbSize().width;
909 thumbRect.height = trackRect.height;
911 else
913 thumbRect.x = trackRect.x;
914 thumbRect.y = trackRect.y;
915 thumbRect.width = trackRect.width;
916 thumbRect.height = getMinimumThumbSize().height;
919 else
921 if (scrollbar.getOrientation() == JScrollBar.HORIZONTAL)
923 thumbRect.x = trackRect.x;
924 thumbRect.width = Math.max(extent * trackRect.width / (max - min),
925 getMinimumThumbSize().width);
926 int availableWidth = trackRect.width - thumbRect.width;
927 thumbRect.x += (value - min) * availableWidth / (max - min - extent);
928 thumbRect.y = trackRect.y;
929 thumbRect.height = trackRect.height;
931 else
933 thumbRect.x = trackRect.x;
934 thumbRect.height = Math.max(extent * trackRect.height / (max - min),
935 getMinimumThumbSize().height);
936 int availableHeight = trackRect.height - thumbRect.height;
937 thumbRect.y = trackRect.y
938 + (value - min) * availableHeight / (max - min - extent);
939 thumbRect.width = trackRect.width;
946 * This method returns the minimum size required for the layout.
948 * @param scrollbarContainer The Container that is laid out.
950 * @return The minimum size.
952 public Dimension minimumLayoutSize(Container scrollbarContainer)
954 return preferredLayoutSize(scrollbarContainer);
958 * This method is called when the component is painted.
960 * @param g The Graphics object to paint with.
961 * @param c The JComponent to paint.
963 public void paint(Graphics g, JComponent c)
965 paintTrack(g, c, getTrackBounds());
966 paintThumb(g, c, getThumbBounds());
968 if (trackHighlight == INCREASE_HIGHLIGHT)
969 paintIncreaseHighlight(g);
970 else if (trackHighlight == DECREASE_HIGHLIGHT)
971 paintDecreaseHighlight(g);
975 * This method is called when repainting and the mouse is pressed in the
976 * track. It paints the track below the thumb with the trackHighlight
977 * color.
979 * @param g The Graphics object to paint with.
981 protected void paintDecreaseHighlight(Graphics g)
983 Color saved = g.getColor();
985 g.setColor(trackHighlightColor);
986 if (scrollbar.getOrientation() == HORIZONTAL)
987 g.fillRect(trackRect.x, trackRect.y, thumbRect.x - trackRect.x,
988 trackRect.height);
989 else
990 g.fillRect(trackRect.x, trackRect.y, trackRect.width,
991 thumbRect.y - trackRect.y);
992 g.setColor(saved);
996 * This method is called when repainting and the mouse is pressed in the
997 * track. It paints the track above the thumb with the trackHighlight
998 * color.
1000 * @param g The Graphics objet to paint with.
1002 protected void paintIncreaseHighlight(Graphics g)
1004 Color saved = g.getColor();
1006 g.setColor(trackHighlightColor);
1007 if (scrollbar.getOrientation() == HORIZONTAL)
1008 g.fillRect(thumbRect.x + thumbRect.width, trackRect.y,
1009 trackRect.x + trackRect.width - thumbRect.x - thumbRect.width,
1010 trackRect.height);
1011 else
1012 g.fillRect(trackRect.x, thumbRect.y + thumbRect.height, trackRect.width,
1013 trackRect.y + trackRect.height - thumbRect.y
1014 - thumbRect.height);
1015 g.setColor(saved);
1019 * This method paints the thumb.
1021 * @param g The Graphics object to paint with.
1022 * @param c The Component that is being painted.
1023 * @param thumbBounds The thumb bounds.
1025 protected void paintThumb(Graphics g, JComponent c, Rectangle thumbBounds)
1027 g.setColor(thumbColor);
1028 g.fillRect(thumbBounds.x, thumbBounds.y, thumbBounds.width,
1029 thumbBounds.height);
1031 BasicGraphicsUtils.drawBezel(g, thumbBounds.x, thumbBounds.y,
1032 thumbBounds.width, thumbBounds.height,
1033 false, false, thumbDarkShadowColor,
1034 thumbDarkShadowColor, thumbHighlightColor,
1035 thumbHighlightColor);
1039 * This method paints the track.
1041 * @param g The Graphics object to paint with.
1042 * @param c The JComponent being painted.
1043 * @param trackBounds The track's bounds.
1045 protected void paintTrack(Graphics g, JComponent c, Rectangle trackBounds)
1047 Color saved = g.getColor();
1048 g.setColor(trackColor);
1049 g.fill3DRect(trackBounds.x, trackBounds.y, trackBounds.width,
1050 trackBounds.height, false);
1051 g.setColor(saved);
1055 * This method returns the preferred size for the layout.
1057 * @param scrollbarContainer The Container to find a size for.
1059 * @return The preferred size for the layout.
1061 public Dimension preferredLayoutSize(Container scrollbarContainer)
1063 if (scrollbarContainer instanceof JComponent)
1064 return getPreferredSize((JComponent) scrollbarContainer);
1065 else
1066 return null;
1070 * This method removes a child component from the layout.
1072 * @param child The child to remove.
1074 public void removeLayoutComponent(Component child)
1076 // You should not be removing stuff from this component.
1080 * The method scrolls the thumb by a block in the direction specified.
1082 * @param direction The direction to scroll.
1084 protected void scrollByBlock(int direction)
1086 scrollbar.setValue(scrollbar.getValue()
1087 + scrollbar.getBlockIncrement(direction));
1091 * The method scrolls the thumb by a unit in the direction specified.
1093 * @param direction The direction to scroll.
1095 protected void scrollByUnit(int direction)
1097 scrollbar.setValue(scrollbar.getValue()
1098 + scrollbar.getUnitIncrement(direction));
1102 * This method sets the thumb's bounds.
1104 * @param x The X position of the thumb.
1105 * @param y The Y position of the thumb.
1106 * @param width The width of the thumb.
1107 * @param height The height of the thumb.
1109 protected void setThumbBounds(int x, int y, int width, int height)
1111 thumbRect.x = x;
1112 thumbRect.y = y;
1113 thumbRect.width = width;
1114 thumbRect.height = height;
1118 * This method uninstalls any components that are a part of or related to
1119 * this scrollbar.
1121 protected void uninstallComponents()
1123 if (incrButton != null)
1124 scrollbar.remove(incrButton);
1125 if (decrButton != null)
1126 scrollbar.remove(decrButton);
1130 * This method uninstalls any defaults that this scrollbar acquired from the
1131 * Basic Look and Feel defaults.
1133 protected void uninstallDefaults()
1135 scrollbar.setForeground(null);
1136 scrollbar.setBackground(null);
1137 LookAndFeel.uninstallBorder(scrollbar);
1138 incrButton = null;
1139 decrButton = null;
1143 * This method uninstalls any keyboard actions this scrollbar acquired
1144 * during install.
1146 protected void uninstallKeyboardActions()
1147 throws NotImplementedException
1149 // FIXME: implement.
1153 * This method uninstalls any listeners that were registered during install.
1155 protected void uninstallListeners()
1157 if (scrollTimer != null)
1158 scrollTimer.removeActionListener(scrollListener);
1160 if (scrollbar != null)
1162 scrollbar.getModel().removeChangeListener(modelListener);
1163 scrollbar.removePropertyChangeListener(propertyChangeListener);
1164 scrollbar.removeMouseListener(trackListener);
1165 scrollbar.removeMouseMotionListener(trackListener);
1168 if (decrButton != null)
1169 decrButton.removeMouseListener(buttonListener);
1170 if (incrButton != null)
1171 incrButton.removeMouseListener(buttonListener);
1173 propertyChangeListener = null;
1174 modelListener = null;
1175 buttonListener = null;
1176 trackListener = null;
1177 scrollListener = null;
1181 * This method uninstalls the UI. This includes removing any defaults,
1182 * listeners, and components that this UI may have initialized. It also
1183 * nulls any instance data.
1185 * @param c The Component to uninstall for.
1187 public void uninstallUI(JComponent c)
1189 uninstallListeners();
1190 uninstallDefaults();
1191 uninstallComponents();
1193 scrollTimer = null;
1195 thumbRect = null;
1196 trackRect = null;
1198 trackColor = null;
1199 trackHighlightColor = null;
1200 thumbColor = null;
1201 thumbHighlightColor = null;
1202 thumbDarkShadowColor = null;
1203 thumbLightShadowColor = null;
1205 scrollbar = null;
1209 * This method returns the value in the scrollbar's range given the y
1210 * coordinate. If the value is out of range, it will return the closest
1211 * legal value.
1212 * This is package-private to avoid an accessor method.
1214 * @param yPos The y coordinate to calculate a value for.
1216 * @return The value for the y coordinate.
1218 int valueForYPosition(int yPos)
1220 int min = scrollbar.getMinimum();
1221 int max = scrollbar.getMaximum();
1222 int len = trackRect.height;
1224 int value;
1226 // If the length is 0, you shouldn't be able to even see where the thumb is.
1227 // This really shouldn't ever happen, but just in case, we'll return the middle.
1228 if (len == 0)
1229 return ((max - min) / 2);
1231 value = ((yPos - trackRect.y) * (max - min) / len + min);
1233 // If this isn't a legal value, then we'll have to move to one now.
1234 if (value > max)
1235 value = max;
1236 else if (value < min)
1237 value = min;
1238 return value;
1242 * This method returns the value in the scrollbar's range given the x
1243 * coordinate. If the value is out of range, it will return the closest
1244 * legal value.
1245 * This is package-private to avoid an accessor method.
1247 * @param xPos The x coordinate to calculate a value for.
1249 * @return The value for the x coordinate.
1251 int valueForXPosition(int xPos)
1253 int min = scrollbar.getMinimum();
1254 int max = scrollbar.getMaximum();
1255 int len = trackRect.width;
1257 int value;
1259 // If the length is 0, you shouldn't be able to even see where the slider is.
1260 // This really shouldn't ever happen, but just in case, we'll return the middle.
1261 if (len == 0)
1262 return ((max - min) / 2);
1264 value = ((xPos - trackRect.x) * (max - min) / len + min);
1266 // If this isn't a legal value, then we'll have to move to one now.
1267 if (value > max)
1268 value = max;
1269 else if (value < min)
1270 value = min;
1271 return value;