Source Code Cross Referenced for BasicScrollBarUI.java in  » 6.0-JDK-Core » swing » javax » swing » plaf » basic » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » swing » javax.swing.plaf.basic 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001        /*
0002         * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
0003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004         *
0005         * This code is free software; you can redistribute it and/or modify it
0006         * under the terms of the GNU General Public License version 2 only, as
0007         * published by the Free Software Foundation.  Sun designates this
0008         * particular file as subject to the "Classpath" exception as provided
0009         * by Sun in the LICENSE file that accompanied this code.
0010         *
0011         * This code is distributed in the hope that it will be useful, but WITHOUT
0012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014         * version 2 for more details (a copy is included in the LICENSE file that
0015         * accompanied this code).
0016         *
0017         * You should have received a copy of the GNU General Public License version
0018         * 2 along with this work; if not, write to the Free Software Foundation,
0019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020         *
0021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022         * CA 95054 USA or visit www.sun.com if you need additional information or
0023         * have any questions.
0024         */
0025        package javax.swing.plaf.basic;
0026
0027        import sun.swing.DefaultLookup;
0028        import sun.swing.UIAction;
0029
0030        import java.awt.*;
0031        import java.awt.event.*;
0032
0033        import java.beans.*;
0034
0035        import javax.swing.*;
0036        import javax.swing.event.*;
0037        import javax.swing.plaf.*;
0038
0039        /**
0040         * Implementation of ScrollBarUI for the Basic Look and Feel
0041         *
0042         * @version 1.94 05/05/07
0043         * @author Rich Schiavi
0044         * @author David Kloba
0045         * @author Hans Muller
0046         */
0047        public class BasicScrollBarUI extends ScrollBarUI implements 
0048                LayoutManager, SwingConstants {
0049            private static final int POSITIVE_SCROLL = 1;
0050            private static final int NEGATIVE_SCROLL = -1;
0051
0052            private static final int MIN_SCROLL = 2;
0053            private static final int MAX_SCROLL = 3;
0054
0055            // NOTE: DO NOT use this field directly, SynthScrollBarUI assumes you'll
0056            // call getMinimumThumbSize to access it.
0057            protected Dimension minimumThumbSize;
0058            protected Dimension maximumThumbSize;
0059
0060            protected Color thumbHighlightColor;
0061            protected Color thumbLightShadowColor;
0062            protected Color thumbDarkShadowColor;
0063            protected Color thumbColor;
0064            protected Color trackColor;
0065            protected Color trackHighlightColor;
0066
0067            protected JScrollBar scrollbar;
0068            protected JButton incrButton;
0069            protected JButton decrButton;
0070            protected boolean isDragging;
0071            protected TrackListener trackListener;
0072            protected ArrowButtonListener buttonListener;
0073            protected ModelListener modelListener;
0074
0075            protected Rectangle thumbRect;
0076            protected Rectangle trackRect;
0077
0078            protected int trackHighlight;
0079
0080            protected static final int NO_HIGHLIGHT = 0;
0081            protected static final int DECREASE_HIGHLIGHT = 1;
0082            protected static final int INCREASE_HIGHLIGHT = 2;
0083
0084            protected ScrollListener scrollListener;
0085            protected PropertyChangeListener propertyChangeListener;
0086            protected Timer scrollTimer;
0087
0088            private final static int scrollSpeedThrottle = 60; // delay in milli seconds
0089
0090            /** True indicates a middle click will absolutely position the
0091             * scrollbar. */
0092            private boolean supportsAbsolutePositioning;
0093
0094            /** Hint as to what width (when vertical) or height (when horizontal)
0095             * should be.
0096             */
0097            private int scrollBarWidth;
0098
0099            private Handler handler;
0100
0101            private boolean thumbActive;
0102
0103            /**
0104             * Determine whether scrollbar layout should use cached value or adjusted
0105             * value returned by scrollbar's <code>getValue</code>.
0106             */
0107            private boolean useCachedValue = false;
0108            /**
0109             * The scrollbar value is cached to save real value if the view is adjusted.
0110             */
0111            private int scrollBarValue;
0112
0113            static void loadActionMap(LazyActionMap map) {
0114                map.put(new Actions(Actions.POSITIVE_UNIT_INCREMENT));
0115                map.put(new Actions(Actions.POSITIVE_BLOCK_INCREMENT));
0116                map.put(new Actions(Actions.NEGATIVE_UNIT_INCREMENT));
0117                map.put(new Actions(Actions.NEGATIVE_BLOCK_INCREMENT));
0118                map.put(new Actions(Actions.MIN_SCROLL));
0119                map.put(new Actions(Actions.MAX_SCROLL));
0120            }
0121
0122            public static ComponentUI createUI(JComponent c) {
0123                return new BasicScrollBarUI();
0124            }
0125
0126            protected void configureScrollBarColors() {
0127                LookAndFeel.installColors(scrollbar, "ScrollBar.background",
0128                        "ScrollBar.foreground");
0129                thumbHighlightColor = UIManager
0130                        .getColor("ScrollBar.thumbHighlight");
0131                thumbLightShadowColor = UIManager
0132                        .getColor("ScrollBar.thumbShadow");
0133                thumbDarkShadowColor = UIManager
0134                        .getColor("ScrollBar.thumbDarkShadow");
0135                thumbColor = UIManager.getColor("ScrollBar.thumb");
0136                trackColor = UIManager.getColor("ScrollBar.track");
0137                trackHighlightColor = UIManager
0138                        .getColor("ScrollBar.trackHighlight");
0139            }
0140
0141            public void installUI(JComponent c) {
0142                scrollbar = (JScrollBar) c;
0143                thumbRect = new Rectangle(0, 0, 0, 0);
0144                trackRect = new Rectangle(0, 0, 0, 0);
0145                installDefaults();
0146                installComponents();
0147                installListeners();
0148                installKeyboardActions();
0149            }
0150
0151            public void uninstallUI(JComponent c) {
0152                scrollbar = (JScrollBar) c;
0153                uninstallListeners();
0154                uninstallDefaults();
0155                uninstallComponents();
0156                uninstallKeyboardActions();
0157                thumbRect = null;
0158                scrollbar = null;
0159                incrButton = null;
0160                decrButton = null;
0161            }
0162
0163            protected void installDefaults() {
0164                scrollBarWidth = UIManager.getInt("ScrollBar.width");
0165                if (scrollBarWidth <= 0) {
0166                    scrollBarWidth = 16;
0167                }
0168                minimumThumbSize = (Dimension) UIManager
0169                        .get("ScrollBar.minimumThumbSize");
0170                maximumThumbSize = (Dimension) UIManager
0171                        .get("ScrollBar.maximumThumbSize");
0172
0173                Boolean absB = (Boolean) UIManager
0174                        .get("ScrollBar.allowsAbsolutePositioning");
0175                supportsAbsolutePositioning = (absB != null) ? absB
0176                        .booleanValue() : false;
0177
0178                trackHighlight = NO_HIGHLIGHT;
0179                if (scrollbar.getLayout() == null
0180                        || (scrollbar.getLayout() instanceof  UIResource)) {
0181                    scrollbar.setLayout(this );
0182                }
0183                configureScrollBarColors();
0184                LookAndFeel.installBorder(scrollbar, "ScrollBar.border");
0185                LookAndFeel.installProperty(scrollbar, "opaque", Boolean.TRUE);
0186
0187                scrollBarValue = scrollbar.getValue();
0188            }
0189
0190            protected void installComponents() {
0191                switch (scrollbar.getOrientation()) {
0192                case JScrollBar.VERTICAL:
0193                    incrButton = createIncreaseButton(SOUTH);
0194                    decrButton = createDecreaseButton(NORTH);
0195                    break;
0196
0197                case JScrollBar.HORIZONTAL:
0198                    if (scrollbar.getComponentOrientation().isLeftToRight()) {
0199                        incrButton = createIncreaseButton(EAST);
0200                        decrButton = createDecreaseButton(WEST);
0201                    } else {
0202                        incrButton = createIncreaseButton(WEST);
0203                        decrButton = createDecreaseButton(EAST);
0204                    }
0205                    break;
0206                }
0207                scrollbar.add(incrButton);
0208                scrollbar.add(decrButton);
0209                // Force the children's enabled state to be updated.
0210                scrollbar.setEnabled(scrollbar.isEnabled());
0211            }
0212
0213            protected void uninstallComponents() {
0214                scrollbar.remove(incrButton);
0215                scrollbar.remove(decrButton);
0216            }
0217
0218            protected void installListeners() {
0219                trackListener = createTrackListener();
0220                buttonListener = createArrowButtonListener();
0221                modelListener = createModelListener();
0222                propertyChangeListener = createPropertyChangeListener();
0223
0224                scrollbar.addMouseListener(trackListener);
0225                scrollbar.addMouseMotionListener(trackListener);
0226                scrollbar.getModel().addChangeListener(modelListener);
0227                scrollbar.addPropertyChangeListener(propertyChangeListener);
0228                scrollbar.addFocusListener(getHandler());
0229
0230                if (incrButton != null) {
0231                    incrButton.addMouseListener(buttonListener);
0232                }
0233                if (decrButton != null) {
0234                    decrButton.addMouseListener(buttonListener);
0235                }
0236
0237                scrollListener = createScrollListener();
0238                scrollTimer = new Timer(scrollSpeedThrottle, scrollListener);
0239                scrollTimer.setInitialDelay(300); // default InitialDelay?
0240            }
0241
0242            protected void installKeyboardActions() {
0243                LazyActionMap.installLazyActionMap(scrollbar,
0244                        BasicScrollBarUI.class, "ScrollBar.actionMap");
0245
0246                InputMap inputMap = getInputMap(JComponent.WHEN_FOCUSED);
0247                SwingUtilities.replaceUIInputMap(scrollbar,
0248                        JComponent.WHEN_FOCUSED, inputMap);
0249                inputMap = getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
0250                SwingUtilities
0251                        .replaceUIInputMap(scrollbar,
0252                                JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT,
0253                                inputMap);
0254            }
0255
0256            protected void uninstallKeyboardActions() {
0257                SwingUtilities.replaceUIInputMap(scrollbar,
0258                        JComponent.WHEN_FOCUSED, null);
0259                SwingUtilities.replaceUIActionMap(scrollbar, null);
0260            }
0261
0262            private InputMap getInputMap(int condition) {
0263                if (condition == JComponent.WHEN_FOCUSED) {
0264                    InputMap keyMap = (InputMap) DefaultLookup.get(scrollbar,
0265                            this , "ScrollBar.focusInputMap");
0266                    InputMap rtlKeyMap;
0267
0268                    if (scrollbar.getComponentOrientation().isLeftToRight()
0269                            || ((rtlKeyMap = (InputMap) DefaultLookup.get(
0270                                    scrollbar, this ,
0271                                    "ScrollBar.focusInputMap.RightToLeft")) == null)) {
0272                        return keyMap;
0273                    } else {
0274                        rtlKeyMap.setParent(keyMap);
0275                        return rtlKeyMap;
0276                    }
0277                } else if (condition == JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) {
0278                    InputMap keyMap = (InputMap) DefaultLookup.get(scrollbar,
0279                            this , "ScrollBar.ancestorInputMap");
0280                    InputMap rtlKeyMap;
0281
0282                    if (scrollbar.getComponentOrientation().isLeftToRight()
0283                            || ((rtlKeyMap = (InputMap) DefaultLookup.get(
0284                                    scrollbar, this ,
0285                                    "ScrollBar.ancestorInputMap.RightToLeft")) == null)) {
0286                        return keyMap;
0287                    } else {
0288                        rtlKeyMap.setParent(keyMap);
0289                        return rtlKeyMap;
0290                    }
0291                }
0292                return null;
0293            }
0294
0295            protected void uninstallListeners() {
0296                scrollTimer.stop();
0297                scrollTimer = null;
0298
0299                if (decrButton != null) {
0300                    decrButton.removeMouseListener(buttonListener);
0301                }
0302                if (incrButton != null) {
0303                    incrButton.removeMouseListener(buttonListener);
0304                }
0305
0306                scrollbar.getModel().removeChangeListener(modelListener);
0307                scrollbar.removeMouseListener(trackListener);
0308                scrollbar.removeMouseMotionListener(trackListener);
0309                scrollbar.removePropertyChangeListener(propertyChangeListener);
0310                scrollbar.removeFocusListener(getHandler());
0311                handler = null;
0312            }
0313
0314            protected void uninstallDefaults() {
0315                LookAndFeel.uninstallBorder(scrollbar);
0316                if (scrollbar.getLayout() == this ) {
0317                    scrollbar.setLayout(null);
0318                }
0319            }
0320
0321            private Handler getHandler() {
0322                if (handler == null) {
0323                    handler = new Handler();
0324                }
0325                return handler;
0326            }
0327
0328            protected TrackListener createTrackListener() {
0329                return new TrackListener();
0330            }
0331
0332            protected ArrowButtonListener createArrowButtonListener() {
0333                return new ArrowButtonListener();
0334            }
0335
0336            protected ModelListener createModelListener() {
0337                return new ModelListener();
0338            }
0339
0340            protected ScrollListener createScrollListener() {
0341                return new ScrollListener();
0342            }
0343
0344            protected PropertyChangeListener createPropertyChangeListener() {
0345                return getHandler();
0346            }
0347
0348            private void updateThumbState(int x, int y) {
0349                Rectangle rect = getThumbBounds();
0350
0351                setThumbRollover(rect.contains(x, y));
0352            }
0353
0354            /**
0355             * Sets whether or not the mouse is currently over the thumb.
0356             *
0357             * @param active True indicates the thumb is currently active.
0358             * @since 1.5
0359             */
0360            protected void setThumbRollover(boolean active) {
0361                if (thumbActive != active) {
0362                    thumbActive = active;
0363                    scrollbar.repaint(getThumbBounds());
0364                }
0365            }
0366
0367            /**
0368             * Returns true if the mouse is currently over the thumb.
0369             *
0370             * @return true if the thumb is currently active
0371             * @since 1.5
0372             */
0373            public boolean isThumbRollover() {
0374                return thumbActive;
0375            }
0376
0377            public void paint(Graphics g, JComponent c) {
0378                paintTrack(g, c, getTrackBounds());
0379                Rectangle thumbBounds = getThumbBounds();
0380                if (thumbBounds.intersects(g.getClipBounds())) {
0381                    paintThumb(g, c, thumbBounds);
0382                }
0383            }
0384
0385            /**
0386             * A vertical scrollbar's preferred width is the maximum of 
0387             * preferred widths of the (non <code>null</code>)
0388             * increment/decrement buttons,
0389             * and the minimum width of the thumb. The preferred height is the 
0390             * sum of the preferred heights of the same parts.  The basis for 
0391             * the preferred size of a horizontal scrollbar is similar. 
0392             * <p>
0393             * The <code>preferredSize</code> is only computed once, subsequent
0394             * calls to this method just return a cached size.
0395             * 
0396             * @param c the <code>JScrollBar</code> that's delegating this method to us
0397             * @return the preferred size of a Basic JScrollBar
0398             * @see #getMaximumSize
0399             * @see #getMinimumSize
0400             */
0401            public Dimension getPreferredSize(JComponent c) {
0402                return (scrollbar.getOrientation() == JScrollBar.VERTICAL) ? new Dimension(
0403                        scrollBarWidth, 48)
0404                        : new Dimension(48, scrollBarWidth);
0405            }
0406
0407            /**
0408             * @param c The JScrollBar that's delegating this method to us.
0409             * @return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
0410             * @see #getMinimumSize
0411             * @see #getPreferredSize
0412             */
0413            public Dimension getMaximumSize(JComponent c) {
0414                return new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE);
0415            }
0416
0417            protected JButton createDecreaseButton(int orientation) {
0418                return new BasicArrowButton(orientation, UIManager
0419                        .getColor("ScrollBar.thumb"), UIManager
0420                        .getColor("ScrollBar.thumbShadow"), UIManager
0421                        .getColor("ScrollBar.thumbDarkShadow"), UIManager
0422                        .getColor("ScrollBar.thumbHighlight"));
0423            }
0424
0425            protected JButton createIncreaseButton(int orientation) {
0426                return new BasicArrowButton(orientation, UIManager
0427                        .getColor("ScrollBar.thumb"), UIManager
0428                        .getColor("ScrollBar.thumbShadow"), UIManager
0429                        .getColor("ScrollBar.thumbDarkShadow"), UIManager
0430                        .getColor("ScrollBar.thumbHighlight"));
0431            }
0432
0433            protected void paintDecreaseHighlight(Graphics g) {
0434                Insets insets = scrollbar.getInsets();
0435                Rectangle thumbR = getThumbBounds();
0436                g.setColor(trackHighlightColor);
0437
0438                if (scrollbar.getOrientation() == JScrollBar.VERTICAL) {
0439                    int x = insets.left;
0440                    int y = decrButton.getY() + decrButton.getHeight();
0441                    int w = scrollbar.getWidth() - (insets.left + insets.right);
0442                    int h = thumbR.y - y;
0443                    g.fillRect(x, y, w, h);
0444                } else {
0445                    int x, w;
0446                    if (scrollbar.getComponentOrientation().isLeftToRight()) {
0447                        x = decrButton.getX() + decrButton.getWidth();
0448                        w = thumbR.x - x;
0449                    } else {
0450                        x = thumbR.x + thumbR.width;
0451                        w = decrButton.getX() - x;
0452                    }
0453                    int y = insets.top;
0454                    int h = scrollbar.getHeight()
0455                            - (insets.top + insets.bottom);
0456                    g.fillRect(x, y, w, h);
0457                }
0458            }
0459
0460            protected void paintIncreaseHighlight(Graphics g) {
0461                Insets insets = scrollbar.getInsets();
0462                Rectangle thumbR = getThumbBounds();
0463                g.setColor(trackHighlightColor);
0464
0465                if (scrollbar.getOrientation() == JScrollBar.VERTICAL) {
0466                    int x = insets.left;
0467                    int y = thumbR.y + thumbR.height;
0468                    int w = scrollbar.getWidth() - (insets.left + insets.right);
0469                    int h = incrButton.getY() - y;
0470                    g.fillRect(x, y, w, h);
0471                } else {
0472                    int x, w;
0473                    if (scrollbar.getComponentOrientation().isLeftToRight()) {
0474                        x = thumbR.x + thumbR.width;
0475                        w = incrButton.getX() - x;
0476                    } else {
0477                        x = incrButton.getX() + incrButton.getWidth();
0478                        w = thumbR.x - x;
0479                    }
0480                    int y = insets.top;
0481                    int h = scrollbar.getHeight()
0482                            - (insets.top + insets.bottom);
0483                    g.fillRect(x, y, w, h);
0484                }
0485            }
0486
0487            protected void paintTrack(Graphics g, JComponent c,
0488                    Rectangle trackBounds) {
0489                g.setColor(trackColor);
0490                g.fillRect(trackBounds.x, trackBounds.y, trackBounds.width,
0491                        trackBounds.height);
0492
0493                if (trackHighlight == DECREASE_HIGHLIGHT) {
0494                    paintDecreaseHighlight(g);
0495                } else if (trackHighlight == INCREASE_HIGHLIGHT) {
0496                    paintIncreaseHighlight(g);
0497                }
0498            }
0499
0500            protected void paintThumb(Graphics g, JComponent c,
0501                    Rectangle thumbBounds) {
0502                if (thumbBounds.isEmpty() || !scrollbar.isEnabled()) {
0503                    return;
0504                }
0505
0506                int w = thumbBounds.width;
0507                int h = thumbBounds.height;
0508
0509                g.translate(thumbBounds.x, thumbBounds.y);
0510
0511                g.setColor(thumbDarkShadowColor);
0512                g.drawRect(0, 0, w - 1, h - 1);
0513                g.setColor(thumbColor);
0514                g.fillRect(0, 0, w - 1, h - 1);
0515
0516                g.setColor(thumbHighlightColor);
0517                g.drawLine(1, 1, 1, h - 2);
0518                g.drawLine(2, 1, w - 3, 1);
0519
0520                g.setColor(thumbLightShadowColor);
0521                g.drawLine(2, h - 2, w - 2, h - 2);
0522                g.drawLine(w - 2, 1, w - 2, h - 3);
0523
0524                g.translate(-thumbBounds.x, -thumbBounds.y);
0525            }
0526
0527            /** 
0528             * Return the smallest acceptable size for the thumb.  If the scrollbar
0529             * becomes so small that this size isn't available, the thumb will be
0530             * hidden.  
0531             * <p>
0532             * <b>Warning </b>: the value returned by this method should not be
0533             * be modified, it's a shared static constant.
0534             *
0535             * @return The smallest acceptable size for the thumb.
0536             * @see #getMaximumThumbSize
0537             */
0538            protected Dimension getMinimumThumbSize() {
0539                return minimumThumbSize;
0540            }
0541
0542            /** 
0543             * Return the largest acceptable size for the thumb.  To create a fixed 
0544             * size thumb one make this method and <code>getMinimumThumbSize</code> 
0545             * return the same value.
0546             * <p>
0547             * <b>Warning </b>: the value returned by this method should not be
0548             * be modified, it's a shared static constant.
0549             *
0550             * @return The largest acceptable size for the thumb.
0551             * @see #getMinimumThumbSize
0552             */
0553            protected Dimension getMaximumThumbSize() {
0554                return maximumThumbSize;
0555            }
0556
0557            /*
0558             * LayoutManager Implementation
0559             */
0560
0561            public void addLayoutComponent(String name, Component child) {
0562            }
0563
0564            public void removeLayoutComponent(Component child) {
0565            }
0566
0567            public Dimension preferredLayoutSize(Container scrollbarContainer) {
0568                return getPreferredSize((JComponent) scrollbarContainer);
0569            }
0570
0571            public Dimension minimumLayoutSize(Container scrollbarContainer) {
0572                return getMinimumSize((JComponent) scrollbarContainer);
0573            }
0574
0575            private int getValue(JScrollBar sb) {
0576                return (useCachedValue) ? scrollBarValue : sb.getValue();
0577            }
0578
0579            protected void layoutVScrollbar(JScrollBar sb) {
0580                Dimension sbSize = sb.getSize();
0581                Insets sbInsets = sb.getInsets();
0582
0583                /*
0584                 * Width and left edge of the buttons and thumb.
0585                 */
0586                int itemW = sbSize.width - (sbInsets.left + sbInsets.right);
0587                int itemX = sbInsets.left;
0588
0589                /* Nominal locations of the buttons, assuming their preferred
0590                 * size will fit.
0591                 */
0592                boolean squareButtons = DefaultLookup.getBoolean(scrollbar,
0593                        this , "ScrollBar.squareButtons", false);
0594                int decrButtonH = squareButtons ? itemW : decrButton
0595                        .getPreferredSize().height;
0596                int decrButtonY = sbInsets.top;
0597
0598                int incrButtonH = squareButtons ? itemW : incrButton
0599                        .getPreferredSize().height;
0600                int incrButtonY = sbSize.height
0601                        - (sbInsets.bottom + incrButtonH);
0602
0603                /* The thumb must fit within the height left over after we
0604                 * subtract the preferredSize of the buttons and the insets.
0605                 */
0606                int sbInsetsH = sbInsets.top + sbInsets.bottom;
0607                int sbButtonsH = decrButtonH + incrButtonH;
0608                float trackH = sbSize.height - (sbInsetsH + sbButtonsH);
0609
0610                /* Compute the height and origin of the thumb.   The case
0611                 * where the thumb is at the bottom edge is handled specially 
0612                 * to avoid numerical problems in computing thumbY.  Enforce
0613                 * the thumbs min/max dimensions.  If the thumb doesn't
0614                 * fit in the track (trackH) we'll hide it later.
0615                 */
0616                float min = sb.getMinimum();
0617                float extent = sb.getVisibleAmount();
0618                float range = sb.getMaximum() - min;
0619                float value = getValue(sb);
0620
0621                int thumbH = (range <= 0) ? getMaximumThumbSize().height
0622                        : (int) (trackH * (extent / range));
0623                thumbH = Math.max(thumbH, getMinimumThumbSize().height);
0624                thumbH = Math.min(thumbH, getMaximumThumbSize().height);
0625
0626                int thumbY = incrButtonY - thumbH;
0627                if (value < (sb.getMaximum() - sb.getVisibleAmount())) {
0628                    float thumbRange = trackH - thumbH;
0629                    thumbY = (int) (0.5f + (thumbRange * ((value - min) / (range - extent))));
0630                    thumbY += decrButtonY + decrButtonH;
0631                }
0632
0633                /* If the buttons don't fit, allocate half of the available 
0634                 * space to each and move the lower one (incrButton) down.
0635                 */
0636                int sbAvailButtonH = (sbSize.height - sbInsetsH);
0637                if (sbAvailButtonH < sbButtonsH) {
0638                    incrButtonH = decrButtonH = sbAvailButtonH / 2;
0639                    incrButtonY = sbSize.height
0640                            - (sbInsets.bottom + incrButtonH);
0641                }
0642                decrButton.setBounds(itemX, decrButtonY, itemW, decrButtonH);
0643                incrButton.setBounds(itemX, incrButtonY, itemW, incrButtonH);
0644
0645                /* Update the trackRect field.
0646                 */
0647                int itrackY = decrButtonY + decrButtonH;
0648                int itrackH = incrButtonY - itrackY;
0649                trackRect.setBounds(itemX, itrackY, itemW, itrackH);
0650
0651                /* If the thumb isn't going to fit, zero it's bounds.  Otherwise
0652                 * make sure it fits between the buttons.  Note that setting the
0653                 * thumbs bounds will cause a repaint.
0654                 */
0655                if (thumbH >= (int) trackH) {
0656                    if (UIManager.getBoolean("ScrollBar.alwaysShowThumb")) {
0657                        // This is used primarily for GTK L&F, which expands the
0658                        // thumb to fit the track when it would otherwise be hidden.
0659                        setThumbBounds(itemX, itrackY, itemW, itrackH);
0660                    } else {
0661                        // Other L&F's simply hide the thumb in this case.
0662                        setThumbBounds(0, 0, 0, 0);
0663                    }
0664                } else {
0665                    if ((thumbY + thumbH) > incrButtonY) {
0666                        thumbY = incrButtonY - thumbH;
0667                    }
0668                    if (thumbY < (decrButtonY + decrButtonH)) {
0669                        thumbY = decrButtonY + decrButtonH + 1;
0670                    }
0671                    setThumbBounds(itemX, thumbY, itemW, thumbH);
0672                }
0673            }
0674
0675            protected void layoutHScrollbar(JScrollBar sb) {
0676                Dimension sbSize = sb.getSize();
0677                Insets sbInsets = sb.getInsets();
0678
0679                /* Height and top edge of the buttons and thumb.
0680                 */
0681                int itemH = sbSize.height - (sbInsets.top + sbInsets.bottom);
0682                int itemY = sbInsets.top;
0683
0684                boolean ltr = sb.getComponentOrientation().isLeftToRight();
0685
0686                /* Nominal locations of the buttons, assuming their preferred
0687                 * size will fit.
0688                 */
0689                boolean squareButtons = DefaultLookup.getBoolean(scrollbar,
0690                        this , "ScrollBar.squareButtons", false);
0691                int leftButtonW = squareButtons ? itemH : decrButton
0692                        .getPreferredSize().width;
0693                int rightButtonW = squareButtons ? itemH : incrButton
0694                        .getPreferredSize().width;
0695                if (!ltr) {
0696                    int temp = leftButtonW;
0697                    leftButtonW = rightButtonW;
0698                    rightButtonW = temp;
0699                }
0700                int leftButtonX = sbInsets.left;
0701                int rightButtonX = sbSize.width
0702                        - (sbInsets.right + rightButtonW);
0703
0704                /* The thumb must fit within the width left over after we
0705                 * subtract the preferredSize of the buttons and the insets.
0706                 */
0707                int sbInsetsW = sbInsets.left + sbInsets.right;
0708                int sbButtonsW = leftButtonW + rightButtonW;
0709                float trackW = sbSize.width - (sbInsetsW + sbButtonsW);
0710
0711                /* Compute the width and origin of the thumb.  Enforce
0712                 * the thumbs min/max dimensions.  The case where the thumb 
0713                 * is at the right edge is handled specially to avoid numerical 
0714                 * problems in computing thumbX.  If the thumb doesn't
0715                 * fit in the track (trackH) we'll hide it later.
0716                 */
0717                float min = sb.getMinimum();
0718                float max = sb.getMaximum();
0719                float extent = sb.getVisibleAmount();
0720                float range = max - min;
0721                float value = getValue(sb);
0722
0723                int thumbW = (range <= 0) ? getMaximumThumbSize().width
0724                        : (int) (trackW * (extent / range));
0725                thumbW = Math.max(thumbW, getMinimumThumbSize().width);
0726                thumbW = Math.min(thumbW, getMaximumThumbSize().width);
0727
0728                int thumbX = ltr ? rightButtonX - thumbW : leftButtonX
0729                        + leftButtonW;
0730                if (value < (max - sb.getVisibleAmount())) {
0731                    float thumbRange = trackW - thumbW;
0732                    if (ltr) {
0733                        thumbX = (int) (0.5f + (thumbRange * ((value - min) / (range - extent))));
0734                    } else {
0735                        thumbX = (int) (0.5f + (thumbRange * ((max - extent - value) / (range - extent))));
0736                    }
0737                    thumbX += leftButtonX + leftButtonW;
0738                }
0739
0740                /* If the buttons don't fit, allocate half of the available 
0741                 * space to each and move the right one over.
0742                 */
0743                int sbAvailButtonW = (sbSize.width - sbInsetsW);
0744                if (sbAvailButtonW < sbButtonsW) {
0745                    rightButtonW = leftButtonW = sbAvailButtonW / 2;
0746                    rightButtonX = sbSize.width
0747                            - (sbInsets.right + rightButtonW);
0748                }
0749
0750                (ltr ? decrButton : incrButton).setBounds(leftButtonX, itemY,
0751                        leftButtonW, itemH);
0752                (ltr ? incrButton : decrButton).setBounds(rightButtonX, itemY,
0753                        rightButtonW, itemH);
0754
0755                /* Update the trackRect field.
0756                 */
0757                int itrackX = leftButtonX + leftButtonW;
0758                int itrackW = rightButtonX - itrackX;
0759                trackRect.setBounds(itrackX, itemY, itrackW, itemH);
0760
0761                /* Make sure the thumb fits between the buttons.  Note 
0762                 * that setting the thumbs bounds causes a repaint.
0763                 */
0764                if (thumbW >= (int) trackW) {
0765                    if (UIManager.getBoolean("ScrollBar.alwaysShowThumb")) {
0766                        // This is used primarily for GTK L&F, which expands the
0767                        // thumb to fit the track when it would otherwise be hidden.
0768                        setThumbBounds(itrackX, itemY, itrackW, itemH);
0769                    } else {
0770                        // Other L&F's simply hide the thumb in this case.
0771                        setThumbBounds(0, 0, 0, 0);
0772                    }
0773                } else {
0774                    if (thumbX + thumbW > rightButtonX) {
0775                        thumbX = rightButtonX - thumbW;
0776                    }
0777                    if (thumbX < leftButtonX + leftButtonW) {
0778                        thumbX = leftButtonX + leftButtonW + 1;
0779                    }
0780                    setThumbBounds(thumbX, itemY, thumbW, itemH);
0781                }
0782            }
0783
0784            public void layoutContainer(Container scrollbarContainer) {
0785                /* If the user is dragging the value, we'll assume that the 
0786                 * scrollbars layout is OK modulo the thumb which is being 
0787                 * handled by the dragging code.
0788                 */
0789                if (isDragging) {
0790                    return;
0791                }
0792
0793                JScrollBar scrollbar = (JScrollBar) scrollbarContainer;
0794                switch (scrollbar.getOrientation()) {
0795                case JScrollBar.VERTICAL:
0796                    layoutVScrollbar(scrollbar);
0797                    break;
0798
0799                case JScrollBar.HORIZONTAL:
0800                    layoutHScrollbar(scrollbar);
0801                    break;
0802                }
0803            }
0804
0805            /**
0806             * Set the bounds of the thumb and force a repaint that includes
0807             * the old thumbBounds and the new one.
0808             *
0809             * @see #getThumbBounds
0810             */
0811            protected void setThumbBounds(int x, int y, int width, int height) {
0812                /* If the thumbs bounds haven't changed, we're done.
0813                 */
0814                if ((thumbRect.x == x) && (thumbRect.y == y)
0815                        && (thumbRect.width == width)
0816                        && (thumbRect.height == height)) {
0817                    return;
0818                }
0819
0820                /* Update thumbRect, and repaint the union of x,y,w,h and 
0821                 * the old thumbRect.
0822                 */
0823                int minX = Math.min(x, thumbRect.x);
0824                int minY = Math.min(y, thumbRect.y);
0825                int maxX = Math.max(x + width, thumbRect.x + thumbRect.width);
0826                int maxY = Math.max(y + height, thumbRect.y + thumbRect.height);
0827
0828                thumbRect.setBounds(x, y, width, height);
0829                scrollbar.repaint(minX, minY, maxX - minX, maxY - minY);
0830
0831                // Once there is API to determine the mouse location this will need
0832                // to be changed.
0833                setThumbRollover(false);
0834            }
0835
0836            /**
0837             * Return the current size/location of the thumb.
0838             * <p>
0839             * <b>Warning </b>: the value returned by this method should not be
0840             * be modified, it's a reference to the actual rectangle, not a copy.
0841             *
0842             * @return The current size/location of the thumb.
0843             * @see #setThumbBounds
0844             */
0845            protected Rectangle getThumbBounds() {
0846                return thumbRect;
0847            }
0848
0849            /**
0850             * Returns the current bounds of the track, i.e. the space in between
0851             * the increment and decrement buttons, less the insets.  The value
0852             * returned by this method is updated each time the scrollbar is
0853             * laid out (validated).
0854             * <p>
0855             * <b>Warning </b>: the value returned by this method should not be
0856             * be modified, it's a reference to the actual rectangle, not a copy.
0857             *
0858             * @return the current bounds of the scrollbar track
0859             * @see #layoutContainer
0860             */
0861            protected Rectangle getTrackBounds() {
0862                return trackRect;
0863            }
0864
0865            /*
0866             * Method for scrolling by a block increment.
0867             * Added for mouse wheel scrolling support, RFE 4202656.
0868             */
0869            static void scrollByBlock(JScrollBar scrollbar, int direction) {
0870                // This method is called from BasicScrollPaneUI to implement wheel
0871                // scrolling, and also from scrollByBlock().
0872                int oldValue = scrollbar.getValue();
0873                int blockIncrement = scrollbar.getBlockIncrement(direction);
0874                int delta = blockIncrement * ((direction > 0) ? +1 : -1);
0875                int newValue = oldValue + delta;
0876
0877                // Check for overflow.
0878                if (delta > 0 && newValue < oldValue) {
0879                    newValue = scrollbar.getMaximum();
0880                } else if (delta < 0 && newValue > oldValue) {
0881                    newValue = scrollbar.getMinimum();
0882                }
0883
0884                scrollbar.setValue(newValue);
0885            }
0886
0887            protected void scrollByBlock(int direction) {
0888                scrollByBlock(scrollbar, direction);
0889                trackHighlight = direction > 0 ? INCREASE_HIGHLIGHT
0890                        : DECREASE_HIGHLIGHT;
0891                Rectangle dirtyRect = getTrackBounds();
0892                scrollbar.repaint(dirtyRect.x, dirtyRect.y, dirtyRect.width,
0893                        dirtyRect.height);
0894            }
0895
0896            /*
0897             * Method for scrolling by a unit increment.
0898             * Added for mouse wheel scrolling support, RFE 4202656.
0899             *
0900             * If limitByBlock is set to true, the scrollbar will scroll at least 1
0901             * unit increment, but will not scroll farther than the block increment.
0902             * See BasicScrollPaneUI.Handler.mouseWheelMoved().
0903             */
0904            static void scrollByUnits(JScrollBar scrollbar, int direction,
0905                    int units, boolean limitToBlock) {
0906                // This method is called from BasicScrollPaneUI to implement wheel
0907                // scrolling, as well as from scrollByUnit().
0908                int delta;
0909                int limit = -1;
0910
0911                if (limitToBlock) {
0912                    if (direction < 0) {
0913                        limit = scrollbar.getValue()
0914                                - scrollbar.getBlockIncrement(direction);
0915                    } else {
0916                        limit = scrollbar.getValue()
0917                                + scrollbar.getBlockIncrement(direction);
0918                    }
0919                }
0920
0921                for (int i = 0; i < units; i++) {
0922                    if (direction > 0) {
0923                        delta = scrollbar.getUnitIncrement(direction);
0924                    } else {
0925                        delta = -scrollbar.getUnitIncrement(direction);
0926                    }
0927
0928                    int oldValue = scrollbar.getValue();
0929                    int newValue = oldValue + delta;
0930
0931                    // Check for overflow.
0932                    if (delta > 0 && newValue < oldValue) {
0933                        newValue = scrollbar.getMaximum();
0934                    } else if (delta < 0 && newValue > oldValue) {
0935                        newValue = scrollbar.getMinimum();
0936                    }
0937                    if (oldValue == newValue) {
0938                        break;
0939                    }
0940
0941                    if (limitToBlock && i > 0) {
0942                        assert limit != -1;
0943                        if ((direction < 0 && newValue < limit)
0944                                || (direction > 0 && newValue > limit)) {
0945                            break;
0946                        }
0947                    }
0948                    scrollbar.setValue(newValue);
0949                }
0950            }
0951
0952            protected void scrollByUnit(int direction) {
0953                scrollByUnits(scrollbar, direction, 1, false);
0954            }
0955
0956            /**
0957             * Indicates whether the user can absolutely position the thumb with
0958             * a mouse gesture (usually the middle mouse button).
0959             *
0960             * @return true if a mouse gesture can absolutely position the thumb
0961             * @since 1.5
0962             */
0963            public boolean getSupportsAbsolutePositioning() {
0964                return supportsAbsolutePositioning;
0965            }
0966
0967            /**
0968             * A listener to listen for model changes.
0969             *
0970             */
0971            protected class ModelListener implements  ChangeListener {
0972                public void stateChanged(ChangeEvent e) {
0973                    if (!useCachedValue) {
0974                        scrollBarValue = scrollbar.getValue();
0975                    }
0976                    layoutContainer(scrollbar);
0977                    useCachedValue = false;
0978                }
0979            }
0980
0981            /**
0982             * Track mouse drags.
0983             */
0984            protected class TrackListener extends MouseAdapter implements 
0985                    MouseMotionListener {
0986                protected transient int offset;
0987                protected transient int currentMouseX, currentMouseY;
0988                private transient int direction = +1;
0989
0990                public void mouseReleased(MouseEvent e) {
0991                    if (isDragging) {
0992                        updateThumbState(e.getX(), e.getY());
0993                    }
0994                    if (SwingUtilities.isRightMouseButton(e)
0995                            || (!getSupportsAbsolutePositioning() && SwingUtilities
0996                                    .isMiddleMouseButton(e)))
0997                        return;
0998                    if (!scrollbar.isEnabled())
0999                        return;
1000
1001                    Rectangle r = getTrackBounds();
1002                    scrollbar.repaint(r.x, r.y, r.width, r.height);
1003
1004                    trackHighlight = NO_HIGHLIGHT;
1005                    isDragging = false;
1006                    offset = 0;
1007                    scrollTimer.stop();
1008                    useCachedValue = true;
1009                    scrollbar.setValueIsAdjusting(false);
1010                }
1011
1012                /**
1013                 * If the mouse is pressed above the "thumb" component
1014                 * then reduce the scrollbars value by one page ("page up"), 
1015                 * otherwise increase it by one page.  If there is no 
1016                 * thumb then page up if the mouse is in the upper half
1017                 * of the track.
1018                 */
1019                public void mousePressed(MouseEvent e) {
1020                    if (SwingUtilities.isRightMouseButton(e)
1021                            || (!getSupportsAbsolutePositioning() && SwingUtilities
1022                                    .isMiddleMouseButton(e)))
1023                        return;
1024                    if (!scrollbar.isEnabled())
1025                        return;
1026
1027                    if (!scrollbar.hasFocus()
1028                            && scrollbar.isRequestFocusEnabled()) {
1029                        scrollbar.requestFocus();
1030                    }
1031
1032                    useCachedValue = true;
1033                    scrollbar.setValueIsAdjusting(true);
1034
1035                    currentMouseX = e.getX();
1036                    currentMouseY = e.getY();
1037
1038                    // Clicked in the Thumb area?
1039                    if (getThumbBounds().contains(currentMouseX, currentMouseY)) {
1040                        switch (scrollbar.getOrientation()) {
1041                        case JScrollBar.VERTICAL:
1042                            offset = currentMouseY - getThumbBounds().y;
1043                            break;
1044                        case JScrollBar.HORIZONTAL:
1045                            offset = currentMouseX - getThumbBounds().x;
1046                            break;
1047                        }
1048                        isDragging = true;
1049                        return;
1050                    } else if (getSupportsAbsolutePositioning()
1051                            && SwingUtilities.isMiddleMouseButton(e)) {
1052                        switch (scrollbar.getOrientation()) {
1053                        case JScrollBar.VERTICAL:
1054                            offset = getThumbBounds().height / 2;
1055                            break;
1056                        case JScrollBar.HORIZONTAL:
1057                            offset = getThumbBounds().width / 2;
1058                            break;
1059                        }
1060                        isDragging = true;
1061                        setValueFrom(e);
1062                        return;
1063                    }
1064                    isDragging = false;
1065
1066                    Dimension sbSize = scrollbar.getSize();
1067                    direction = +1;
1068
1069                    switch (scrollbar.getOrientation()) {
1070                    case JScrollBar.VERTICAL:
1071                        if (getThumbBounds().isEmpty()) {
1072                            int scrollbarCenter = sbSize.height / 2;
1073                            direction = (currentMouseY < scrollbarCenter) ? -1
1074                                    : +1;
1075                        } else {
1076                            int thumbY = getThumbBounds().y;
1077                            direction = (currentMouseY < thumbY) ? -1 : +1;
1078                        }
1079                        break;
1080                    case JScrollBar.HORIZONTAL:
1081                        if (getThumbBounds().isEmpty()) {
1082                            int scrollbarCenter = sbSize.width / 2;
1083                            direction = (currentMouseX < scrollbarCenter) ? -1
1084                                    : +1;
1085                        } else {
1086                            int thumbX = getThumbBounds().x;
1087                            direction = (currentMouseX < thumbX) ? -1 : +1;
1088                        }
1089                        if (!scrollbar.getComponentOrientation()
1090                                .isLeftToRight()) {
1091                            direction = -direction;
1092                        }
1093                        break;
1094                    }
1095                    scrollByBlock(direction);
1096
1097                    scrollTimer.stop();
1098                    scrollListener.setDirection(direction);
1099                    scrollListener.setScrollByBlock(true);
1100                    startScrollTimerIfNecessary();
1101                }
1102
1103                /** 
1104                 * Set the models value to the position of the thumb's top of Vertical
1105                 * scrollbar, or the left/right of Horizontal scrollbar in
1106                 * left-to-right/right-to-left scrollbar relative to the origin of the
1107                 * track.
1108                 */
1109                public void mouseDragged(MouseEvent e) {
1110                    if (SwingUtilities.isRightMouseButton(e)
1111                            || (!getSupportsAbsolutePositioning() && SwingUtilities
1112                                    .isMiddleMouseButton(e)))
1113                        return;
1114                    if (!scrollbar.isEnabled() || getThumbBounds().isEmpty()) {
1115                        return;
1116                    }
1117                    if (isDragging) {
1118                        setValueFrom(e);
1119                    } else {
1120                        currentMouseX = e.getX();
1121                        currentMouseY = e.getY();
1122                        updateThumbState(currentMouseX, currentMouseY);
1123                        startScrollTimerIfNecessary();
1124                    }
1125                }
1126
1127                private void setValueFrom(MouseEvent e) {
1128                    boolean active = isThumbRollover();
1129                    BoundedRangeModel model = scrollbar.getModel();
1130                    Rectangle thumbR = getThumbBounds();
1131                    float trackLength;
1132                    int thumbMin, thumbMax, thumbPos;
1133
1134                    if (scrollbar.getOrientation() == JScrollBar.VERTICAL) {
1135                        thumbMin = decrButton.getY() + decrButton.getHeight();
1136                        thumbMax = incrButton.getY() - thumbR.height;
1137                        thumbPos = Math.min(thumbMax, Math.max(thumbMin, (e
1138                                .getY() - offset)));
1139                        setThumbBounds(thumbR.x, thumbPos, thumbR.width,
1140                                thumbR.height);
1141                        trackLength = getTrackBounds().height;
1142                    } else {
1143                        if (scrollbar.getComponentOrientation().isLeftToRight()) {
1144                            thumbMin = decrButton.getX()
1145                                    + decrButton.getWidth();
1146                            thumbMax = incrButton.getX() - thumbR.width;
1147                        } else {
1148                            thumbMin = incrButton.getX()
1149                                    + incrButton.getWidth();
1150                            thumbMax = decrButton.getX() - thumbR.width;
1151                        }
1152                        thumbPos = Math.min(thumbMax, Math.max(thumbMin, (e
1153                                .getX() - offset)));
1154                        setThumbBounds(thumbPos, thumbR.y, thumbR.width,
1155                                thumbR.height);
1156                        trackLength = getTrackBounds().width;
1157                    }
1158
1159                    /* Set the scrollbars value.  If the thumb has reached the end of
1160                     * the scrollbar, then just set the value to its maximum.  Otherwise
1161                     * compute the value as accurately as possible.
1162                     */
1163                    if (thumbPos == thumbMax) {
1164                        if (scrollbar.getOrientation() == JScrollBar.VERTICAL
1165                                || scrollbar.getComponentOrientation()
1166                                        .isLeftToRight()) {
1167                            scrollbar.setValue(model.getMaximum()
1168                                    - model.getExtent());
1169                        } else {
1170                            scrollbar.setValue(model.getMinimum());
1171                        }
1172                    } else {
1173                        float valueMax = model.getMaximum() - model.getExtent();
1174                        float valueRange = valueMax - model.getMinimum();
1175                        float thumbValue = thumbPos - thumbMin;
1176                        float thumbRange = thumbMax - thumbMin;
1177                        int value;
1178                        if (scrollbar.getOrientation() == JScrollBar.VERTICAL
1179                                || scrollbar.getComponentOrientation()
1180                                        .isLeftToRight()) {
1181                            value = (int) (0.5 + ((thumbValue / thumbRange) * valueRange));
1182                        } else {
1183                            value = (int) (0.5 + (((thumbMax - thumbPos) / thumbRange) * valueRange));
1184                        }
1185
1186                        useCachedValue = true;
1187                        scrollBarValue = value + model.getMinimum();
1188                        scrollbar
1189                                .setValue(adjustValueIfNecessary(scrollBarValue));
1190                    }
1191                    setThumbRollover(active);
1192                }
1193
1194                private int adjustValueIfNecessary(int value) {
1195                    if (scrollbar.getParent() instanceof  JScrollPane) {
1196                        JScrollPane scrollpane = (JScrollPane) scrollbar
1197                                .getParent();
1198                        JViewport viewport = scrollpane.getViewport();
1199                        Component view = viewport.getView();
1200                        if (view instanceof  JList) {
1201                            JList list = (JList) view;
1202                            if (DefaultLookup.getBoolean(list, list.getUI(),
1203                                    "List.lockToPositionOnScroll", false)) {
1204                                int adjustedValue = value;
1205                                int mode = list.getLayoutOrientation();
1206                                int orientation = scrollbar.getOrientation();
1207                                if (orientation == JScrollBar.VERTICAL
1208                                        && mode == JList.VERTICAL) {
1209                                    int index = list.locationToIndex(new Point(
1210                                            0, value));
1211                                    Rectangle rect = list.getCellBounds(index,
1212                                            index);
1213                                    if (rect != null) {
1214                                        adjustedValue = rect.y;
1215                                    }
1216                                }
1217                                if (orientation == JScrollBar.HORIZONTAL
1218                                        && (mode == JList.VERTICAL_WRAP || mode == JList.HORIZONTAL_WRAP)) {
1219                                    if (scrollpane.getComponentOrientation()
1220                                            .isLeftToRight()) {
1221                                        int index = list
1222                                                .locationToIndex(new Point(
1223                                                        value, 0));
1224                                        Rectangle rect = list.getCellBounds(
1225                                                index, index);
1226                                        if (rect != null) {
1227                                            adjustedValue = rect.x;
1228                                        }
1229                                    } else {
1230                                        Point loc = new Point(value, 0);
1231                                        int extent = viewport.getExtentSize().width;
1232                                        loc.x += extent - 1;
1233                                        int index = list.locationToIndex(loc);
1234                                        Rectangle rect = list.getCellBounds(
1235                                                index, index);
1236                                        if (rect != null) {
1237                                            adjustedValue = rect.x + rect.width
1238                                                    - extent;
1239                                        }
1240                                    }
1241                                }
1242                                value = adjustedValue;
1243
1244                            }
1245                        }
1246                    }
1247                    return value;
1248                }
1249
1250                private void startScrollTimerIfNecessary() {
1251                    if (scrollTimer.isRunning()) {
1252                        return;
1253                    }
1254
1255                    Rectangle tb = getThumbBounds();
1256
1257                    switch (scrollbar.getOrientation()) {
1258                    case JScrollBar.VERTICAL:
1259                        if (direction > 0) {
1260                            if (tb.y + tb.height < trackListener.currentMouseY) {
1261                                scrollTimer.start();
1262                            }
1263                        } else if (tb.y > trackListener.currentMouseY) {
1264                            scrollTimer.start();
1265                        }
1266                        break;
1267                    case JScrollBar.HORIZONTAL:
1268                        if ((direction > 0 && isMouseAfterThumb())
1269                                || (direction < 0 && isMouseBeforeThumb())) {
1270
1271                            scrollTimer.start();
1272                        }
1273                        break;
1274                    }
1275                }
1276
1277                public void mouseMoved(MouseEvent e) {
1278                    if (!isDragging) {
1279                        updateThumbState(e.getX(), e.getY());
1280                    }
1281                }
1282
1283                /**
1284                 * Invoked when the mouse exits the scrollbar.
1285                 *
1286                 * @param e MouseEvent further describing the event
1287                 * @since 1.5
1288                 */
1289                public void mouseExited(MouseEvent e) {
1290                    if (!isDragging) {
1291                        setThumbRollover(false);
1292                    }
1293                }
1294            }
1295
1296            /**
1297             * Listener for cursor keys.
1298             */
1299            protected class ArrowButtonListener extends MouseAdapter {
1300                // Because we are handling both mousePressed and Actions
1301                // we need to make sure we don't fire under both conditions.
1302                // (keyfocus on scrollbars causes action without mousePress
1303                boolean handledEvent;
1304
1305                public void mousePressed(MouseEvent e) {
1306                    if (!scrollbar.isEnabled()) {
1307                        return;
1308                    }
1309                    // not an unmodified left mouse button
1310                    //if(e.getModifiers() != InputEvent.BUTTON1_MASK) {return; }
1311                    if (!SwingUtilities.isLeftMouseButton(e)) {
1312                        return;
1313                    }
1314
1315                    int direction = (e.getSource() == incrButton) ? 1 : -1;
1316
1317                    scrollByUnit(direction);
1318                    scrollTimer.stop();
1319                    scrollListener.setDirection(direction);
1320                    scrollListener.setScrollByBlock(false);
1321                    scrollTimer.start();
1322
1323                    handledEvent = true;
1324                    if (!scrollbar.hasFocus()
1325                            && scrollbar.isRequestFocusEnabled()) {
1326                        scrollbar.requestFocus();
1327                    }
1328                }
1329
1330                public void mouseReleased(MouseEvent e) {
1331                    scrollTimer.stop();
1332                    handledEvent = false;
1333                    scrollbar.setValueIsAdjusting(false);
1334                }
1335            }
1336
1337            /**
1338             * Listener for scrolling events initiated in the
1339             * <code>ScrollPane</code>.
1340             */
1341            protected class ScrollListener implements  ActionListener {
1342                int direction = +1;
1343                boolean useBlockIncrement;
1344
1345                public ScrollListener() {
1346                    direction = +1;
1347                    useBlockIncrement = false;
1348                }
1349
1350                public ScrollListener(int dir, boolean block) {
1351                    direction = dir;
1352                    useBlockIncrement = block;
1353                }
1354
1355                public void setDirection(int direction) {
1356                    this .direction = direction;
1357                }
1358
1359                public void setScrollByBlock(boolean block) {
1360                    this .useBlockIncrement = block;
1361                }
1362
1363                public void actionPerformed(ActionEvent e) {
1364                    if (useBlockIncrement) {
1365                        scrollByBlock(direction);
1366                        // Stop scrolling if the thumb catches up with the mouse
1367                        if (scrollbar.getOrientation() == JScrollBar.VERTICAL) {
1368                            if (direction > 0) {
1369                                if (getThumbBounds().y
1370                                        + getThumbBounds().height >= trackListener.currentMouseY)
1371                                    ((Timer) e.getSource()).stop();
1372                            } else if (getThumbBounds().y <= trackListener.currentMouseY) {
1373                                ((Timer) e.getSource()).stop();
1374                            }
1375                        } else {
1376                            if ((direction > 0 && !isMouseAfterThumb())
1377                                    || (direction < 0 && !isMouseBeforeThumb())) {
1378
1379                                ((Timer) e.getSource()).stop();
1380                            }
1381                        }
1382                    } else {
1383                        scrollByUnit(direction);
1384                    }
1385
1386                    if (direction > 0
1387                            && scrollbar.getValue()
1388                                    + scrollbar.getVisibleAmount() >= scrollbar
1389                                    .getMaximum())
1390                        ((Timer) e.getSource()).stop();
1391                    else if (direction < 0
1392                            && scrollbar.getValue() <= scrollbar.getMinimum())
1393                        ((Timer) e.getSource()).stop();
1394                }
1395            }
1396
1397            private boolean isMouseLeftOfThumb() {
1398                return trackListener.currentMouseX < getThumbBounds().x;
1399            }
1400
1401            private boolean isMouseRightOfThumb() {
1402                Rectangle tb = getThumbBounds();
1403                return trackListener.currentMouseX > tb.x + tb.width;
1404            }
1405
1406            private boolean isMouseBeforeThumb() {
1407                return scrollbar.getComponentOrientation().isLeftToRight() ? isMouseLeftOfThumb()
1408                        : isMouseRightOfThumb();
1409            }
1410
1411            private boolean isMouseAfterThumb() {
1412                return scrollbar.getComponentOrientation().isLeftToRight() ? isMouseRightOfThumb()
1413                        : isMouseLeftOfThumb();
1414            }
1415
1416            private void updateButtonDirections() {
1417                int orient = scrollbar.getOrientation();
1418                if (scrollbar.getComponentOrientation().isLeftToRight()) {
1419                    if (incrButton instanceof  BasicArrowButton) {
1420                        ((BasicArrowButton) incrButton)
1421                                .setDirection(orient == HORIZONTAL ? EAST
1422                                        : SOUTH);
1423                    }
1424                    if (decrButton instanceof  BasicArrowButton) {
1425                        ((BasicArrowButton) decrButton)
1426                                .setDirection(orient == HORIZONTAL ? WEST
1427                                        : NORTH);
1428                    }
1429                } else {
1430                    if (incrButton instanceof  BasicArrowButton) {
1431                        ((BasicArrowButton) incrButton)
1432                                .setDirection(orient == HORIZONTAL ? WEST
1433                                        : SOUTH);
1434                    }
1435                    if (decrButton instanceof  BasicArrowButton) {
1436                        ((BasicArrowButton) decrButton)
1437                                .setDirection(orient == HORIZONTAL ? EAST
1438                                        : NORTH);
1439                    }
1440                }
1441            }
1442
1443            public class PropertyChangeHandler implements 
1444                    PropertyChangeListener {
1445                // NOTE: This class exists only for backward compatability. All
1446                // its functionality has been moved into Handler. If you need to add
1447                // new functionality add it to the Handler, but make sure this      
1448                // class calls into the Handler.
1449
1450                public void propertyChange(PropertyChangeEvent e) {
1451                    getHandler().propertyChange(e);
1452                }
1453            }
1454
1455            /**
1456             * Used for scrolling the scrollbar.
1457             */
1458            private static class Actions extends UIAction {
1459                private static final String POSITIVE_UNIT_INCREMENT = "positiveUnitIncrement";
1460                private static final String POSITIVE_BLOCK_INCREMENT = "positiveBlockIncrement";
1461                private static final String NEGATIVE_UNIT_INCREMENT = "negativeUnitIncrement";
1462                private static final String NEGATIVE_BLOCK_INCREMENT = "negativeBlockIncrement";
1463                private static final String MIN_SCROLL = "minScroll";
1464                private static final String MAX_SCROLL = "maxScroll";
1465
1466                Actions(String name) {
1467                    super (name);
1468                }
1469
1470                public void actionPerformed(ActionEvent e) {
1471                    JScrollBar scrollBar = (JScrollBar) e.getSource();
1472                    String key = getName();
1473                    if (key == POSITIVE_UNIT_INCREMENT) {
1474                        scroll(scrollBar, POSITIVE_SCROLL, false);
1475                    } else if (key == POSITIVE_BLOCK_INCREMENT) {
1476                        scroll(scrollBar, POSITIVE_SCROLL, true);
1477                    } else if (key == NEGATIVE_UNIT_INCREMENT) {
1478                        scroll(scrollBar, NEGATIVE_SCROLL, false);
1479                    } else if (key == NEGATIVE_BLOCK_INCREMENT) {
1480                        scroll(scrollBar, NEGATIVE_SCROLL, true);
1481                    } else if (key == MIN_SCROLL) {
1482                        scroll(scrollBar, BasicScrollBarUI.MIN_SCROLL, true);
1483                    } else if (key == MAX_SCROLL) {
1484                        scroll(scrollBar, BasicScrollBarUI.MAX_SCROLL, true);
1485                    }
1486                }
1487
1488                private void scroll(JScrollBar scrollBar, int dir, boolean block) {
1489
1490                    if (dir == NEGATIVE_SCROLL || dir == POSITIVE_SCROLL) {
1491                        int amount;
1492                        // Don't use the BasicScrollBarUI.scrollByXXX methods as we
1493                        // don't want to use an invokeLater to reset the trackHighlight
1494                        // via an invokeLater
1495                        if (block) {
1496                            if (dir == NEGATIVE_SCROLL) {
1497                                amount = -1 * scrollBar.getBlockIncrement(-1);
1498                            } else {
1499                                amount = scrollBar.getBlockIncrement(1);
1500                            }
1501                        } else {
1502                            if (dir == NEGATIVE_SCROLL) {
1503                                amount = -1 * scrollBar.getUnitIncrement(-1);
1504                            } else {
1505                                amount = scrollBar.getUnitIncrement(1);
1506                            }
1507                        }
1508                        scrollBar.setValue(scrollBar.getValue() + amount);
1509                    } else if (dir == BasicScrollBarUI.MIN_SCROLL) {
1510                        scrollBar.setValue(scrollBar.getMinimum());
1511                    } else if (dir == BasicScrollBarUI.MAX_SCROLL) {
1512                        scrollBar.setValue(scrollBar.getMaximum());
1513                    }
1514                }
1515            }
1516
1517            //
1518            // EventHandler
1519            //
1520            private class Handler implements  FocusListener,
1521                    PropertyChangeListener {
1522                //
1523                // FocusListener
1524                //
1525                public void focusGained(FocusEvent e) {
1526                    scrollbar.repaint();
1527                }
1528
1529                public void focusLost(FocusEvent e) {
1530                    scrollbar.repaint();
1531                }
1532
1533                //
1534                // PropertyChangeListener
1535                //
1536                public void propertyChange(PropertyChangeEvent e) {
1537                    String propertyName = e.getPropertyName();
1538
1539                    if ("model" == propertyName) {
1540                        BoundedRangeModel oldModel = (BoundedRangeModel) e
1541                                .getOldValue();
1542                        BoundedRangeModel newModel = (BoundedRangeModel) e
1543                                .getNewValue();
1544                        oldModel.removeChangeListener(modelListener);
1545                        newModel.addChangeListener(modelListener);
1546                        scrollbar.repaint();
1547                        scrollbar.revalidate();
1548                    } else if ("orientation" == propertyName) {
1549                        updateButtonDirections();
1550                    } else if ("componentOrientation" == propertyName) {
1551                        updateButtonDirections();
1552                        InputMap inputMap = getInputMap(JComponent.WHEN_FOCUSED);
1553                        SwingUtilities.replaceUIInputMap(scrollbar,
1554                                JComponent.WHEN_FOCUSED, inputMap);
1555                    }
1556                }
1557            }
1558        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.