📄 scrollpaneui.java
字号:
package com.digitprop.tonic;
import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;
import javax.swing.plaf.*;
/** UI delegate for JScrollPanes.
*
* @author Markus Fischer
*
* <p>This software is under the <a href="http://www.gnu.org/copyleft/lesser.html" target="_blank">GNU Lesser General Public License</a>
*/
/*
* ------------------------------------------------------------------------
* Copyright (C) 2004 Markus Fischer
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
* You can contact the author at:
* Markus Fischer
* www.digitprop.com
* info@digitprop.com
* ------------------------------------------------------------------------
*/
public class ScrollPaneUI extends javax.swing.plaf.ScrollPaneUI implements ScrollPaneConstants
{
/** The underlying scroll pane */
protected JScrollPane scrollpane;
protected ChangeListener vsbChangeListener;
protected ChangeListener hsbChangeListener;
protected ChangeListener viewportChangeListener;
protected PropertyChangeListener spPropertyChangeListener;
private MouseWheelListener mouseScrollListener;
/** PropertyChangeListener installed on the vertical scrollbar. */
private PropertyChangeListener vsbPropertyChangeListener;
/** PropertyChangeListener installed on the horizontal scrollbar. */
private PropertyChangeListener hsbPropertyChangeListener;
/** The default implementation of createHSBPropertyChangeListener and
* createVSBPropertyChangeListener share the PropertyChangeListener, which
* is this ivar.
*/
private PropertyChangeListener sbPropertyChangeListener;
/** 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;
/** Creates and returns the UI delegate for the specified component */
public static ComponentUI createUI(JComponent component)
{
return new ScrollPaneUI();
}
/** Paints the specified component */
public void paint(Graphics g, JComponent c)
{
// Overridden to prevent superclass from painting anything
}
/** Returns the preferred size of the specified component. In this case,
* this will be null to indicate to the LayoutManager that it must
* compute this value.
*/
public Dimension getPreferredSize(JComponent c)
{
return null;
}
/** Returns the minimum size of the specified component */
public Dimension getMinimumSize(JComponent c)
{
return getPreferredSize(c);
}
/** Returns the maximum size of the specified component */
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);
}
scrollpane.setLayout(new TonicScrollPaneLayout());
scrollpane.setCorner(JScrollPane.UPPER_RIGHT_CORNER, new UpperRightCorner());
}
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);
ActionMap actionMap = getActionMap();
SwingUtilities.replaceUIActionMap(c, actionMap);
}
InputMap getInputMap(int condition) {
if (condition == JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT) {
InputMap keyMap = (InputMap)UIManager.get("ScrollPane.ancestorInputMap");
InputMap rtlKeyMap;
if (scrollpane.getComponentOrientation().isLeftToRight() ||
((rtlKeyMap = (InputMap)UIManager.get("ScrollPane.ancestorInputMap.RightToLeft")) == null)) {
return keyMap;
} else {
rtlKeyMap.setParent(keyMap);
return rtlKeyMap;
}
}
return null;
}
ActionMap getActionMap() {
ActionMap map = (ActionMap)UIManager.get("ScrollPane.actionMap");
if (map == null) {
map = createActionMap();
if (map != null) {
UIManager.getLookAndFeelDefaults().put("ScrollPane.actionMap",
map);
}
}
return map;
}
ActionMap createActionMap() {
ActionMap map = new ActionMapUIResource();
map.put("scrollUp", new ScrollAction("scrollUp", SwingConstants.
VERTICAL, -1, true));
map.put("scrollDown", new ScrollAction("scrollDown",
SwingConstants.VERTICAL, 1, true));
map.put("scrollHome", new ScrollHomeAction("ScrollHome"));
map.put("scrollEnd", new ScrollEndAction("ScrollEnd"));
map.put("unitScrollUp", new ScrollAction
("UnitScrollUp", SwingConstants.VERTICAL, -1,false));
map.put("unitScrollDown", new ScrollAction
("UnitScrollDown", SwingConstants.VERTICAL, 1, false));
if (scrollpane.getComponentOrientation().isLeftToRight()) {
map.put("scrollLeft", new ScrollAction("scrollLeft",
SwingConstants.HORIZONTAL, -1, true));
map.put("scrollRight", new ScrollAction("ScrollRight",
SwingConstants.HORIZONTAL, 1, true));
map.put("unitScrollRight", new ScrollAction
("UnitScrollRight", SwingConstants.HORIZONTAL, 1, false));
map.put("unitScrollLeft", new ScrollAction
("UnitScrollLeft", SwingConstants.HORIZONTAL, -1, false));
} else {
map.put("scrollLeft", new ScrollAction("scrollLeft",
SwingConstants.HORIZONTAL, 1, true));
map.put("scrollRight", new ScrollAction("ScrollRight",
SwingConstants.HORIZONTAL, -1, true));
map.put("unitScrollRight", new ScrollAction
("UnitScrollRight", SwingConstants.HORIZONTAL, -1, false));
map.put("unitScrollLeft", new ScrollAction
("UnitScrollLeft", SwingConstants.HORIZONTAL, 1, false));
}
return map;
}
/** Installs the UI settings for the specified component */
public void installUI(JComponent component)
{
scrollpane= (JScrollPane) component;
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;
}
protected void uninstallKeyboardActions(JScrollPane c) {
SwingUtilities.replaceUIActionMap(c, null);
SwingUtilities.replaceUIInputMap(c, JComponent.
WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, null);
}
/** Uninstalls the UI settings from the specified component */
public void uninstallUI(JComponent c)
{
uninstallDefaults(scrollpane);
uninstallListeners(scrollpane);
uninstallKeyboardActions(scrollpane);
scrollpane= null;
}
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));
}
}
}
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);
}
}
}
/** Listener for Viewport events */
public class ViewportChangeHandler implements ChangeListener
{
public void stateChanged(ChangeEvent e)
{
syncScrollPaneWithViewport();
}
}
protected ChangeListener createViewportChangeListener() {
return new ViewportChangeHandler();
}
/**
* Horizontal scrollbar listener.
*/
public class HSBChangeListener implements ChangeListener
{
public void stateChanged(ChangeEvent e)
{
JViewport viewport = scrollpane.getViewport();
if (viewport != null) {
BoundedRangeModel model = (BoundedRangeModel)(e.getSource());
Point p = viewport.getViewPosition();
int value = model.getValue();
if (scrollpane.getComponentOrientation().isLeftToRight()) {
p.x = value;
} else {
int max = viewport.getViewSize().width;
int extent = viewport.getExtentSize().width;
int oldX = p.x;
/* Set new X coordinate based on "value".
*/
p.x = max - extent - value;
/* If setValue() was called before "extent" was fixed,
* turn setValueCalled flag on.
*/
if ((extent == 0) && (value != 0) && (oldX == max)) {
setValueCalled = true;
} else {
/* When a pane without a horizontal scroll bar was
* reduced and the bar appeared, the viewport should
* show the right side of the view.
*/
if ((extent != 0) && (oldX < 0) && (p.x == 0)) {
p.x += value;
}
}
}
viewport.setViewPosition(p);
}
}
}
/**
* Returns a <code>PropertyChangeListener</code> that will be installed
* on the horizontal <code>JScrollBar</code>.
*/
private PropertyChangeListener createHSBPropertyChangeListener() {
return getSBPropertyChangeListener();
}
/**
* Returns a shared <code>PropertyChangeListener</code> that will update
* the listeners installed on the scrollbars as the model changes.
*/
private PropertyChangeListener getSBPropertyChangeListener() {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -