Google Tag Manager

Showing posts with label TransferHandler. Show all posts
Showing posts with label TransferHandler. Show all posts

2018/06/29

aterai

Move items by copying and pasting between JLists

Code

class ListPopupMenu extends JPopupMenu {
  private final JMenuItem cutItem;
  private final JMenuItem copyItem;
  protected ListPopupMenu(JList list) {
    super();
    Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
    TransferHandler handler = list.getTransferHandler();
    cutItem = add("cut");
    cutItem.addActionListener(e -> {
      handler.exportToClipboard(list, clipboard, TransferHandler.MOVE);
    });
    copyItem = add("copy");
    copyItem.addActionListener(e -> {
      handler.exportToClipboard(list, clipboard, TransferHandler.COPY);
    });
    add("paste").addActionListener(e -> {
      handler.importData(list, clipboard.getContents(null));
    });
    addSeparator();
    add("clearSelection").addActionListener(e -> list.clearSelection());
  }
  @Override public void show(Component c, int x, int y) {
    if (c instanceof JList) {
      boolean isSelected = !((JList) c).isSelectionEmpty();
      cutItem.setEnabled(isSelected);
      copyItem.setEnabled(isSelected);
      super.show(c, x, y);
    }
  }
}

// ...
private static int getIndex(TransferHandler.TransferSupport info) {
  JList target = (JList) info.getComponent();
  int index; // = dl.getIndex();
  if (info.isDrop()) { // Mouse Drag & Drop
    System.out.println("Mouse Drag & Drop");
    TransferHandler.DropLocation tdl = info.getDropLocation();
    if (tdl instanceof JList.DropLocation) {
      index = ((JList.DropLocation) tdl).getIndex();
    } else {
      index = target.getSelectedIndex();
    }
  } else { // Keyboard Copy & Paste
    index = target.getSelectedIndex();
  }
  DefaultListModel listModel = (DefaultListModel) target.getModel();
  // boolean insert = dl.isInsert();
  int max = listModel.getSize();
  // int index = dl.getIndex();
  index = index < 0 ? max : index; // If it is out of range, it is appended to the end
  index = Math.min(index, max);
  return index;
}

References

2015/08/13

aterai

Create a custom drag ghost image

Code

class ListItemTransferHandler extends TransferHandler {
  @Override public int getSourceActions(JComponent c) {
    System.out.println("getSourceActions");
    if (!(c instanceof JList)) {
      return NONE;
    }
    JList source = (JList) c;
    Point pt;
    if (compact) {
      int w = source.getFixedCellWidth();
      int h = source.getFixedCellHeight() - 20; //TODO
      setDragImage(createCompactDragImage(source, w, h));
      pt = new Point(w / 2, h);
    } else {
      setDragImage(createDragImage(source));
      pt = c.getMousePosition();
    }
    if (pt != null) {
      setDragImageOffset(pt);
    }
    return MOVE; //TransferHandler.COPY_OR_MOVE;
  }
  private static BufferedImage createDragImage(JList source) {
    int w = source.getWidth();
    int h = source.getHeight();
    BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
    Graphics g = bi.getGraphics();
    DefaultListCellRenderer renderer =
      (DefaultListCellRenderer) source.getCellRenderer();
    for (int i : source.getSelectedIndices()) {
      Component c = renderer.getListCellRendererComponent(
          source, source.getModel().getElementAt(i), i, false, false);
      Rectangle rect = source.getCellBounds(i, i);
      SwingUtilities.paintComponent(g, c, source, rect);
    }
    g.dispose();
    return bi;
  }
  private BufferedImage createCompactDragImage(JList source, int w, int h) {
    BufferedImage br = null;
    if (w > 0 && h > 0) {
      br = source.getGraphicsConfiguration().createCompatibleImage(
          w, h, Transparency.TRANSLUCENT);
    } else {
      return null;
    }
    int[] selectedIndices = source.getSelectedIndices();
    int length = selectedIndices.length;
    Graphics g = br.getGraphics();
    DefaultListCellRenderer renderer =
      (DefaultListCellRenderer) source.getCellRenderer();
    int idx = selectedIndices[0];
    Object valueAt = source.getModel().getElementAt(idx);
    Component c = renderer.getListCellRendererComponent(
        source, valueAt, idx, false, false);
    Rectangle rect = source.getCellBounds(idx, idx);
    SwingUtilities.paintComponent(g, c, source, 0, 0, rect.width, rect.height);
    if (length > 1) {
      LABEL.setText(String.valueOf(length));
      Dimension d = LABEL.getPreferredSize();
      SwingUtilities.paintComponent(
          g, LABEL, source, (w - d.width) / 2, (h - d.height) / 2, d.width, d.height);
    }
    g.dispose();
    br.coerceData(true);
    return br;
  }
//...

References

2012/01/25

aterai

Sharing tabs between 2 JFrames

Code

//Display "DropLocation" using JLayer 
class DropLocationLayerUI extends LayerUI {
  private static final int LINEWIDTH = 3;
  private final Rectangle lineRect = new Rectangle();
  @Override public void paint(Graphics g, JComponent c) {
    super.paint (g, c);
    JLayer layer = (JLayer)c;
    DnDTabbedPane tabbedPane = (DnDTabbedPane)layer.getView();
    DnDTabbedPane.DropLocation loc = tabbedPane.getDropLocation();
    if(loc != null && loc.isDropable() && loc.getIndex()>=0) {
      int index = loc.getIndex();
      boolean isZero = index==0;
      Rectangle r = tabbedPane.getBoundsAt(isZero?0:index-1);
      if(tabbedPane.getTabPlacement()==JTabbedPane.TOP ||
         tabbedPane.getTabPlacement()==JTabbedPane.BOTTOM) {
        lineRect.setRect(
            r.x-LINEWIDTH/2+r.width*(isZero?0:1), r.y,LINEWIDTH,r.height);
      }else{
        lineRect.setRect(
            r.x,r.y-LINEWIDTH/2+r.height*(isZero?0:1), r.width,LINEWIDTH);
      }
      Graphics2D g2 = (Graphics2D)g.create();
      g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
      g2.setColor(Color.RED);
      g2.fill(lineRect);
      g2.dispose();
    }
  }
}
private final JLabel label = new JLabel() {
// https://free-the-pixel.blogspot.com/2010/04/ghost-drag-and-drop-over-multiple.html
// Free the pixel: GHOST drag and drop, over multiple windows]
  @Override public boolean contains(int x, int y) {
    return false;
  }
};
private final JWindow dialog = new JWindow();
public TabTransferHandler() {
  dialog.add(label);
  //dialog.setAlwaysOnTop(true); // Web Start
  dialog.setOpacity(0.5f);
  //com.sun.awt.AWTUtilities.setWindowOpacity(dialog, 0.5f); // JDK 1.6.0
  DragSource.getDefaultDragSource().addDragSourceMotionListener(
      new DragSourceMotionListener() {
    @Override public void dragMouseMoved(DragSourceDragEvent dsde) {
      Point pt = dsde.getLocation();
      pt.translate(5, 5); // offset
      dialog.setLocation(pt);
    }
  });
//...

References

2010/08/09

aterai

Drag and Drop between JLists

Code

class ListItemTransferHandler extends TransferHandler {
  private JList source = null;
  @Override protected Transferable createTransferable(JComponent c) {
    source = (JList) c;
    indices = source.getSelectedIndices();
    transferedObjects = source.getSelectedValues();
    return new DataHandler(transferedObjects, localObjectFlavor.getMimeType());
  }
  @Override public boolean importData(TransferHandler.TransferSupport info) {
    if (!canImport(info)) return false;
    JList target = (JList)info.getComponent();
    JList.DropLocation dl = (JList.DropLocation)info.getDropLocation();
    DefaultListModel listModel = (DefaultListModel)target.getModel();
    int index = dl.getIndex();
    int max = listModel.getSize();
    if(index < 0 || index > max) index = max;
    addIndex = index;
    try{
      Object[] values = (Object[])info.getTransferable().getTransferData(localObjectFlavor);
      for(int i=0;i < values.length;i++) {
        int idx = index++;
        listModel.add(idx, values[i]);
        target.addSelectionInterval(idx, idx);
      }
      addCount = (target==source)? values.length : 0;
      return true;
    }catch(UnsupportedFlavorException ufe) {
      ufe.printStackTrace();
    }catch(java.io.IOException ioe) {
      ioe.printStackTrace();
    }
    return false;
  }
//......

References

2010/02/25

aterai

TabTransferHandler

Code

class TabTransferHandler extends TransferHandler {
  private final DataFlavor localObjectFlavor;
  public TabTransferHandler() {
    System.out.println("TabTransferHandler");
    localObjectFlavor = new DataFlavor(DnDTabData.class, "DnDTabData");
  }
  private DnDTabbedPane source = null;
  @Override protected Transferable createTransferable(JComponent c) {
    System.out.println("createTransferable");
    if (c instanceof DnDTabbedPane) source = (DnDTabbedPane) c;
    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 new DnDTabData(source);
        } else {
           throw new UnsupportedFlavorException(flavor);
        }
      }
    };
  }
  @Override public boolean canImport(TransferSupport support) {
    //System.out.println("canImport");
    if (!support.isDrop() || !support.isDataFlavorSupported(localObjectFlavor)) {
      return false;
    }
    support.setDropAction(TransferHandler.MOVE);
    DropLocation tdl = support.getDropLocation();
    Point pt = tdl.getDropPoint();
    DnDTabbedPane target = (DnDTabbedPane) support.getComponent();
    target.autoScrollTest(pt);
    DnDTabbedPane.DropLocation dl =
      (DnDTabbedPane.DropLocation) target.dropLocationForPoint(pt);
    int idx = dl.getIndex();
    boolean isDroppable = false;

    if (target == source) {
      isDroppable = target.getTabAreaBounds().contains(pt) && idx >= 0 &&
                   idx != target.dragTabIndex && idx != target.dragTabIndex + 1;
    } else {
      if (source != null && target != source.getComponentAt(source.dragTabIndex)) {
        isDroppable = target.getTabAreaBounds().contains(pt) && idx >= 0;
      }
    }

    Component c = target.getRootPane().getGlassPane();
    c.setCursor(isDroppable?DragSource.DefaultMoveDrop:DragSource.DefaultMoveNoDrop);
    if (isDroppable) {
      support.setShowDropLocation(true);
      dl.setDroppable(true);
      target.setDropLocation(dl, null, true);
      return true;
    } else {
      support.setShowDropLocation(false);
      dl.setDroppable(false);
      target.setDropLocation(dl, null, false);
      return false;
    }
  }

