001/* A transferable object that contains a named object. 002 003 Copyright (c) 2000-2014 The Regents of the University of California. 004 All rights reserved. 005 Permission is hereby granted, without written agreement and without 006 license or royalty fees, to use, copy, modify, and distribute this 007 software and its documentation for any purpose, provided that the above 008 copyright notice and the following two paragraphs appear in all copies 009 of this software. 010 011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 015 SUCH DAMAGE. 016 017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 022 ENHANCEMENTS, OR MODIFICATIONS. 023 024 PT_COPYRIGHT_VERSION_2 025 COPYRIGHTENDKEY 026 027 */ 028package ptolemy.vergil.toolbox; 029 030import java.awt.datatransfer.DataFlavor; 031import java.awt.datatransfer.Transferable; 032import java.awt.datatransfer.UnsupportedFlavorException; 033import java.io.IOException; 034import java.io.Serializable; 035import java.io.StringReader; 036import java.io.StringWriter; 037import java.util.Collections; 038import java.util.Iterator; 039import java.util.LinkedList; 040import java.util.List; 041 042import ptolemy.gui.PtGUIUtilities; 043import ptolemy.kernel.util.NamedObj; 044 045/////////////////////////////////////////////////////////////////// 046//// PtolemyTransferable 047 048/** 049 A transferable object that contains a local JVM reference to a 050 number of named objects. To get a reference to an iterator on the 051 objects, request data with the data flavor given in the static 052 namedObjFlavor variable. This class will also return a MoML 053 representation of the objects, if data is requested with the 054 DataFlavor.stringFlavor or DataFlavor.plainTextFlavor. 055 056 @author Steve Neuendorffer 057 @version $Id$ 058 @since Ptolemy II 1.0 059 @Pt.ProposedRating Red (eal) 060 @Pt.AcceptedRating Red (johnr) 061 */ 062@SuppressWarnings("serial") 063public class PtolemyTransferable implements Transferable, Serializable { 064 // This class implements Serializable in hopes that 065 // drag and drop will work under Mac OS X. 066 067 /** 068 * Create a new transferable object that contains no objects. 069 */ 070 public PtolemyTransferable() { 071 _objectList = new LinkedList(); 072 } 073 074 /////////////////////////////////////////////////////////////////// 075 //// public methods //// 076 077 /** 078 * Add the given named object to the objects contained in this 079 * transferable. If the object already exists in this transferable, 080 * then do not add it again. 081 * @param object The object to be added to this transferable. 082 */ 083 public void addObject(NamedObj object) { 084 if (!_objectList.contains(object)) { 085 _objectList.add(object); 086 } 087 } 088 089 /** 090 * Return the data flavors that this transferable supports. 091 * @return The data flavors. 092 */ 093 @Override 094 public synchronized DataFlavor[] getTransferDataFlavors() { 095 return _flavors; 096 } 097 098 /** 099 * Return true if the given data flavor is supported. 100 * @param flavor The data flavor that is searched for. 101 * @return true if the given data flavor is supported. 102 */ 103 @Override 104 public boolean isDataFlavorSupported(DataFlavor flavor) { 105 int i; 106 107 for (i = 0; i < _flavors.length; i++) { 108 if (_flavors[i].equals(flavor)) { 109 return true; 110 } 111 } 112 113 return false; 114 } 115 116 /** 117 * Return an object that represents the data contained within this 118 * transferable with the given flavor. If the flavor is namedObjFlavor, 119 * return an iterator of the objects that this transferable refers to. 120 * If the flavor is DataFlavor.plainTextFlavor, return an 121 * InputStream that contains a MoML representation of the objects. 122 * If the flavor is DataFlavor.stringFlavor return a string that 123 * contains the MoML representation. 124 * 125 * @param flavor The data flavor. 126 * @return An object with the given flavor. 127 * @exception UnsupportedFlavorException If the given flavor is 128 * not supported. 129 * @exception IOException If thrown while creating the MoML. 130 */ 131 @Override 132 public Object getTransferData(DataFlavor flavor) 133 throws UnsupportedFlavorException, IOException { 134 if (flavor.equals(DataFlavor.plainTextFlavor)) { 135 // plain text flavor is deprecated, but everybody still 136 // implements it. The problem is that all the implementations 137 // differ from the docs. *sigh* 138 return new StringReader(_getMoML()); 139 } else if (flavor.equals(namedObjFlavor)) { 140 return Collections.unmodifiableList(_objectList); 141 } else if (flavor.equals(DataFlavor.stringFlavor)) { 142 return _getMoML(); 143 } 144 145 throw new UnsupportedFlavorException(flavor); 146 } 147 148 /** 149 * Remove the given object from this transferable. 150 * If the object does not exist in the transferable, then do nothing. 151 * @param object The object to be removed. 152 */ 153 public void removeObject(NamedObj object) { 154 if (_objectList.contains(object)) { 155 _objectList.remove(object); 156 } 157 } 158 159 /////////////////////////////////////////////////////////////////// 160 //// public variables //// 161 162 /** 163 * The flavor that requests a local virtual machine 164 * reference to the contained object. 165 */ 166 public static final DataFlavor namedObjFlavor; 167 168 static { 169 // Under MacOS X 10.2, Java 1.4.1_01 we get a stack trace 170 // when ever we drag and drop. For details See 171 // http://lists.apple.com/archives/java-dev/2003/Apr/16/classcastexceptionindrag.txt 172 // FIXME: This change happened just before the release of 3.0.2, 173 // so we only make the change under Mac OS. 174 if (PtGUIUtilities.macOSLookAndFeel()) { 175 namedObjFlavor = new DataFlavor( 176 DataFlavor.javaJVMLocalObjectMimeType 177 + ";class=ptolemy.kernel.util.NamedObj", 178 "Named Object"); 179 } else { 180 namedObjFlavor = new DataFlavor( 181 DataFlavor.javaJVMLocalObjectMimeType 182 + "ptolemy.kernel.util.NamedObj", 183 "Named Object"); 184 } 185 } 186 187 /** Return a string with a MoML description of all the objects in 188 * the list. 189 * @return the MoML description. 190 * @exception IOException If thrown while creating the MoML. 191 */ 192 public String _getMoML() throws IOException { 193 StringWriter buffer = new StringWriter(); 194 buffer.write("<group>\n"); 195 196 Iterator elements = Collections.unmodifiableList(_objectList) 197 .iterator(); 198 199 while (elements.hasNext()) { 200 NamedObj element = (NamedObj) elements.next(); 201 202 // first level to avoid obnoxiousness with toplevel translations. 203 element.exportMoML(buffer, 1); 204 } 205 206 buffer.write("</group>\n"); 207 return buffer.toString(); 208 } 209 210 /////////////////////////////////////////////////////////////////// 211 //// private variables //// 212 // The flavors that this node can return. 213 private final DataFlavor[] _flavors = { DataFlavor.plainTextFlavor, 214 DataFlavor.stringFlavor, namedObjFlavor, }; 215 216 //The object contained by this transferable. 217 private List _objectList; 218}