| /* BasicScrollPaneUI.java |
| Copyright (C) 2002, 2004, 2005, 2006, Free Software Foundation, Inc. |
| |
| This file is part of GNU Classpath. |
| |
| GNU Classpath is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2, or (at your option) |
| any later version. |
| |
| GNU Classpath 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 for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GNU Classpath; see the file COPYING. If not, write to the |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
| 02110-1301 USA. |
| |
| Linking this library statically or dynamically with other modules is |
| making a combined work based on this library. Thus, the terms and |
| conditions of the GNU General Public License cover the whole |
| combination. |
| |
| As a special exception, the copyright holders of this library give you |
| permission to link this library with independent modules to produce an |
| executable, regardless of the license terms of these independent |
| modules, and to copy and distribute the resulting executable under |
| terms of your choice, provided that you also meet, for each linked |
| independent module, the terms and conditions of the license of that |
| module. An independent module is a module which is not derived from |
| or based on this library. If you modify this library, you may extend |
| this exception to your version of the library, but you are not |
| obligated to do so. If you do not wish to do so, delete this |
| exception statement from your version. */ |
| |
| |
| package javax.swing.plaf.basic; |
| |
| import gnu.classpath.NotImplementedException; |
| |
| import java.awt.Component; |
| import java.awt.Dimension; |
| import java.awt.Graphics; |
| import java.awt.Point; |
| import java.awt.Rectangle; |
| import java.awt.event.ActionEvent; |
| import java.awt.event.ContainerEvent; |
| import java.awt.event.ContainerListener; |
| import java.awt.event.MouseWheelEvent; |
| import java.awt.event.MouseWheelListener; |
| import java.beans.PropertyChangeEvent; |
| import java.beans.PropertyChangeListener; |
| |
| import javax.swing.AbstractAction; |
| import javax.swing.Action; |
| import javax.swing.ActionMap; |
| import javax.swing.InputMap; |
| import javax.swing.JComponent; |
| import javax.swing.JScrollBar; |
| import javax.swing.JScrollPane; |
| import javax.swing.JSlider; |
| import javax.swing.JViewport; |
| import javax.swing.LookAndFeel; |
| import javax.swing.ScrollPaneConstants; |
| import javax.swing.ScrollPaneLayout; |
| import javax.swing.Scrollable; |
| import javax.swing.SwingConstants; |
| import javax.swing.SwingUtilities; |
| import javax.swing.UIManager; |
| import javax.swing.event.ChangeEvent; |
| import javax.swing.event.ChangeListener; |
| import javax.swing.plaf.ActionMapUIResource; |
| import javax.swing.plaf.ComponentUI; |
| import javax.swing.plaf.ScrollPaneUI; |
| |
| /** |
| * A UI delegate for the {@link JScrollPane} component. |
| */ |
| public class BasicScrollPaneUI extends ScrollPaneUI |
| implements ScrollPaneConstants |
| { |
| |
| /** |
| * Listens for changes in the state of the horizontal scrollbar's model and |
| * updates the scrollpane accordingly. |
| * |
| * @author Roman Kennke (kennke@aicas.com) |
| */ |
| public class HSBChangeListener implements ChangeListener |
| { |
| |
| /** |
| * Receives notification when the state of the horizontal scrollbar |
| * model has changed. |
| * |
| * @param event the change event |
| */ |
| public void stateChanged(ChangeEvent event) |
| { |
| JScrollBar hsb = scrollpane.getHorizontalScrollBar(); |
| JViewport vp = scrollpane.getViewport(); |
| Point viewPosition = vp.getViewPosition(); |
| int xpos = hsb.getValue(); |
| |
| if (xpos != viewPosition.x) |
| { |
| viewPosition.x = xpos; |
| vp.setViewPosition(viewPosition); |
| } |
| |
| viewPosition.y = 0; |
| JViewport columnHeader = scrollpane.getColumnHeader(); |
| if (columnHeader != null |
| && !columnHeader.getViewPosition().equals(viewPosition)) |
| columnHeader.setViewPosition(viewPosition); |
| } |
| |
| } |
| |
| /** |
| * Listens for changes in the state of the vertical scrollbar's model and |
| * updates the scrollpane accordingly. |
| * |
| * @author Roman Kennke (kennke@aicas.com) |
| */ |
| public class VSBChangeListener implements ChangeListener |
| { |
| |
| /** |
| * Receives notification when the state of the vertical scrollbar |
| * model has changed. |
| * |
| * @param event the change event |
| */ |
| public void stateChanged(ChangeEvent event) |
| { |
| JScrollBar vsb = scrollpane.getVerticalScrollBar(); |
| JViewport vp = scrollpane.getViewport(); |
| Point viewPosition = vp.getViewPosition(); |
| int ypos = vsb.getValue(); |
| if (ypos != viewPosition.y) |
| { |
| viewPosition.y = ypos; |
| vp.setViewPosition(viewPosition); |
| } |
| |
| viewPosition.x = 0; |
| JViewport rowHeader = scrollpane.getRowHeader(); |
| if (rowHeader != null |
| && !rowHeader.getViewPosition().equals(viewPosition)) |
| rowHeader.setViewPosition(viewPosition); |
| } |
| |
| } |
| |
| /** |
| * Listens for changes of the viewport's extent size and updates the |
| * scrollpane accordingly. |
| * |
| * @author Roman Kennke (kennke@aicas.com) |
| */ |
| public class ViewportChangeHandler implements ChangeListener |
| { |
| |
| /** |
| * Receives notification when the view's size, position or extent size |
| * changes. When the extents size has changed, this method calls |
| * {@link BasicScrollPaneUI#syncScrollPaneWithViewport()} to adjust the |
| * scrollbars extents as well. |
| * |
| * @param event the change event |
| */ |
| public void stateChanged(ChangeEvent event) |
| { |
| JViewport vp = scrollpane.getViewport(); |
| JScrollBar hsb = scrollpane.getHorizontalScrollBar(); |
| JScrollBar vsb = scrollpane.getVerticalScrollBar(); |
| syncScrollPaneWithViewport(); |
| } |
| |
| } |
| |
| /** |
| * Listens for property changes on the scrollpane and update the view |
| * accordingly. |
| * |
| * @author Roman Kennke (kennke@aicas.com) |
| */ |
| public class PropertyChangeHandler implements PropertyChangeListener |
| { |
| |
| /** |
| * Receives notification when any of the scrollpane's bound property |
| * changes. This method calls the appropriate update method on the |
| * <code>ScrollBarUI</code>. |
| * |
| * @param e the property change event |
| * |
| * @see BasicScrollPaneUI#updateColumnHeader(PropertyChangeEvent) |
| * @see BasicScrollPaneUI#updateRowHeader(PropertyChangeEvent) |
| * @see BasicScrollPaneUI#updateScrollBarDisplayPolicy(PropertyChangeEvent) |
| * @see BasicScrollPaneUI#updateViewport(PropertyChangeEvent) |
| */ |
| public void propertyChange(PropertyChangeEvent e) |
| { |
| String propName = e.getPropertyName(); |
| if (propName.equals("viewport")) |
| updateViewport(e); |
| else if (propName.equals("rowHeader")) |
| updateRowHeader(e); |
| else if (propName.equals("columnHeader")) |
| updateColumnHeader(e); |
| else if (propName.equals("horizontalScrollBarPolicy") |
| || e.getPropertyName().equals("verticalScrollBarPolicy")) |
| updateScrollBarDisplayPolicy(e); |
| else if (propName.equals("verticalScrollBar")) |
| { |
| JScrollBar oldSb = (JScrollBar) e.getOldValue(); |
| oldSb.getModel().removeChangeListener(vsbChangeListener); |
| JScrollBar newSb = (JScrollBar) e.getNewValue(); |
| newSb.getModel().addChangeListener(vsbChangeListener); |
| } |
| else if (propName.equals("horizontalScrollBar")) |
| { |
| JScrollBar oldSb = (JScrollBar) e.getOldValue(); |
| oldSb.getModel().removeChangeListener(hsbChangeListener); |
| JScrollBar newSb = (JScrollBar) e.getNewValue(); |
| newSb.getModel().addChangeListener(hsbChangeListener); |
| } |
| } |
| |
| } |
| |
| /** |
| * Listens for mouse wheel events and update the scrollpane accordingly. |
| * |
| * @author Roman Kennke (kennke@aicas.com) |
| * |
| * @since 1.4 |
| */ |
| protected class MouseWheelHandler implements MouseWheelListener |
| { |
| /** |
| * Use to compute the visible rectangle. |
| */ |
| final Rectangle rect = new Rectangle(); |
| |
| /** |
| * Scroll with the mouse wheel. |
| * |
| * @author Audrius Meskauskas (audriusa@Bioinformatics.org) |
| */ |
| public void mouseWheelMoved(MouseWheelEvent e) |
| { |
| if (scrollpane.getViewport().getComponentCount() == 0) |
| return; |
| |
| Component target = scrollpane.getViewport().getComponent(0); |
| JScrollBar bar = scrollpane.getVerticalScrollBar(); |
| Scrollable scrollable = (target instanceof Scrollable) ? (Scrollable) target |
| : null; |
| |
| boolean tracksHeight = scrollable != null |
| && scrollable.getScrollableTracksViewportHeight(); |
| int wheel = e.getWheelRotation() * ROWS_PER_WHEEL_CLICK; |
| int delta; |
| |
| // If possible, scroll vertically. |
| if (bar != null && ! tracksHeight) |
| { |
| if (scrollable != null) |
| { |
| bounds(target); |
| delta = scrollable.getScrollableUnitIncrement( |
| rect, SwingConstants.VERTICAL, wheel); |
| } |
| else |
| { |
| // Scroll non scrollables. |
| delta = wheel * SCROLL_NON_SCROLLABLES; |
| } |
| scroll(bar, delta); |
| } |
| // If not, try to scroll horizontally |
| else |
| { |
| bar = scrollpane.getHorizontalScrollBar(); |
| boolean tracksWidth = scrollable != null |
| && scrollable.getScrollableTracksViewportWidth(); |
| |
| if (bar != null && ! tracksWidth) |
| { |
| if (scrollable != null) |
| { |
| bounds(target); |
| delta = scrollable.getScrollableUnitIncrement( |
| rect, SwingConstants.HORIZONTAL, wheel); |
| } |
| else |
| { |
| // Scroll non scrollables. |
| delta = wheel * SCROLL_NON_SCROLLABLES; |
| } |
| scroll(bar, delta); |
| } |
| } |
| } |
| |
| /** |
| * Place the component bounds into rect. The x and y values |
| * need to be reversed. |
| * |
| * @param target the target being scrolled |
| */ |
| final void bounds(Component target) |
| { |
| // Viewport bounds, translated by the scroll bar positions. |
| target.getParent().getBounds(rect); |
| rect.x = getValue(scrollpane.getHorizontalScrollBar()); |
| rect.y = getValue(scrollpane.getVerticalScrollBar()); |
| } |
| |
| /** |
| * Get the scroll bar value or 0 if there is no such scroll bar. |
| * |
| * @param bar the scroll bar (<code>null</code> permitted). |
| * |
| * @return The scroll bar value, or 0. |
| */ |
| final int getValue(JScrollBar bar) |
| { |
| return bar != null ? bar.getValue() : 0; |
| } |
| |
| /** |
| * Scroll the given distance. |
| * |
| * @param bar the scrollbar to scroll |
| * @param delta the distance |
| */ |
| final void scroll(JScrollBar bar, int delta) |
| { |
| int y = bar.getValue() + delta; |
| |
| if (y < bar.getMinimum()) |
| y = bar.getMinimum(); |
| if (y > bar.getMaximum()) |
| y = bar.getMaximum(); |
| |
| bar.setValue(y); |
| } |
| } |
| |
| /** |
| * Adds/removes the mouse wheel listener when the component is added/removed |
| * to/from the scroll pane view port. |
| * |
| * @author Audrius Meskauskas (audriusa@bioinformatics.org) |
| */ |
| class ViewportContainerListener implements ContainerListener |
| { |
| /** |
| * Add the mouse wheel listener, allowing to scroll with the mouse. |
| */ |
| public void componentAdded(ContainerEvent e) |
| { |
| e.getChild().addMouseWheelListener(mouseWheelListener); |
| } |
| |
| /** |
| * Remove the mouse wheel listener. |
| */ |
| public void componentRemoved(ContainerEvent e) |
| { |
| e.getChild().removeMouseWheelListener(mouseWheelListener); |
| } |
| } |
| |
| /** |
| * The number of pixels by that we should scroll the content that does |
| * not implement Scrollable. |
| */ |
| static int SCROLL_NON_SCROLLABLES = 10; |
| |
| /** |
| * The number of rows to scroll per mouse wheel click. From impression, |
| * Sun seems using the value 3. |
| */ |
| static int ROWS_PER_WHEEL_CLICK = 3; |
| |
| /** The Scrollpane for which the UI is provided by this class. */ |
| protected JScrollPane scrollpane; |
| |
| /** |
| * The horizontal scrollbar listener. |
| */ |
| protected ChangeListener hsbChangeListener; |
| |
| /** |
| * The vertical scrollbar listener. |
| */ |
| protected ChangeListener vsbChangeListener; |
| |
| /** |
| * The viewport listener. |
| */ |
| protected ChangeListener viewportChangeListener; |
| |
| /** |
| * The scrollpane property change listener. |
| */ |
| protected PropertyChangeListener spPropertyChangeListener; |
| |
| /** |
| * The mousewheel listener for the scrollpane. |
| */ |
| MouseWheelListener mouseWheelListener; |
| |
| /** |
| * The listener to add and remove the mouse wheel listener to/from |
| * the component container. |
| */ |
| ContainerListener containerListener; |
| |
| public static ComponentUI createUI(final JComponent c) |
| { |
| return new BasicScrollPaneUI(); |
| } |
| |
| protected void installDefaults(JScrollPane p) |
| { |
| scrollpane = p; |
| LookAndFeel.installColorsAndFont(p, "ScrollPane.background", |
| "ScrollPane.foreground", |
| "ScrollPane.font"); |
| LookAndFeel.installBorder(p, "ScrollPane.border"); |
| p.setOpaque(true); |
| } |
| |
| protected void uninstallDefaults(JScrollPane p) |
| { |
| p.setForeground(null); |
| p.setBackground(null); |
| p.setFont(null); |
| p.setBorder(null); |
| scrollpane = null; |
| } |
| |
| public void installUI(final JComponent c) |
| { |
| super.installUI(c); |
| installDefaults((JScrollPane) c); |
| installListeners((JScrollPane) c); |
| installKeyboardActions((JScrollPane) c); |
| } |
| |
| /** |
| * Installs the listeners on the scrollbars, the viewport and the scrollpane. |
| * |
| * @param sp the scrollpane on which to install the listeners |
| */ |
| protected void installListeners(JScrollPane sp) |
| { |
| if (spPropertyChangeListener == null) |
| spPropertyChangeListener = createPropertyChangeListener(); |
| sp.addPropertyChangeListener(spPropertyChangeListener); |
| |
| if (hsbChangeListener == null) |
| hsbChangeListener = createHSBChangeListener(); |
| sp.getHorizontalScrollBar().getModel().addChangeListener(hsbChangeListener); |
| |
| if (vsbChangeListener == null) |
| vsbChangeListener = createVSBChangeListener(); |
| sp.getVerticalScrollBar().getModel().addChangeListener(vsbChangeListener); |
| |
| if (viewportChangeListener == null) |
| viewportChangeListener = createViewportChangeListener(); |
| |
| if (mouseWheelListener == null) |
| mouseWheelListener = createMouseWheelListener(); |
| |
| if (containerListener == null) |
| containerListener = new ViewportContainerListener(); |
| |
| JViewport v = sp.getViewport(); |
| v.addChangeListener(viewportChangeListener); |
| v.addContainerListener(containerListener); |
| |
| // Add mouse wheel listeners to the componets that are probably already |
| // in the view port. |
| for (int i = 0; i < v.getComponentCount(); i++) |
| v.getComponent(i).addMouseWheelListener(mouseWheelListener); |
| } |
| |
| InputMap getInputMap(int condition) |
| { |
| if (condition == JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) |
| return (InputMap) UIManager.get("ScrollPane.ancestorInputMap"); |
| return null; |
| } |
| |
| /** |
| * Returns the action map for the {@link JScrollPane}. All scroll panes |
| * share a single action map which is created the first time this method is |
| * called, then stored in the UIDefaults table for subsequent access. |
| * |
| * @return The shared action map. |
| */ |
| ActionMap getActionMap() |
| { |
| ActionMap map = (ActionMap) UIManager.get("ScrollPane.actionMap"); |
| |
| if (map == null) // first time here |
| { |
| map = createActionMap(); |
| if (map != null) |
| UIManager.put("ScrollPane.actionMap", map); |
| } |
| return map; |
| } |
| |
| /** |
| * Creates the action map shared by all {@link JSlider} instances. |
| * This method is called once by {@link #getActionMap()} when it |
| * finds no action map in the UIDefaults table...after the map is |
| * created, it gets added to the defaults table so that subsequent |
| * calls to {@link #getActionMap()} will return the same shared |
| * instance. |
| * |
| * @return The action map. |
| */ |
| ActionMap createActionMap() |
| { |
| ActionMap map = new ActionMapUIResource(); |
| map.put("scrollLeft", |
| new AbstractAction("scrollLeft") { |
| public void actionPerformed(ActionEvent event) |
| { |
| JScrollPane sp = (JScrollPane) event.getSource(); |
| JScrollBar sb = sp.getHorizontalScrollBar(); |
| if (sb.isVisible()) |
| { |
| int delta = sb.getBlockIncrement(-1); |
| sb.setValue(sb.getValue() + delta); |
| } |
| } |
| } |
| ); |
| map.put("scrollEnd", |
| new AbstractAction("scrollEnd") { |
| public void actionPerformed(ActionEvent event) |
| { |
| JScrollPane sp = (JScrollPane) event.getSource(); |
| JScrollBar sb1 = sp.getHorizontalScrollBar(); |
| if (sb1.isVisible()) |
| { |
| sb1.setValue(sb1.getMaximum()); |
| } |
| JScrollBar sb2 = sp.getVerticalScrollBar(); |
| if (sb2.isVisible()) |
| { |
| sb2.setValue(sb2.getMaximum()); |
| } |
| } |
| } |
| ); |
| map.put("unitScrollUp", |
| new AbstractAction("unitScrollUp") { |
| public void actionPerformed(ActionEvent event) |
| { |
| JScrollPane sp = (JScrollPane) event.getSource(); |
| JScrollBar sb = sp.getVerticalScrollBar(); |
| if (sb.isVisible()) |
| { |
| int delta = sb.getUnitIncrement(-1); |
| sb.setValue(sb.getValue() + delta); |
| } |
| } |
| } |
| ); |
| map.put("unitScrollLeft", |
| new AbstractAction("unitScrollLeft") { |
| public void actionPerformed(ActionEvent event) |
| { |
| JScrollPane sp = (JScrollPane) event.getSource(); |
| JScrollBar sb = sp.getHorizontalScrollBar(); |
| if (sb.isVisible()) |
| { |
| int delta = sb.getUnitIncrement(-1); |
| sb.setValue(sb.getValue() + delta); |
| } |
| } |
| } |
| ); |
| map.put("scrollUp", |
| new AbstractAction("scrollUp") { |
| public void actionPerformed(ActionEvent event) |
| { |
| JScrollPane sp = (JScrollPane) event.getSource(); |
| JScrollBar sb = sp.getVerticalScrollBar(); |
| if (sb.isVisible()) |
| { |
| int delta = sb.getBlockIncrement(-1); |
| sb.setValue(sb.getValue() + delta); |
| } |
| } |
| } |
| ); |
| map.put("scrollRight", |
| new AbstractAction("scrollRight") { |
| public void actionPerformed(ActionEvent event) |
| { |
| JScrollPane sp = (JScrollPane) event.getSource(); |
| JScrollBar sb = sp.getHorizontalScrollBar(); |
| if (sb.isVisible()) |
| { |
| int delta = sb.getBlockIncrement(1); |
| sb.setValue(sb.getValue() + delta); |
| } |
| } |
| } |
| ); |
| map.put("scrollHome", |
| new AbstractAction("scrollHome") { |
| public void actionPerformed(ActionEvent event) |
| { |
| JScrollPane sp = (JScrollPane) event.getSource(); |
| JScrollBar sb1 = sp.getHorizontalScrollBar(); |
| if (sb1.isVisible()) |
| { |
| sb1.setValue(sb1.getMinimum()); |
| } |
| JScrollBar sb2 = sp.getVerticalScrollBar(); |
| if (sb2.isVisible()) |
| { |
| sb2.setValue(sb2.getMinimum()); |
| } |
| } |
| } |
| ); |
| map.put("scrollDown", |
| new AbstractAction("scrollDown") { |
| public void actionPerformed(ActionEvent event) |
| { |
| JScrollPane sp = (JScrollPane) event.getSource(); |
| JScrollBar sb = sp.getVerticalScrollBar(); |
| if (sb.isVisible()) |
| { |
| int delta = sb.getBlockIncrement(1); |
| sb.setValue(sb.getValue() + delta); |
| } |
| } |
| } |
| ); |
| map.put("unitScrollDown", |
| new AbstractAction("unitScrollDown") { |
| public void actionPerformed(ActionEvent event) |
| { |
| JScrollPane sp = (JScrollPane) event.getSource(); |
| JScrollBar sb = sp.getVerticalScrollBar(); |
| if (sb.isVisible()) |
| { |
| int delta = sb.getUnitIncrement(1); |
| sb.setValue(sb.getValue() + delta); |
| } |
| } |
| } |
| ); |
| map.put("unitScrollRight", |
| new AbstractAction("unitScrollRight") { |
| public void actionPerformed(ActionEvent event) |
| { |
| JScrollPane sp = (JScrollPane) event.getSource(); |
| JScrollBar sb = sp.getHorizontalScrollBar(); |
| if (sb.isVisible()) |
| { |
| int delta = sb.getUnitIncrement(1); |
| sb.setValue(sb.getValue() + delta); |
| } |
| } |
| } |
| ); |
| return map; |
| } |
| |
| /** |
| * Installs additional keyboard actions on the scrollpane. This is a hook |
| * method provided to subclasses in order to install their own keyboard |
| * actions. |
| * |
| * @param sp the scrollpane to install keyboard actions on |
| */ |
| protected void installKeyboardActions(JScrollPane sp) |
| { |
| InputMap keyMap = getInputMap( |
| JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); |
| SwingUtilities.replaceUIInputMap(sp, |
| JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, keyMap); |
| ActionMap map = getActionMap(); |
| SwingUtilities.replaceUIActionMap(sp, map); |
| } |
| |
| /** |
| * Uninstalls all keyboard actions from the JScrollPane that have been |
| * installed by {@link #installKeyboardActions}. This is a hook method |
| * provided to subclasses to add their own keyboard actions. |
| * |
| * @param sp the scrollpane to uninstall keyboard actions from |
| */ |
| protected void uninstallKeyboardActions(JScrollPane sp) |
| { |
| SwingUtilities.replaceUIActionMap(sp, null); |
| SwingUtilities.replaceUIInputMap(sp, |
| JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, null); |
| } |
| |
| /** |
| * Creates and returns the change listener for the horizontal scrollbar. |
| * |
| * @return the change listener for the horizontal scrollbar |
| */ |
| protected ChangeListener createHSBChangeListener() |
| { |
| return new HSBChangeListener(); |
| } |
| |
| /** |
| * Creates and returns the change listener for the vertical scrollbar. |
| * |
| * @return the change listener for the vertical scrollbar |
| */ |
| protected ChangeListener createVSBChangeListener() |
| { |
| return new VSBChangeListener(); |
| } |
| |
| /** |
| * Creates and returns the change listener for the viewport. |
| * |
| * @return the change listener for the viewport |
| */ |
| protected ChangeListener createViewportChangeListener() |
| { |
| return new ViewportChangeHandler(); |
| } |
| |
| /** |
| * Creates and returns the property change listener for the scrollpane. |
| * |
| * @return the property change listener for the scrollpane |
| */ |
| protected PropertyChangeListener createPropertyChangeListener() |
| { |
| return new PropertyChangeHandler(); |
| } |
| |
| /** |
| * Creates and returns the mouse wheel listener for the scrollpane. |
| * |
| * @return the mouse wheel listener for the scrollpane |
| * |
| * @since 1.4 |
| */ |
| protected MouseWheelListener createMouseWheelListener() |
| { |
| return new MouseWheelHandler(); |
| } |
| |
| public void uninstallUI(final JComponent c) |
| { |
| super.uninstallUI(c); |
| this.uninstallDefaults((JScrollPane) c); |
| uninstallListeners((JScrollPane) c); |
| installKeyboardActions((JScrollPane) c); |
| } |
| |
| /** |
| * Uninstalls all the listeners that have been installed in |
| * {@link #installListeners(JScrollPane)}. |
| * |
| * @param c the scrollpane from which to uninstall the listeners |
| */ |
| protected void uninstallListeners(JComponent c) |
| { |
| JScrollPane sp = (JScrollPane) c; |
| sp.removePropertyChangeListener(spPropertyChangeListener); |
| sp.getHorizontalScrollBar().getModel() |
| .removeChangeListener(hsbChangeListener); |
| sp.getVerticalScrollBar().getModel() |
| .removeChangeListener(vsbChangeListener); |
| |
| JViewport v = sp.getViewport(); |
| v.removeChangeListener(viewportChangeListener); |
| v.removeContainerListener(containerListener); |
| |
| for (int i = 0; i < v.getComponentCount(); i++) |
| v.getComponent(i).removeMouseWheelListener(mouseWheelListener); |
| |
| } |
| |
| public Dimension getMinimumSize(JComponent c) |
| { |
| JScrollPane p = (JScrollPane) c; |
| ScrollPaneLayout sl = (ScrollPaneLayout) p.getLayout(); |
| return sl.minimumLayoutSize(c); |
| } |
| |
| public void paint(Graphics g, JComponent c) |
| { |
| // do nothing; the normal painting-of-children algorithm, along with |
| // ScrollPaneLayout, does all the relevant work. |
| } |
| |
| /** |
| * Synchronizes the scrollbars with the viewport's extents. |
| */ |
| protected void syncScrollPaneWithViewport() |
| { |
| JViewport vp = scrollpane.getViewport(); |
| |
| // Update the horizontal scrollbar. |
| JScrollBar hsb = scrollpane.getHorizontalScrollBar(); |
| hsb.setMaximum(vp.getViewSize().width); |
| hsb.setValue(vp.getViewPosition().x); |
| hsb.setVisibleAmount(vp.getExtentSize().width); |
| |
| // Update the vertical scrollbar. |
| JScrollBar vsb = scrollpane.getVerticalScrollBar(); |
| vsb.setMaximum(vp.getViewSize().height); |
| vsb.setValue(vp.getViewPosition().y); |
| vsb.setVisibleAmount(vp.getExtentSize().height); |
| } |
| |
| /** |
| * Receives notification when the <code>columnHeader</code> property has |
| * changed on the scrollpane. |
| * |
| * @param ev the property change event |
| */ |
| protected void updateColumnHeader(PropertyChangeEvent ev) |
| { |
| // TODO: Find out what should be done here. Or is this only a hook? |
| } |
| |
| /** |
| * Receives notification when the <code>rowHeader</code> property has changed |
| * on the scrollpane. |
| * |
| * @param ev the property change event |
| */ |
| protected void updateRowHeader(PropertyChangeEvent ev) |
| { |
| // TODO: Find out what should be done here. Or is this only a hook? |
| } |
| |
| /** |
| * Receives notification when the <code>scrollBarDisplayPolicy</code> |
| * property has changed on the scrollpane. |
| * |
| * @param ev the property change event |
| */ |
| protected void updateScrollBarDisplayPolicy(PropertyChangeEvent ev) |
| { |
| // TODO: Find out what should be done here. Or is this only a hook? |
| } |
| |
| /** |
| * Receives notification when the <code>viewport</code> property has changed |
| * on the scrollpane. |
| * |
| * This method sets removes the viewportChangeListener from the old viewport |
| * and adds it to the new viewport. |
| * |
| * @param ev the property change event |
| */ |
| protected void updateViewport(PropertyChangeEvent ev) |
| { |
| JViewport oldViewport = (JViewport) ev.getOldValue(); |
| oldViewport.removeChangeListener(viewportChangeListener); |
| JViewport newViewport = (JViewport) ev.getNewValue(); |
| newViewport.addChangeListener(viewportChangeListener); |
| syncScrollPaneWithViewport(); |
| } |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |