123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246 |
- /*
- * Copyright (c) 2006-2010 Chris Smith, Shane Mc Cormack, Gregory Holmes
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
- package com.dmdirc.addons.ui_swing.components.reorderablelist;
-
- import com.dmdirc.logger.ErrorLevel;
- import com.dmdirc.logger.Logger;
-
- import java.awt.datatransfer.DataFlavor;
- import java.awt.datatransfer.Transferable;
- import java.awt.datatransfer.UnsupportedFlavorException;
- import java.io.IOException;
- import java.util.ArrayList;
- import java.util.List;
-
- import javax.swing.DefaultListModel;
- import javax.swing.JComponent;
- import javax.swing.JList;
- import javax.swing.TransferHandler;
-
- /**
- * Arraylist Transfer handler.
- */
- public final class ArrayListTransferHandler extends TransferHandler {
-
- /**
- * A version number for this class. It should be changed whenever the class
- * structure is changed (or anything else that would prevent serialized
- * objects being unserialized with the new class).
- */
- private static final long serialVersionUID = 1;
- /** Local Transfer flavour. */
- private DataFlavor localArrayListFlavor;
- /** Serial Transfer flavour. */
- private final DataFlavor serialArrayListFlavor;
- /** Source component. */
- private JList sourceList;
- /** Dragged Indices. */
- private int[] indices;
- /** Index to add item(s). */
- private int addIndex = -1;
- /** Number of items to add. */
- private int addCount;
-
- /** Instantiates a new ArrayListTransferHandler. */
- public ArrayListTransferHandler() {
- super();
-
- try {
- localArrayListFlavor = new DataFlavor(
- DataFlavor.javaJVMLocalObjectMimeType + ";class=java.util.ArrayList");
- } catch (ClassNotFoundException e) {
- Logger.userError(ErrorLevel.LOW, "unable to create data flavor: " + e.getMessage());
- }
- serialArrayListFlavor = new DataFlavor(ArrayList.class, "ArrayList"); //NOPMD
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean importData(final JComponent comp, final Transferable t) {
- if (!canImport(comp, t.getTransferDataFlavors())) {
- return false;
- }
-
- try {
- if (hasLocalArrayListFlavor(t.getTransferDataFlavors())) {
- return doImport((JList) comp, (ArrayList) t.getTransferData(localArrayListFlavor));
- } else if (hasSerialArrayListFlavor(t.getTransferDataFlavors())) {
- return doImport((JList) comp, (ArrayList) t.getTransferData(serialArrayListFlavor));
- } else {
- return false;
- }
- } catch (UnsupportedFlavorException e) {
- Logger.userError(ErrorLevel.LOW, "Unsupported data flavor: " + e.getMessage());
- return false;
- } catch (IOException e) {
- Logger.userError(ErrorLevel.LOW, "Unable to import data: " + e.getMessage());
- return false;
- }
- }
-
- /**
- * Imports the tranferrable data into the list.
- *
- * @param target target list
- * @param transferList transferable list
- *
- * @return Whether the data was imported
- */
- private boolean doImport(final JList target, final List transferList) {
- int index = target.getSelectedIndex();
- if (sourceList.equals(target) && indices != null && index >= indices[0] - 1 && index <= indices[indices.length - 1]) {
- indices = null;
- return true;
- }
-
- final DefaultListModel listModel = (DefaultListModel) target.getModel();
- final int max = listModel.getSize();
-
- if (index < 0) {
- index = max;
- } else {
- index++;
- if (index > max) {
- index = max;
- }
-
- }
- addIndex = index;
- addCount = transferList.size();
-
- for (int i = 0; i < transferList.size(); i++) {
- listModel.add(index++, transferList.get(i));
- }
-
- return true;
- }
-
- /** {@inheritDoc} */
- @Override
- protected void exportDone(final JComponent source, final Transferable data,
- final int action) {
- if ((action == MOVE) && (indices != null)) {
- final DefaultListModel model = (DefaultListModel) sourceList.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.remove(indices[i]);
- }
- }
-
- indices = null;
- addIndex = -1;
- addCount = 0;
- }
-
- /**
- * Do any of the specified flavours match the local flavour.
- *
- * @param transferFlavors Flavours to check
- *
- * @return whether the transferFlavors is supported
- */
- private boolean hasLocalArrayListFlavor(final DataFlavor[] transferFlavors) {
- if (localArrayListFlavor == null) {
- return false;
- }
-
- for (int i = 0; i < transferFlavors.length; i++) {
- if (transferFlavors[i].equals(localArrayListFlavor)) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Do any of the specified flavours match the serial flavour.
- *
- * @param transferFlavors Flavours to check
- *
- * @return whether the flavour is supported
- */
- private boolean hasSerialArrayListFlavor(final DataFlavor[] transferFlavors) {
- if (serialArrayListFlavor == null) {
- return false;
- }
-
- for (int i = 0; i < transferFlavors.length; i++) {
- if (transferFlavors[i].equals(serialArrayListFlavor)) {
- return true;
- }
- }
-
- return false;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean canImport(final JComponent comp, final DataFlavor[] transferFlavors) {
- return comp instanceof JList && ((JList) comp).getModel() instanceof DefaultListModel
- && (hasLocalArrayListFlavor(transferFlavors)
- || hasSerialArrayListFlavor(transferFlavors));
- }
-
- /** {@inheritDoc} */
- @Override
- protected Transferable createTransferable(final JComponent c) {
- if (c instanceof JList) {
- sourceList = (JList) c;
- indices = sourceList.getSelectedIndices();
- final Object[] values = sourceList.getSelectedValues();
-
- if (values == null || values.length == 0) {
- return null;
- }
-
- final ArrayList<Object> alist = new ArrayList<Object>(values.length);
-
- for (int i = 0; i < values.length; i++) {
- final Object o = values[i];
- String str = o.toString();
- if (str == null) {
- str = "";
- }
- alist.add(str);
- }
-
- return new ArrayListTransferable(alist);
- }
-
- return null;
- }
-
- /** {@inheritDoc} */
- @Override
- public int getSourceActions(final JComponent c) {
- return COPY_OR_MOVE;
- }
- }
|