// -*- mode:java; encoding:utf-8 -*-
// vim:set fileencoding=utf-8:
// @homepage@

package example;

import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.stream.IntStream;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;

public final class MainPanel extends JPanel {
  private MainPanel() {
    super(new BorderLayout());

    String[] columnNames = {"String", "Integer", "Boolean"};
    DefaultTableModel model = new DefaultTableModel(null, columnNames) {
      @Override public Class<?> getColumnClass(int column) {
        return getValueAt(0, column).getClass();
      }
    };

    IntStream.range(0, 1000)
      .mapToObj(i -> new Object[] {"aaaaa", i, i % 2 == 0})
      .forEach(model::addRow);

    JTable table = new JTable(model) {
      private transient MouseAdapter handler;
      @Override public void updateUI() {
        removeMouseMotionListener(handler);
        removeMouseListener(handler);
        super.updateUI();
        handler = new DragScrollingListener(this);
        addMouseMotionListener(handler);
        addMouseListener(handler);
      }
    };
    JScrollPane scroll = new JScrollPane(table);
    scroll.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
    add(scroll);
    setPreferredSize(new Dimension(320, 240));
  }

  public static void main(String... args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        createAndShowGui();
      }
    });
  }

  public static void createAndShowGui() {
    try {
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
      ex.printStackTrace();
      Toolkit.getDefaultToolkit().beep();
    }
    JFrame frame = new JFrame("@title@");
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    frame.getContentPane().add(new MainPanel());
    frame.pack();
    frame.setLocationRelativeTo(null);
    frame.setVisible(true);
  }
}

class DragScrollingListener extends MouseAdapter {
  private static final int VELOCITY = 5;
  private static final int DELAY = 10;
  private static final double GRAVITY = .95;
  private final Cursor dc = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
  private final Cursor hc = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
  private final Timer scroller;
  private final Point startPt = new Point();
  private final Point delta = new Point();

  protected DragScrollingListener(JComponent c) {
    super();
    this.scroller = new Timer(DELAY, e -> {
      JViewport vport = (JViewport) SwingUtilities.getUnwrappedParent(c);
      Point vp = vport.getViewPosition();
      vp.translate(-delta.x, -delta.y);
      c.scrollRectToVisible(new Rectangle(vp, vport.getSize()));
      if (Math.abs(delta.x) > 0 || Math.abs(delta.y) > 0) {
        delta.setLocation((int) (delta.x * GRAVITY), (int) (delta.y * GRAVITY));
      } else {
        ((Timer) e.getSource()).stop();
      }
    });
  }

  @Override public void mousePressed(MouseEvent e) {
    Component c = e.getComponent();
    c.setCursor(hc);
    c.setEnabled(false);
    Container p = SwingUtilities.getUnwrappedParent(c);
    if (p instanceof JViewport) {
      JViewport vport = (JViewport) p;
      Point cp = SwingUtilities.convertPoint(c, e.getPoint(), vport);
      startPt.setLocation(cp);
      scroller.stop();
    }
  }

  @Override public void mouseDragged(MouseEvent e) {
    Component c = e.getComponent();
    Container p = SwingUtilities.getUnwrappedParent(c);
    if (p instanceof JViewport) {
      JViewport vport = (JViewport) p;
      Point cp = SwingUtilities.convertPoint(c, e.getPoint(), vport);
      Point vp = vport.getViewPosition();
      vp.translate(startPt.x - cp.x, startPt.y - cp.y);
      delta.setLocation(VELOCITY * (cp.x - startPt.x), VELOCITY * (cp.y - startPt.y));
      ((JComponent) c).scrollRectToVisible(new Rectangle(vp, vport.getSize()));
      startPt.setLocation(cp);
    }
  }

  @Override public void mouseReleased(MouseEvent e) {
    Component c = e.getComponent();
    c.setCursor(dc);
    c.setEnabled(true);
    scroller.start();
  }
}

@@ -1128,32 +1128,132 @@
 andler);%0A      %7D
+%0A%0A      @Override public boolean isCellEditable(int row, int column) %7B%0A        return false;%0A      %7D
 %0A    %7D;%0A    JScr
@@ -2249,30 +2249,29 @@
 dapter %7B%0A  p
-rivate
+ublic
  static fina
@@ -2289,30 +2289,29 @@
 ITY = 5;%0A  p
-rivate
+ublic
  static fina
@@ -2331,22 +2331,21 @@
  10;%0A  p
-rivate
+ublic
  static 
@@ -3428,58 +3428,28 @@
     
-JViewport vport = (JViewport) p;%0A      Point cp = 
+startPt.setLocation(
 Swin
@@ -3493,44 +3493,10 @@
 (), 
-vport);%0A      startPt.setLocation(c
 p
+)
 );%0A 

cell editable false