001    /* Clipboard.java -- Class for transferring data via cut and paste.
002       Copyright (C) 1999, 2001, 2005, 2006 Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    
039    package java.awt.datatransfer;
040    
041    import java.io.IOException;
042    import java.util.ArrayList;
043    
044    /**
045     * This class allows data to be transferred using a cut and paste type
046     * mechanism.
047     *
048     * @author Aaron M. Renn (arenn@urbanophile.com)
049     * @author Mark J. Wielaard (mark@klomp.org)
050     */
051    public class Clipboard
052    {
053      /**
054       * The data currently on this clipboard.  For use by
055       * subclasses. Also returned by the public method getContents().
056       */
057      protected Transferable contents;
058    
059      /**
060       * The owner of this clipboard.
061       */
062      protected ClipboardOwner owner;
063    
064      // The clipboard name
065      private final String name;
066    
067      // The flavor listeners (most likely small).
068      private final ArrayList listeners = new ArrayList(3);
069    
070      /**
071       * Initializes a new instance of <code>Clipboard</code> with the
072       * specified name.
073       *
074       * @param name The clipboard name.
075       */
076      public Clipboard(String name)
077      {
078        this.name = name;
079      }
080    
081      /**
082        * Returns the name of the clipboard.
083        */
084      public String getName()
085      {
086        return name;
087      }
088    
089      /**
090       * Returns the contents of the clipboard.
091       *
092       * @param requestor The object requesting the contents. This
093       * implementation ignores this parameter.
094       *
095       * @exception IllegalStateException If the clipboard is currently unavailable
096       */
097      public synchronized Transferable getContents(Object requestor)
098      {
099        return contents;
100      }
101    
102      /**
103       * Sets the content and owner of this clipboard.  If the given owner
104       * is different from the current owner then <code>lostOwnership()</code>
105       * is called on the current owner with the old contents of the given
106       * clipboard.
107       *
108       * @param contents The new clipboard contents.
109       * @param owner The new clipboard owner
110       *
111       * @exception IllegalStateException If the clipboard is currently unavailable
112       */
113      public synchronized void setContents(Transferable contents,
114                                           ClipboardOwner owner)
115      {
116        Transferable oldContents = getContents(null);
117        this.contents = contents;
118        if (this.owner != owner)
119          {
120            ClipboardOwner oldOwner = this.owner;
121            this.owner = owner;
122            if (oldOwner != null)
123              oldOwner.lostOwnership(this, oldContents);
124          }
125    
126        FlavorListener[] fs = getFlavorListeners();
127        if (fs.length > 0)
128          {
129            // We are a bit optimistic here. We assume DataFlavors will be
130            // given in the same order. If the number of flavors is
131            // different or the order of the DataFlavors in the list then
132            // fire a change event.
133            boolean newFlavors = ((contents != null && oldContents == null)
134                                  || (contents == null && oldContents != null));
135            if (!newFlavors && contents != null && oldContents != null)
136              {
137                DataFlavor[] df1 = contents.getTransferDataFlavors();
138                DataFlavor[] df2 = oldContents.getTransferDataFlavors();
139                newFlavors = df1.length != df2.length;
140    
141                for (int i = 0; !newFlavors && i < df1.length; i++)
142                  newFlavors = !df1[i].equals(df2[i]);
143              }
144    
145            if (newFlavors)
146              {
147                FlavorEvent e = new FlavorEvent(this);
148                for (int i = 0; i < fs.length; i++)
149                  fs[i].flavorsChanged(e);
150              }
151          }
152      }
153    
154      public DataFlavor[] getAvailableDataFlavors()
155      {
156        Transferable c = getContents(null);
157        if (c == null)
158          return new DataFlavor[0];
159        else
160          return c.getTransferDataFlavors();
161      }
162    
163      public boolean isDataFlavorAvailable(DataFlavor flavor)
164      {
165        DataFlavor[] fs = getAvailableDataFlavors();
166        for (int i = 0; i < fs.length; i++)
167          if (flavor.equals(fs[i]))
168            return true;
169    
170        return false;
171      }
172    
173      public Object getData(DataFlavor flavor)
174        throws UnsupportedFlavorException, IOException
175      {
176        Transferable c = getContents(null);
177        if (c == null)
178          throw new UnsupportedFlavorException(flavor);
179        else
180          return c.getTransferData(flavor);
181      }
182    
183      public void addFlavorListener(FlavorListener listener)
184      {
185        if (listener == null)
186          return;
187    
188        synchronized(listeners)
189          {
190            listeners.add(listener);
191          }
192      }
193    
194      public void removeFlavorListener(FlavorListener listener)
195      {
196        if (listener == null)
197          return;
198    
199        synchronized(listeners)
200          {
201            listeners.remove(listener);
202          }
203      }
204    
205      public FlavorListener[] getFlavorListeners()
206      {
207        synchronized(listeners)
208          {
209            return (FlavorListener[])
210              listeners.toArray(new FlavorListener[listeners.size()]);
211          }
212      }
213    }