  private BufferedImage makeDragTabImage(DnDTabbedPane tabbedPane) {
    Rectangle rect = tabbedPane.getBoundsAt(tabbedPane.dragTabIndex);
    BufferedImage image = new BufferedImage(
      tabbedPane.getWidth(), tabbedPane.getHeight(), BufferedImage.TYPE_INT_ARGB);
    Graphics g = image.getGraphics();
    tabbedPane.paint(g);
    g.dispose();
    if (rect.x < 0) {
      rect.translate(-rect.x, 0);
    }
    if (rect.y < 0) {
      rect.translate(0, -rect.y);
    }
    if (rect.x + rect.width > image.getWidth()) {
      rect.width = image.getWidth() - rect.x;
    }
    if (rect.y + rect.height > image.getHeight()) {
      rect.height = image.getHeight() - rect.y;
    }
    return image.getSubimage(rect.x, rect.y, rect.width, rect.height);
  }

  private static GhostGlassPane glassPane;
  @Override public int getSourceActions(JComponent c) {
    System.out.println("getSourceActions");
    DnDTabbedPane src = (DnDTabbedPane) c;
    if (glassPane == null) {
      c.getRootPane().setGlassPane(glassPane = new GhostGlassPane(src));
    }
    if (src.dragTabIndex < 0) return TransferHandler.NONE;
    glassPane.setImage(makeDragTabImage(src));
    source = src;
    //setDragImage(img); //java 1.7.0-ea-b84
    glassPane.setVisible(true);
    return TransferHandler.MOVE;
  }
  @Override public boolean importData(TransferSupport support) {
    System.out.println("importData");
    if (!canImport(support)) return false;

    DnDTabbedPane target = (DnDTabbedPane) support.getComponent();
    DnDTabbedPane.DropLocation dl = target.getDropLocation();
    try {
      DnDTabbedPane source = (DnDTabbedPane) support.getTransferable()
        .getTransferData(localObjectFlavor);
      int index = dl.getIndex(); //boolean insert = dl.isInsert();
      if (target == source) {
        source.convertTab(source.dragTabIndex, index);
      } else {
        source.exportTab(source.dragTabIndex, target, index);
      }
      return true;
    } catch (UnsupportedFlavorException ufe) {
      ufe.printStackTrace();
    } catch (IOException ioe) {
      ioe.printStackTrace();
    }
    return false;
  }
  @Override protected void exportDone(JComponent c, Transferable data, int action) {
    System.out.println("exportDone");
    DnDTabbedPane src = (DnDTabbedPane) c;
    c.getRootPane().getGlassPane().setVisible(false);
    src.setDropLocation(null, null, false);
  }
}

