1178 lines · 45.4 KB · Java
RawDownload
/* * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package javax.swing.plaf.basic; import sun.swing.DefaultLookup;import sun.swing.UIAction; import javax.swing.*;import javax.swing.event.*;import javax.swing.border.*;import javax.swing.plaf.*; import java.beans.PropertyChangeListener;import java.beans.PropertyChangeEvent; import java.awt.Component;import java.awt.Rectangle;import java.awt.Dimension;import java.awt.Point;import java.awt.Insets;import java.awt.Graphics;import java.awt.event.*; /** * A default L&F implementation of ScrollPaneUI. * * @author Hans Muller */public class BasicScrollPaneUI    extends ScrollPaneUI implements ScrollPaneConstants{    protected JScrollPane scrollpane;    protected ChangeListener vsbChangeListener;    protected ChangeListener hsbChangeListener;    protected ChangeListener viewportChangeListener;    protected PropertyChangeListener spPropertyChangeListener;    private MouseWheelListener mouseScrollListener;    private int oldExtent = Integer.MIN_VALUE;     /**     * PropertyChangeListener installed on the vertical scrollbar.     */    private PropertyChangeListener vsbPropertyChangeListener;     /**     * PropertyChangeListener installed on the horizontal scrollbar.     */    private PropertyChangeListener hsbPropertyChangeListener;     private Handler handler;     /**     * State flag that shows whether setValue() was called from a user program     * before the value of "extent" was set in right-to-left component     * orientation.     */    private boolean setValueCalled = false;      public static ComponentUI createUI(JComponent x) {        return new BasicScrollPaneUI();    }     static void loadActionMap(LazyActionMap map) {        map.put(new Actions(Actions.SCROLL_UP));        map.put(new Actions(Actions.SCROLL_DOWN));        map.put(new Actions(Actions.SCROLL_HOME));        map.put(new Actions(Actions.SCROLL_END));        map.put(new Actions(Actions.UNIT_SCROLL_UP));        map.put(new Actions(Actions.UNIT_SCROLL_DOWN));        map.put(new Actions(Actions.SCROLL_LEFT));        map.put(new Actions(Actions.SCROLL_RIGHT));        map.put(new Actions(Actions.UNIT_SCROLL_RIGHT));        map.put(new Actions(Actions.UNIT_SCROLL_LEFT));    }       public void paint(Graphics g, JComponent c) {        Border vpBorder = scrollpane.getViewportBorder();        if (vpBorder != null) {            Rectangle r = scrollpane.getViewportBorderBounds();            vpBorder.paintBorder(scrollpane, g, r.x, r.y, r.width, r.height);        }    }      /**     * @return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE)     */    public Dimension getMaximumSize(JComponent c) {        return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE);    }      protected void installDefaults(JScrollPane scrollpane)    {        LookAndFeel.installBorder(scrollpane, "ScrollPane.border");        LookAndFeel.installColorsAndFont(scrollpane,            "ScrollPane.background",            "ScrollPane.foreground",            "ScrollPane.font");         Border vpBorder = scrollpane.getViewportBorder();        if ((vpBorder == null) ||( vpBorder instanceof UIResource)) {            vpBorder = UIManager.getBorder("ScrollPane.viewportBorder");            scrollpane.setViewportBorder(vpBorder);        }        LookAndFeel.installProperty(scrollpane, "opaque", Boolean.TRUE);    }      protected void installListeners(JScrollPane c)    {        vsbChangeListener = createVSBChangeListener();        vsbPropertyChangeListener = createVSBPropertyChangeListener();        hsbChangeListener = createHSBChangeListener();        hsbPropertyChangeListener = createHSBPropertyChangeListener();        viewportChangeListener = createViewportChangeListener();        spPropertyChangeListener = createPropertyChangeListener();         JViewport viewport = scrollpane.getViewport();        JScrollBar vsb = scrollpane.getVerticalScrollBar();        JScrollBar hsb = scrollpane.getHorizontalScrollBar();         if (viewport != null) {            viewport.addChangeListener(viewportChangeListener);        }        if (vsb != null) {            vsb.getModel().addChangeListener(vsbChangeListener);            vsb.addPropertyChangeListener(vsbPropertyChangeListener);        }        if (hsb != null) {            hsb.getModel().addChangeListener(hsbChangeListener);            hsb.addPropertyChangeListener(hsbPropertyChangeListener);        }         scrollpane.addPropertyChangeListener(spPropertyChangeListener);     mouseScrollListener = createMouseWheelListener();    scrollpane.addMouseWheelListener(mouseScrollListener);     }     protected void installKeyboardActions(JScrollPane c) {        InputMap inputMap = getInputMap(JComponent.                                  WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);         SwingUtilities.replaceUIInputMap(c, JComponent.                               WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, inputMap);         LazyActionMap.installLazyActionMap(c, BasicScrollPaneUI.class,                                           "ScrollPane.actionMap");    }     InputMap getInputMap(int condition) {        if (condition == JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) {            InputMap keyMap = (InputMap)DefaultLookup.get(scrollpane, this,                                        "ScrollPane.ancestorInputMap");            InputMap rtlKeyMap;             if (scrollpane.getComponentOrientation().isLeftToRight() ||                    ((rtlKeyMap = (InputMap)DefaultLookup.get(scrollpane, this,                    "ScrollPane.ancestorInputMap.RightToLeft")) == null)) {                return keyMap;            } else {                rtlKeyMap.setParent(keyMap);                return rtlKeyMap;            }        }        return null;    }     public void installUI(JComponent x) {        scrollpane = (JScrollPane)x;        installDefaults(scrollpane);        installListeners(scrollpane);        installKeyboardActions(scrollpane);    }      protected void uninstallDefaults(JScrollPane c) {        LookAndFeel.uninstallBorder(scrollpane);         if (scrollpane.getViewportBorder() instanceof UIResource) {            scrollpane.setViewportBorder(null);        }    }      protected void uninstallListeners(JComponent c) {        JViewport viewport = scrollpane.getViewport();        JScrollBar vsb = scrollpane.getVerticalScrollBar();        JScrollBar hsb = scrollpane.getHorizontalScrollBar();         if (viewport != null) {            viewport.removeChangeListener(viewportChangeListener);        }        if (vsb != null) {            vsb.getModel().removeChangeListener(vsbChangeListener);            vsb.removePropertyChangeListener(vsbPropertyChangeListener);        }        if (hsb != null) {            hsb.getModel().removeChangeListener(hsbChangeListener);            hsb.removePropertyChangeListener(hsbPropertyChangeListener);        }         scrollpane.removePropertyChangeListener(spPropertyChangeListener);     if (mouseScrollListener != null) {        scrollpane.removeMouseWheelListener(mouseScrollListener);    }         vsbChangeListener = null;        hsbChangeListener = null;        viewportChangeListener = null;        spPropertyChangeListener = null;        mouseScrollListener = null;        handler = null;    }      protected void uninstallKeyboardActions(JScrollPane c) {        SwingUtilities.replaceUIActionMap(c, null);        SwingUtilities.replaceUIInputMap(c, JComponent.                           WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, null);    }      public void uninstallUI(JComponent c) {        uninstallDefaults(scrollpane);        uninstallListeners(scrollpane);        uninstallKeyboardActions(scrollpane);        scrollpane = null;    }     private Handler getHandler() {        if (handler == null) {            handler = new Handler();        }        return handler;    }     protected void syncScrollPaneWithViewport()    {        JViewport viewport = scrollpane.getViewport();        JScrollBar vsb = scrollpane.getVerticalScrollBar();        JScrollBar hsb = scrollpane.getHorizontalScrollBar();        JViewport rowHead = scrollpane.getRowHeader();        JViewport colHead = scrollpane.getColumnHeader();        boolean ltr = scrollpane.getComponentOrientation().isLeftToRight();         if (viewport != null) {            Dimension extentSize = viewport.getExtentSize();            Dimension viewSize = viewport.getViewSize();            Point viewPosition = viewport.getViewPosition();             if (vsb != null) {                int extent = extentSize.height;                int max = viewSize.height;                int value = Math.max(0, Math.min(viewPosition.y, max - extent));                vsb.setValues(value, extent, 0, max);            }             if (hsb != null) {                int extent = extentSize.width;                int max = viewSize.width;                int value;                 if (ltr) {                    value = Math.max(0, Math.min(viewPosition.x, max - extent));                } else {                    int currentValue = hsb.getValue();                     /* Use a particular formula to calculate "value"                     * until effective x coordinate is calculated.                     */                    if (setValueCalled && ((max - currentValue) == viewPosition.x)) {                        value = Math.max(0, Math.min(max - extent, currentValue));                        /* After "extent" is set, turn setValueCalled flag off.                         */                        if (extent != 0) {                            setValueCalled = false;                        }                    } else {                        if (extent > max) {                            viewPosition.x = max - extent;                            viewport.setViewPosition(viewPosition);                            value = 0;                        } else {                           /* The following line can't handle a small value of                            * viewPosition.x like Integer.MIN_VALUE correctly                            * because (max - extent - viewPositoiin.x) causes                            * an overflow. As a result, value becomes zero.                            * (e.g. setViewPosition(Integer.MAX_VALUE, ...)                            *       in a user program causes a overflow.                            *       Its expected value is (max - extent).)                            * However, this seems a trivial bug and adding a                            * fix makes this often-called method slow, so I'll                            * leave it until someone claims.                            */                            value = Math.max(0, Math.min(max - extent, max - extent - viewPosition.x));                            if (oldExtent > extent) {                                value -= oldExtent - extent;                            }                        }                    }                }                oldExtent = extent;                hsb.setValues(value, extent, 0, max);            }             if (rowHead != null) {                Point p = rowHead.getViewPosition();                p.y = viewport.getViewPosition().y;                p.x = 0;                rowHead.setViewPosition(p);            }             if (colHead != null) {                Point p = colHead.getViewPosition();                if (ltr) {                    p.x = viewport.getViewPosition().x;                } else {                    p.x = Math.max(0, viewport.getViewPosition().x);                }                p.y = 0;                colHead.setViewPosition(p);            }        }    }     /**     * Returns the baseline.     *     * @throws NullPointerException {@inheritDoc}     * @throws IllegalArgumentException {@inheritDoc}     * @see javax.swing.JComponent#getBaseline(int, int)     * @since 1.6     */    public int getBaseline(JComponent c, int width, int height) {        if (c == null) {            throw new NullPointerException("Component must be non-null");        }         if (width < 0 || height < 0) {            throw new IllegalArgumentException("Width and height must be >= 0");        }         JViewport viewport = scrollpane.getViewport();        Insets spInsets = scrollpane.getInsets();        int y = spInsets.top;        height = height - spInsets.top - spInsets.bottom;        width = width - spInsets.left - spInsets.right;        JViewport columnHeader = scrollpane.getColumnHeader();        if (columnHeader != null && columnHeader.isVisible()) {            Component header = columnHeader.getView();            if (header != null && header.isVisible()) {                // Header is always given it's preferred size.                Dimension headerPref = header.getPreferredSize();                int baseline = header.getBaseline(headerPref.width,                                                  headerPref.height);                if (baseline >= 0) {                    return y + baseline;                }            }            Dimension columnPref = columnHeader.getPreferredSize();            height -= columnPref.height;            y += columnPref.height;        }        Component view = (viewport == null) ? null : viewport.getView();        if (view != null && view.isVisible() &&                view.getBaselineResizeBehavior() ==                Component.BaselineResizeBehavior.CONSTANT_ASCENT) {            Border viewportBorder = scrollpane.getViewportBorder();            if (viewportBorder != null) {                Insets vpbInsets = viewportBorder.getBorderInsets(scrollpane);                y += vpbInsets.top;                height = height - vpbInsets.top - vpbInsets.bottom;                width = width - vpbInsets.left - vpbInsets.right;            }            if (view.getWidth() > 0 && view.getHeight() > 0) {                Dimension min = view.getMinimumSize();                width = Math.max(min.width, view.getWidth());                height = Math.max(min.height, view.getHeight());            }            if (width > 0 && height > 0) {                int baseline = view.getBaseline(width, height);                if (baseline > 0) {                    return y + baseline;                }            }        }        return -1;    }     /**     * Returns an enum indicating how the baseline of the component     * changes as the size changes.     *     * @throws NullPointerException {@inheritDoc}     * @see javax.swing.JComponent#getBaseline(int, int)     * @since 1.6     */    public Component.BaselineResizeBehavior getBaselineResizeBehavior(            JComponent c) {        super.getBaselineResizeBehavior(c);        // Baseline is either from the header, in which case it's always        // the same size and therefor can be created as CONSTANT_ASCENT.        // If the header doesn't have a baseline than the baseline will only        // be valid if it's BaselineResizeBehavior is        // CONSTANT_ASCENT, so, return CONSTANT_ASCENT.        return Component.BaselineResizeBehavior.CONSTANT_ASCENT;    }      /**     * Listener for viewport events.     */    public class ViewportChangeHandler implements ChangeListener    {         // NOTE: This class exists only for backward compatability. All        // its functionality has been moved into Handler. If you need to add        // new functionality add it to the Handler, but make sure this        // class calls into the Handler.         public void stateChanged(ChangeEvent e) {            getHandler().stateChanged(e);        }    }     protected ChangeListener createViewportChangeListener() {        return getHandler();    }      /**     * Horizontal scrollbar listener.     */    public class HSBChangeListener implements ChangeListener    {         // NOTE: This class exists only for backward compatability. All        // its functionality has been moved into Handler. If you need to add        // new functionality add it to the Handler, but make sure this        // class calls into the Handler.         public void stateChanged(ChangeEvent e)        {            getHandler().stateChanged(e);        }    }     /**     * Returns a <code>PropertyChangeListener</code> that will be installed     * on the horizontal <code>JScrollBar</code>.     */    private PropertyChangeListener createHSBPropertyChangeListener() {        return getHandler();    }     protected ChangeListener createHSBChangeListener() {        return getHandler();    }      /**     * Vertical scrollbar listener.     */    public class VSBChangeListener implements ChangeListener    {         // NOTE: This class exists only for backward compatability. All        // its functionality has been moved into Handler. If you need to add        // new functionality add it to the Handler, but make sure this        // class calls into the Handler.

Lines 1–500 of 1178.