Google Tag Manager

2010/08/16

Kinetic Scrolling JScrollPane

Code

class KineticScrollingListener2 extends MouseAdapter implements HierarchyListener {
  protected static final int SPEED = 4;
  protected static final int DELAY = 10;
  protected static final double D = .8;
  protected final JComponent label;
  protected final Point startPt = new Point();
  protected final Point delta = new Point();
  protected final Cursor dc;
  protected final Cursor hc = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
  protected final Timer inside = new Timer(DELAY, null);
  protected final Timer outside = new Timer(DELAY, null);

  protected static boolean isInside(JViewport viewport, JComponent comp) {
    Point vp = viewport.getViewPosition();
    return vp.x >= 0 && vp.x + viewport.getWidth() - comp.getWidth() <= 0
        && vp.y >= 0 && vp.y + viewport.getHeight() - comp.getHeight() <= 0;
  }

  protected KineticScrollingListener2(JComponent comp) {
    super();
    this.label = comp;
    this.dc = comp.getCursor();
    inside.addActionListener(e -> dragInside());
    outside.addActionListener(e -> dragOutside());
  }

  private void dragInside() {
    JViewport viewport = (JViewport) SwingUtilities.getUnwrappedParent(label);
    Point vp = viewport.getViewPosition();
    // System.out.format("s: %s, %s%n", delta, vp);
    vp.translate(-delta.x, -delta.y);
    viewport.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 + viewport.getWidth() - label.getWidth() > 0) {
        delta.x = (int) (delta.x * D);
      }
      if (vp.y < 0 || vp.y + viewport.getHeight() - label.getHeight() > 0) {
        delta.y = (int) (delta.y * D);
      }
    } else {
      inside.stop();
      if (!isInside(viewport, label)) {
        outside.start();
      }
    }
  }

  private void dragOutside() {
    JViewport viewport = (JViewport) SwingUtilities.getUnwrappedParent(label);
    Point vp = viewport.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 + viewport.getWidth() - label.getWidth() > 0) {
      vp.x = (int) (vp.x - (vp.x + viewport.getWidth() - label.getWidth()) * (1d - D));
    }
    if (vp.y + viewport.getHeight() > label.getHeight()) {
      vp.y = (int) (vp.y - (vp.y + viewport.getHeight() - label.getHeight()) * (1d - D));
    }
    viewport.setViewPosition(vp);
    if (isInside(viewport, label)) {
      outside.stop();
    }
  }

  @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 viewport = (JViewport) SwingUtilities.getUnwrappedParent(label);
    Point vp = viewport.getViewPosition();
    vp.translate(startPt.x - pt.x, startPt.y - pt.y);
    viewport.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 viewport = (JViewport) SwingUtilities.getUnwrappedParent(label);
    if (isInside(viewport, label)) {
      inside.start();
    } else {
      outside.start();
    }
  }

  @Override public void hierarchyChanged(HierarchyEvent e) {
    Component c = e.getComponent();
    if ((e.getChangeFlags() & HierarchyEvent.DISPLAYABILITY_CHANGED) != 0
        && !c.isDisplayable()) {
      inside.stop();
      outside.stop();
    }
  }
}

References

2010/08/09

Drag and Drop between JLists

Code

class ListItemTransferHandler extends TransferHandler {
  protected final DataFlavor localObjectFlavor;
  protected JList<?> source;
  protected int[] indices;
  protected int addIndex = -1;
  protected int addCount;

  protected ListItemTransferHandler() {
    super();
    localObjectFlavor = new DataFlavor(List.class, "List of items");
  }

  @Override protected Transferable createTransferable(JComponent c) {
    source = (JList<?>) c;
    indices = source.getSelectedIndices();
    List<?> transferredObjects = source.getSelectedValuesList();
    return new Transferable() {
      @Override public DataFlavor[] getTransferDataFlavors() {
        return new DataFlavor[] {localObjectFlavor};
      }

      @Override public boolean isDataFlavorSupported(DataFlavor flavor) {
        return Objects.equals(localObjectFlavor, flavor);
      }

      @Override public Object getTransferData(DataFlavor flavor)
          throws UnsupportedFlavorException, IOException {
        if (isDataFlavorSupported(flavor)) {
          return transferredObjects;
        } else {
          throw new UnsupportedFlavorException(flavor);
        }
      }
    };
  }

  @Override public boolean canImport(TransferHandler.TransferSupport info) {
    return info.isDrop() && info.isDataFlavorSupported(localObjectFlavor);
  }

  @Override public int getSourceActions(JComponent c) {
    return TransferHandler.MOVE;
  }

  @SuppressWarnings("unchecked")
  @Override public boolean importData(TransferHandler.TransferSupport info) {
    TransferHandler.DropLocation tdl = info.getDropLocation();
    if (!(tdl instanceof JList.DropLocation)) {
      return false;
    }
    JList.DropLocation dl = (JList.DropLocation) tdl;
    JList<?> target = (JList<?>) info.getComponent();
    DefaultListModel listModel = (DefaultListModel) target.getModel();
    int max = listModel.getSize();
    int index = dl.getIndex();
    index = index < 0 ? max : index;
    index = Math.min(index, max);
    addIndex = index;
    try {
      List<?> values = (List<?>) info.getTransferable().getTransferData(
        localObjectFlavor);
      for (Object o : values) {
        int i = index++;
        listModel.add(i, o);
        target.addSelectionInterval(i, i);
      }
      // ---->
      addCount = target.equals(source) ? values.size() : 0;
      // <----
      return true;
    } catch (UnsupportedFlavorException | IOException ex) {
      ex.printStackTrace();
    }
    return false;
  }
  // ...

References

2010/08/02

Transparent, Translucent JTable

Code

JScrollPane scroll = new JScrollPane(table) {
  private final TexturePaint texture = makeImageTexture();
  @Override protected JViewport createViewport() {
    return new JViewport() {
      @Override protected void paintComponent(Graphics g) {
        if (texture != null) {
          Graphics2D g2 = (Graphics2D) g;
          g2.setPaint(texture);
          g2.fillRect(0, 0, getWidth(), getHeight());
        }
        super.paintComponent(g);
      }
    };
  }
};
Color alphaZero = new Color(0x0, true);
table.setOpaque(false);
table.setBackground(alphaZero);
scroll.getViewport().setOpaque(false);
scroll.getViewport().setBackground(alphaZero);

References