001/*
002 *  $Source: v:/cvsroot/open/projects/WebARTS/ca/bc/webarts/widgets/dnd/TransferableObject.java,v $
003 *  $Name:  $
004 *  $Revision: 1.1 $
005 *  $Date: 2005-04-10 11:53:16 -0700 (Sun, 10 Apr 2005) $
006 *  $Locker:  $
007 */
008/*
009 *  Copyright (C) 2001 WebARTS Design, North Vancouver Canada
010 *  http://www..webarts.bc.ca
011 *
012 *  This program is free software; you can redistribute it and/or modify
013 *  it under the terms of the GNU General Public License as published by
014 *  the Free Software Foundation; either version 2 of the License, or
015 *  (at your option) any later version.
016 *
017 *  This program is distributed in the hope that it will be useful,
018 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
019 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
020 *  GNU General Public License for more details.
021 *
022 *  You should have received a copy of the GNU General Public License
023 *  along with this program; if not, write to the Free Software
024 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
025 */
026package ca.bc.webarts.widgets.dnd;
027
028
029/**
030 * At last an easy way to encapsulate your custom objects for dragging and dropping
031 * in your Java programs!
032 * When you need to create a {@link java.awt.datatransfer.Transferable} object,
033 * use this class to wrap your object.
034 * For example:
035 * <pre><code>
036 *      ...
037 *      MyCoolClass myObj = new MyCoolClass();
038 *      Transferable xfer = new TransferableObject( myObj );
039 *      ...
040 * </code></pre>
041 * Or if you need to know when the data was actually dropped, like when you're
042 * moving data out of a list, say, you can use the {@link TransferableObject.Fetcher}
043 * inner class to return your object Just in Time.
044 * For example:
045 * <pre><code>
046 *      ...
047 *      final MyCoolClass myObj = new MyCoolClass();
048 *
049 *      TransferableObject.Fetcher fetcher = new TransferableObject.Fetcher()
050 *      {   public Object getObject(){ return myObj; }
051 *      }; // end fetcher
052 *
053 *      Transferable xfer = new TransferableObject( fetcher );
054 *      ...
055 * </code></pre>
056 *
057 * The {@link java.awt.datatransfer.DataFlavor} associated with
058 * {@link TransferableObject} has the representation class
059 * <tt>net.iharder.dnd.TransferableObject.class</tt> and MIME type
060 * <tt>application/x-net.iharder.dnd.TransferableObject</tt>.
061 * This data flavor is accessible via the static
062 * {@link #DATA_FLAVOR} property.
063 *
064 *
065 * <p><em>This code is licensed for public use under the Common Public License version 0.5.</em><br/>
066 * The Common Public License, developed by IBM and modeled after their industry-friendly IBM Public License,
067 * differs from other common open source licenses in several important ways:
068 * <ul>
069 *  <li>You may include this software with other software that uses a different (even non-open source) license.</li>
070 *  <li>You may use this software to make for-profit software.</li>
071 *  <li>Your patent rights, should you generate patents, are protected.</li>
072 * </ul>
073 * </p>
074 * <p><em>Copyright ? 2001 Robert Harder</em></p>
075 *
076 * @author  Robert.Harder
077 * @copyright 2001
078 * @version 1.1
079 */
080public class TransferableObject implements java.awt.datatransfer.Transferable
081{
082    /**
083     * The MIME type for {@link #DATA_FLAVOR} is
084     * <tt>application/x-net.iharder.dnd.TransferableObject</tt>.
085     *
086     * @since 1.1
087     */
088    public final static String MIME_TYPE = "application/x-net.iharder.dnd.TransferableObject";
089
090
091    /**
092     * The default {@link java.awt.datatransfer.DataFlavor} for
093     * {@link TransferableObject} has the representation class
094     * <tt>net.iharder.dnd.TransferableObject.class</tt>
095     * and the MIME type
096     * <tt>application/x-net.iharder.dnd.TransferableObject</tt>.
097     *
098     * @since 1.1
099     */
100    public final static java.awt.datatransfer.DataFlavor DATA_FLAVOR =
101        new java.awt.datatransfer.DataFlavor( ca.bc.webarts.widgets.dnd.TransferableObject.class, MIME_TYPE );
102
103
104    private Fetcher fetcher;
105    private Object data;
106
107    private java.awt.datatransfer.DataFlavor customFlavor;
108
109
110
111    /**
112     * Creates a new {@link TransferableObject} that wraps <var>data</var>.
113     * Along with the {@link #DATA_FLAVOR} associated with this class,
114     * this creates a custom data flavor with a representation class
115     * determined from <code>data.getClass()</code> and the MIME type
116     * <tt>application/x-net.iharder.dnd.TransferableObject</tt>.
117     *
118     * @param data The data to transfer
119     * @since 1.1
120     */
121    public TransferableObject( Object data )
122    {   this.data = data;
123        this.customFlavor = new java.awt.datatransfer.DataFlavor( data.getClass(), MIME_TYPE );
124    }   // end constructor
125
126
127
128    /**
129     * Creates a new {@link TransferableObject} that will return the
130     * object that is returned by <var>fetcher</var>.
131     * No custom data flavor is set other than the default
132     * {@link #DATA_FLAVOR}.
133     *
134     * @see Fetcher
135     * @param fetcher The {@link Fetcher} that will return the data object
136     * @since 1.1
137     */
138    public TransferableObject( Fetcher fetcher )
139    {   this.fetcher = fetcher;
140    }   // end constructor
141
142
143
144    /**
145     * Creates a new {@link TransferableObject} that will return the
146     * object that is returned by <var>fetcher</var>.
147     * Along with the {@link #DATA_FLAVOR} associated with this class,
148     * this creates a custom data flavor with a representation class <var>dataClass</var>
149     * and the MIME type
150     * <tt>application/x-net.iharder.dnd.TransferableObject</tt>.
151     *
152     * @see Fetcher
153     * @param dataClass The {@link java.lang.Class} to use in the custom data flavor
154     * @param fetcher The {@link Fetcher} that will return the data object
155     * @since 1.1
156     */
157    public TransferableObject( Class dataClass, Fetcher fetcher )
158    {   this.fetcher = fetcher;
159        this.customFlavor = new java.awt.datatransfer.DataFlavor( dataClass, MIME_TYPE );
160    }   // end constructor
161
162    /**
163     * Returns the custom {@link java.awt.datatransfer.DataFlavor} associated
164     * with the encapsulated object or <tt>null</tt> if the {@link Fetcher}
165     * constructor was used without passing a {@link java.lang.Class}.
166     *
167     * @return The custom data flavor for the encapsulated object
168     * @since 1.1
169     */
170    public java.awt.datatransfer.DataFlavor getCustomDataFlavor()
171    {   return customFlavor;
172    }   // end getCustomDataFlavor
173
174
175/* ********  T R A N S F E R A B L E   M E T H O D S  ******** */
176
177
178    /**
179     * Returns a two- or three-element array containing first
180     * the custom data flavor, if one was created in the constructors,
181     * second the default {@link #DATA_FLAVOR} associated with
182     * {@link TransferableObject}, and third the
183     * {@link java.awt.datatransfer.DataFlavor.stringFlavor}.
184     *
185     * @return An array of supported data flavors
186     * @since 1.1
187     */
188    public java.awt.datatransfer.DataFlavor[] getTransferDataFlavors()
189    {
190        if( customFlavor != null )
191            return new java.awt.datatransfer.DataFlavor[]
192            {   customFlavor,
193                DATA_FLAVOR,
194                java.awt.datatransfer.DataFlavor.stringFlavor
195            };  // end flavors array
196        else
197            return new java.awt.datatransfer.DataFlavor[]
198            {   DATA_FLAVOR,
199                java.awt.datatransfer.DataFlavor.stringFlavor
200            };  // end flavors array
201    }   // end getTransferDataFlavors
202
203
204
205    /**
206     * Returns the data encapsulated in this {@link TransferableObject}.
207     * If the {@link Fetcher} constructor was used, then this is when
208     * the {@link Fetcher#getObject getObject()} method will be called.
209     * If the requested data flavor is not supported, then the
210     * {@link Fetcher#getObject getObject()} method will not be called.
211     *
212     * @param flavor The data flavor for the data to return
213     * @return The dropped data
214     * @since 1.1
215     */
216    public Object getTransferData( java.awt.datatransfer.DataFlavor flavor )
217    throws java.awt.datatransfer.UnsupportedFlavorException, java.io.IOException
218    {
219        // Native object
220        if( flavor.equals( DATA_FLAVOR ) )
221            return fetcher == null ? data : fetcher.getObject();
222
223        // String
224        if( flavor.equals( java.awt.datatransfer.DataFlavor.stringFlavor ) )
225            return fetcher == null ? data.toString() : fetcher.getObject().toString();
226
227        // We can't do anything else
228        throw new java.awt.datatransfer.UnsupportedFlavorException(flavor);
229    }   // end getTransferData
230
231
232
233
234    /**
235     * Returns <tt>true</tt> if <var>flavor</var> is one of the supported
236     * flavors. Flavors are supported using the <code>equals(...)</code> method.
237     *
238     * @param flavor The data flavor to check
239     * @return Whether or not the flavor is supported
240     * @since 1.1
241     */
242    public boolean isDataFlavorSupported( java.awt.datatransfer.DataFlavor flavor )
243    {
244        // Native object
245        if( flavor.equals( DATA_FLAVOR ) )
246            return true;
247
248        // String
249        if( flavor.equals( java.awt.datatransfer.DataFlavor.stringFlavor ) )
250            return true;
251
252        // We can't do anything else
253        return false;
254    }   // end isDataFlavorSupported
255
256
257/* ********  I N N E R   I N T E R F A C E   F E T C H E R  ******** */
258
259    /**
260     * Instead of passing your data directly to the {@link TransferableObject}
261     * constructor, you may want to know exactly when your data was received
262     * in case you need to remove it from its source (or do anyting else to it).
263     * When the {@link #getTransferData getTransferData(...)} method is called
264     * on the {@link TransferableObject}, the {@link Fetcher}'s
265     * {@link #getObject getObject()} method will be called.
266     *
267     * @author Robert Harder
268     * @copyright 2001
269     * @version 1.1
270     * @since 1.1
271     */
272    public static interface Fetcher
273    {
274        /**
275         * Return the object being encapsulated in the
276         * {@link TransferableObject}.
277         *
278         * @return The dropped object
279         * @since 1.1
280         */
281        public abstract Object getObject();
282    }   // end inner interface Fetcher
283
284
285
286}   // end class TransferableObject
287