Created
December 28, 2016 05:57
-
-
Save aterai/997c15af2db378efa4cd7834ee39e57e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//package example; | |
//-*- mode:java; encoding:utf-8 -*- | |
// vim:set fileencoding=utf-8: | |
//@homepage@ | |
import java.awt.*; | |
import java.awt.event.*; | |
import java.util.*; | |
import javax.swing.*; | |
import javax.swing.Timer; | |
import javax.swing.tree.*; | |
public final class KineticScrollingViewPositionTest { | |
private JComponent makeUI() { | |
JTree tree = new JTree(); | |
tree.setOpaque(false); | |
JScrollPane scroll = new JScrollPane(tree); | |
JViewport viewport = new JViewport() { | |
private boolean validateIsAdjusting; | |
@Override public void revalidate() { | |
if (validateIsAdjusting) { | |
return; | |
} | |
super.revalidate(); | |
} | |
@Override public void setViewPosition(Point p) { | |
validateIsAdjusting = true; | |
super.setViewPosition(p); | |
validateIsAdjusting = false; | |
} | |
}; | |
viewport.setView(tree); | |
//viewport.setScrollMode(JViewport.BACKINGSTORE_SCROLL_MODE); | |
viewport.setBackground(tree.getBackground()); | |
scroll.setViewport(viewport); | |
MouseAdapter ma1 = new KineticScrollingListener2(tree); | |
viewport.addMouseMotionListener(ma1); | |
viewport.addMouseListener(ma1); | |
MouseAdapter dispatcher = new MouseAdapter() { | |
private void dispatchEvent(MouseEvent e) { | |
JComponent c = (JComponent) e.getComponent(); | |
JComponent p = (JComponent) e.getComponent().getParent(); | |
p.dispatchEvent(SwingUtilities.convertMouseEvent(c, e, p)); | |
} | |
@Override public void mouseDragged(MouseEvent e) { | |
dispatchEvent(e); | |
} | |
@Override public void mouseClicked(MouseEvent e) { | |
dispatchEvent(e); | |
} | |
@Override public void mouseEntered(MouseEvent e) { | |
dispatchEvent(e); | |
} | |
@Override public void mouseExited(MouseEvent e) { | |
dispatchEvent(e); | |
} | |
@Override public void mousePressed(MouseEvent e) { | |
dispatchEvent(e); | |
} | |
@Override public void mouseReleased(MouseEvent e) { | |
dispatchEvent(e); | |
} | |
}; | |
tree.addMouseMotionListener(dispatcher); | |
tree.addMouseListener(dispatcher); | |
return scroll; | |
} | |
public static void main(String... args) { | |
EventQueue.invokeLater(() -> { | |
createAndShowGUI(); | |
}); | |
} | |
public static void createAndShowGUI() { | |
try { | |
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); | |
} catch (ClassNotFoundException | InstantiationException | |
| IllegalAccessException | UnsupportedLookAndFeelException ex) { | |
ex.printStackTrace(); | |
} | |
JFrame frame = new JFrame(); | |
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); | |
frame.getContentPane().add(new KineticScrollingViewPositionTest().makeUI()); | |
frame.setSize(320, 240); | |
frame.setLocationRelativeTo(null); | |
frame.setVisible(true); | |
} | |
} | |
class KineticScrollingListener2 extends MouseAdapter implements HierarchyListener { | |
private static final int SPEED = 4; | |
private static final int DELAY = 10; | |
private static final double D = .8; | |
private final JComponent label; | |
private final Point startPt = new Point(); | |
private final Point delta = new Point(); | |
private final Cursor dc; | |
private final Cursor hc = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR); | |
private final Timer inside = new Timer(DELAY, new ActionListener() { | |
@Override public void actionPerformed(ActionEvent e) { | |
JViewport vport = (JViewport) SwingUtilities.getUnwrappedParent(label); | |
Point vp = vport.getViewPosition(); | |
//System.out.format("s: %s, %s%n", delta, vp); | |
vp.translate(-delta.x, -delta.y); | |
vport.setViewPosition(vp); | |
if (Math.abs(delta.x) > 0 || Math.abs(delta.y) > 0) { | |
delta.setLocation((int)(delta.x * D), (int)(delta.y * D)); | |
//Outside | |
if (vp.x < 0 || vp.x + vport.getWidth() - label.getWidth() > 0) { | |
delta.x = (int)(delta.x * D); | |
} | |
if (vp.y < 0 || vp.y + vport.getHeight() - label.getHeight() > 0) { | |
delta.y = (int)(delta.y * D); | |
} | |
} else { | |
//inside.stop(); | |
((Timer) e.getSource()).stop(); | |
if (!isInside(vport, label)) { | |
outside.start(); | |
} | |
} | |
} | |
}); | |
private final Timer outside = new Timer(DELAY, new ActionListener() { | |
@Override public void actionPerformed(ActionEvent e) { | |
JViewport vport = (JViewport) SwingUtilities.getUnwrappedParent(label); | |
Point vp = vport.getViewPosition(); | |
//System.out.format("r: %s%n", vp); | |
if (vp.x < 0) { | |
vp.x = (int)(vp.x * D); | |
} | |
if (vp.y < 0) { | |
vp.y = (int)(vp.y * D); | |
} | |
if (vp.x + vport.getWidth() - label.getWidth() > 0) { | |
vp.x = (int)(vp.x - (vp.x + vport.getWidth() - label.getWidth()) * (1d - D)); | |
} | |
if (vp.y + vport.getHeight() > label.getHeight()) { | |
vp.y = (int)(vp.y - (vp.y + vport.getHeight() - label.getHeight()) * (1d - D)); | |
} | |
vport.setViewPosition(vp); | |
if (isInside(vport, label)) { | |
//outside.stop(); | |
((Timer) e.getSource()).stop(); | |
} | |
} | |
}); | |
private static boolean isInside(JViewport vport, JComponent comp) { | |
Point vp = vport.getViewPosition(); | |
return vp.x >= 0 && vp.x + vport.getWidth() - comp.getWidth() <= 0 | |
&& vp.y >= 0 && vp.y + vport.getHeight() - comp.getHeight() <= 0; | |
} | |
protected KineticScrollingListener2(JComponent comp) { | |
super(); | |
this.label = comp; | |
this.dc = comp.getCursor(); | |
} | |
@Override public void mousePressed(MouseEvent e) { | |
e.getComponent().setCursor(hc); | |
startPt.setLocation(e.getPoint()); | |
inside.stop(); | |
outside.stop(); | |
} | |
@Override public void mouseDragged(MouseEvent e) { | |
Point pt = e.getPoint(); | |
JViewport vport = (JViewport) SwingUtilities.getUnwrappedParent(label); | |
Point vp = vport.getViewPosition(); | |
vp.translate(startPt.x - pt.x, startPt.y - pt.y); | |
vport.setViewPosition(vp); | |
delta.setLocation(SPEED * (pt.x - startPt.x), SPEED * (pt.y - startPt.y)); | |
startPt.setLocation(pt); | |
} | |
@Override public void mouseReleased(MouseEvent e) { | |
e.getComponent().setCursor(dc); | |
JViewport vport = (JViewport) SwingUtilities.getUnwrappedParent(label); | |
if (isInside(vport, label)) { | |
inside.start(); | |
} else { | |
outside.start(); | |
} | |
} | |
@Override public void hierarchyChanged(HierarchyEvent e) { | |
if ((e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0 && !e.getComponent().isDisplayable()) { | |
inside.stop(); | |
outside.stop(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment