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