/* Clipboard.java -- Class for transferring data via cut and paste.
   Copyright (C) 1999, 2001, 2005, 2006 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package java.awt.datatransfer;

import java.io.IOException;
import java.util.ArrayList;

/**
 * This class allows data to be transferred using a cut and paste type
 * mechanism.
 *
 * @author Aaron M. Renn (arenn@urbanophile.com)
 * @author Mark J. Wielaard (mark@klomp.org)
 */
public class Clipboard
{
  /**
   * The data currently on this clipboard.  For use by
   * subclasses. Also returned by the public method getContents().
   */
  protected Transferable contents;

  /**
   * The owner of this clipboard.
   */
  protected ClipboardOwner owner;

  // The clipboard name
  private final String name;

  // The flavor listeners (most likely small).
  private final ArrayList listeners = new ArrayList(3);

  /**
   * Initializes a new instance of <code>Clipboard</code> with the
   * specified name.
   *
   * @param name The clipboard name.
   */
  public Clipboard(String name)
  {
    this.name = name;
  }

  /**
    * Returns the name of the clipboard.
    */
  public String getName()
  {
    return name;
  }

  /**
   * Returns the contents of the clipboard.
   *
   * @param requestor The object requesting the contents. This
   * implementation ignores this parameter.
   *
   * @exception IllegalStateException If the clipboard is currently unavailable
   */
  public synchronized Transferable getContents(Object requestor)
  {
    return contents;
  }

  /**
   * Sets the content and owner of this clipboard.  If the given owner
   * is different from the current owner then <code>lostOwnership()</code>
   * is called on the current owner with the old contents of the given
   * clipboard.
   *
   * @param contents The new clipboard contents.
   * @param owner The new clipboard owner
   *
   * @exception IllegalStateException If the clipboard is currently unavailable
   */
  public synchronized void setContents(Transferable contents,
                                       ClipboardOwner owner)
  {
    Transferable oldContents = getContents(null);
    this.contents = contents;
    if (this.owner != owner)
      {
        ClipboardOwner oldOwner = this.owner;
        this.owner = owner;
        if (oldOwner != null)
          oldOwner.lostOwnership(this, oldContents);
      }

    FlavorListener[] fs = getFlavorListeners();
    if (fs.length > 0)
      {
        // We are a bit optimistic here. We assume DataFlavors will be
        // given in the same order. If the number of flavors is
        // different or the order of the DataFlavors in the list then
        // fire a change event.
        boolean newFlavors = ((contents != null && oldContents == null)
                              || (contents == null && oldContents != null));
        if (!newFlavors && contents != null && oldContents != null)
          {
            DataFlavor[] df1 = contents.getTransferDataFlavors();
            DataFlavor[] df2 = oldContents.getTransferDataFlavors();
            newFlavors = df1.length != df2.length;

            for (int i = 0; !newFlavors && i < df1.length; i++)
              newFlavors = !df1[i].equals(df2[i]);
          }

        if (newFlavors)
          {
            FlavorEvent e = new FlavorEvent(this);
            for (int i = 0; i < fs.length; i++)
              fs[i].flavorsChanged(e);
          }
      }
  }

  public DataFlavor[] getAvailableDataFlavors()
  {
    Transferable c = getContents(null);
    if (c == null)
      return new DataFlavor[0];
    else
      return c.getTransferDataFlavors();
  }

  public boolean isDataFlavorAvailable(DataFlavor flavor)
  {
    DataFlavor[] fs = getAvailableDataFlavors();
    for (int i = 0; i < fs.length; i++)
      if (flavor.equals(fs[i]))
        return true;

    return false;
  }

  public Object getData(DataFlavor flavor)
    throws UnsupportedFlavorException, IOException
  {
    Transferable c = getContents(null);
    if (c == null)
      throw new UnsupportedFlavorException(flavor);
    else
      return c.getTransferData(flavor);
  }

  public void addFlavorListener(FlavorListener listener)
  {
    if (listener == null)
      return;

    synchronized(listeners)
      {
        listeners.add(listener);
      }
  }

  public void removeFlavorListener(FlavorListener listener)
  {
    if (listener == null)
      return;

    synchronized(listeners)
      {
        listeners.remove(listener);
      }
  }

  public FlavorListener[] getFlavorListeners()
  {
    synchronized(listeners)
      {
        return (FlavorListener[])
          listeners.toArray(new FlavorListener[listeners.size()]);
      }
  }
}
