/* * TransferableCollection.java * Eisenkraut * * Copyright (c) 2004-2016 Hanns Holger Rutz. All rights reserved. * * This software is published under the GNU General Public License v3+ * * * For further information, please contact Hanns Holger Rutz at * contact@sciss.de * * * Changelog: * 07-Feb-05 created from de.sciss.meloncillo.util.Meloncillo */ package de.sciss.eisenkraut.util; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.datatransfer.UnsupportedFlavorException; import java.io.IOException; import java.util.List; import java.util.Vector; /** * A special transferable object which * wraps a collection of individual transferable * objects. For example, if the user selects * a collection of receivers and chooses Cut from * the edit menu, a <code>TransferableCollection</code> * is created containing these receivers. * <p> * In the a pasting situation, the clipboard managing * object obtains a <code>java.awt.List</code> object * through the <code>getTransferData</code> method. * It should traverse this list and check if an element * is instanceof <code>Transferable</code> (this is guaranteed but * checking maintains cleaner code). It can then check * if the individual <code>Transferable</code> can * provide a requested data format. */ public class TransferableCollection implements Transferable { /** * The flavor used to * identify a <code>TransferableCollection</code> */ public static final DataFlavor collectionFlavor = new DataFlavor( List.class, null ); private final Vector<Transferable> collTransferables; private final DataFlavor[] collFlavors; /** * Constructs a new <code>TransferableCollection</code> * backup'ed by a list of <code>Transferable</code> objects. * The list elements are copied to a new list, hence it's safe * to modify the list afterwards. * * @param coll a list containing elements which implement the * <code>Transferable</code> interface. Each element's * flavor is added to the flavor list which is checked * in a call to <code>isDataFlavorSupported</code>! * * @throws IllegalArgumentException if the list contains an object * which does not implement the Transferable * interface */ public TransferableCollection(List<Transferable> coll) { collTransferables = new Vector<Transferable>(); int i, j, k; Object o; DataFlavor[] flavorArray; DataFlavor flavor; Vector<DataFlavor> v = new Vector<DataFlavor>(); for (i = 0; i < coll.size(); i++) { o = coll.get(i); if (!(o instanceof Transferable)) throw new IllegalArgumentException(); Transferable t = (Transferable) o; flavorArray = ((Transferable) o).getTransferDataFlavors(); collFlavLp: for (j = 0; j < flavorArray.length; j++) { flavor = flavorArray[j]; for (k = 0; k < v.size(); k++) { if (v.get(k).equals(flavor)) continue collFlavLp; } v.add(flavor); } collTransferables.add(t); } v.add( collectionFlavor ); collFlavors = new DataFlavor[v.size()]; for (i = 0; i < v.size(); i++) { collFlavors[i] = v.get(i); } } // ---------------- Transferable interface ---------------- /** * Queries the available flavors. * * @return an array of available flavors. This is a sum * of <code>collectionFlavor</code> and all * individual flavors of the list */ public DataFlavor[] getTransferDataFlavors() { return( collFlavors ); } /** * Checks if a certain flavor is available. * * @return <code>true</code>, if at least one of the list's * elements supports the given flavor, or if <code>flavor</code> * equals <code>collectionFlavor</code>. */ public boolean isDataFlavorSupported(DataFlavor flavor) { for (DataFlavor collFlavor : collFlavors) { if (collFlavor.equals(flavor)) return true; } return false; } /** * Returns the transfer data. If <code>flavor</code> equals * <code>collectionFlavor</code>, * a <code>java.util.List</code> containing <code>Transferable</code> objects is * returned. Otherwise the list is traversed until <strong>one</strong> * transferable is found which supports the given flavor. This object is * returned. * * @param flavor the transferable object(s) will be returned in this flavor. * @return either a list if flavor is collectionFlavor, otherwise the transfer data * of the first list item supporting the given flavor * @throws UnsupportedFlavorException if none of the items supports the given flavor * @throws IOException if the data is no longer available in the requested flavor */ public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException { if (flavor.equals(collectionFlavor)) return new Vector<Transferable>(collTransferables); Object o; for (Transferable collTransferable : collTransferables) { o = collTransferable; if (o instanceof Transferable) { if (((Transferable) o).isDataFlavorSupported(flavor)) { return (((Transferable) o).getTransferData(flavor)); } } } throw new UnsupportedFlavorException( flavor ); } }