References

2009/09/28

aterai

Drag rows from one JTable to another JTable

Code

class TableRowTransferHandler extends TransferHandler {
  private final DataFlavor localObjectFlavor;
  private int[] indices;
  private int addIndex = -1; //Location where items were added
  private int addCount; //Number of items added.
  private JComponent source;
  public TableRowTransferHandler() {
    super();
    localObjectFlavor = new DataFlavor(Object[].class, "Array of items");
  }
  @Override protected Transferable createTransferable(JComponent c) {
    source = c;
    JTable table = (JTable) c;
    DefaultTableModel model = (DefaultTableModel) table.getModel();
    List<Object> list = new ArrayList<>();
    indices = table.getSelectedRows();
    for (int i : indices) {
      list.add(model.getDataVector().elementAt(i));
    }
    Object[] transferedObjects = list.toArray();
    return new Transferable() {
      @Override public DataFlavor[] getTransferDataFlavors() {
        return new DataFlavor[] {FLAVOR};
      }
      @Override public boolean isDataFlavorSupported(DataFlavor flavor) {
        return Objects.equals(FLAVOR, flavor);
      }
      @Override public Object getTransferData(DataFlavor flavor)
            throws UnsupportedFlavorException, IOException {
        if (isDataFlavorSupported(flavor)) {
          return nodes;
        } else {
          throw new UnsupportedFlavorException(flavor);
        }
      }
    };
  }
  @Override public boolean canImport(TransferSupport info) {
    JTable table = (JTable) info.getComponent();
    boolean isDroppable = info.isDrop()
      && info.isDataFlavorSupported(localObjectFlavor);
    //XXX bug?
    table.setCursor(isDroppable ? DragSource.DefaultMoveDrop
                                : DragSource.DefaultMoveNoDrop);
    return isDroppable;
  }
  @Override public int getSourceActions(JComponent c) {
    return TransferHandler.MOVE; //TransferHandler.COPY_OR_MOVE;
  }
  @Override public boolean importData(TransferSupport info) {
    if (!canImport(info)) {
      return false;
    }
    TransferHandler.DropLocation tdl = info.getDropLocation();
    if (!(tdl instanceof JTable.DropLocation)) {
      return false;
    }
    JTable.DropLocation dl = (JTable.DropLocation) tdl;
    JTable target = (JTable) info.getComponent();
    DefaultTableModel model = (DefaultTableModel) target.getModel();
    int index = dl.getRow();
    //boolean insert = dl.isInsert();
    int max = model.getRowCount();
    if (index < 0 || index > max) {
      index = max;
    }
    addIndex = index;
    target.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
    try {
      Object[] values =
        (Object[]) info.getTransferable().getTransferData(localObjectFlavor);
      if (Objects.equals(source, target)) {
        addCount = values.length;
      }
      for (int i = 0; i < values.length; i++) {
        int idx = index++;
        model.insertRow(idx, (Vector) values[i]);
        target.getSelectionModel().addSelectionInterval(idx, idx);
      }
      return true;
    } catch (UnsupportedFlavorException | IOException ex) {
      ex.printStackTrace();
    }
    return false;
  }
  @Override protected void exportDone(
      JComponent c, Transferable data, int action) {
    cleanup(c, action == MOVE);
  }
  private void cleanup(JComponent c, boolean remove) {
    if (remove && indices != null) {
      c.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
      DefaultTableModel model = (DefaultTableModel) ((JTable) c).getModel();
      if (addCount > 0) {
        for (int i = 0; i < indices.length; i++) {
          if (indices[i] >= addIndex) {
            indices[i] += addCount;
          }
        }
      }
      for (int i = indices.length - 1; i >= 0; i--) {
        model.removeRow(indices[i]);
      }
    }
    indices = null;
    addCount = 0;
    addIndex = -1;
  }
}

References

2008/10/14

aterai

rubber band selection, drag and drop reordering

Code

JList list = new JList(model);
list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
list.setVisibleRowCount(0);
list.setFixedCellWidth(62);
list.setFixedCellHeight(62);
list.setCellRenderer(new IconListCellRenderer());
RubberBandingListener rbl = new RubberBandingListener();
list.addMouseMotionListener(rbl);
list.addMouseListener(rbl);
list.getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
list.setTransferHandler(new ListItemTransferHandler());
list.setDropMode(DropMode.INSERT);

References