import java.awt.Graphics;
import java.awt.dnd.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;

/**
 * An example of a Component that supports text drag.
 * 
 * @author  Prof. David Bernstein, James Madison University
 * @version Drag Only (Copy or Move); Using a MouseListener
 */
public class StringCollage extends JPanel
{
  private static final long serialVersionUID = 1L;

  private boolean                   dragEnabled;
  private int                       action;
  private List<StringContent>       elements;

//[constructor
  /**
   * Default Constructor.
   */
  public StringCollage()
  {
    super();
    elements = new ArrayList<StringContent>();
    this.action = DnDConstants.ACTION_MOVE;

    // Disable drag by default
    setDragEnabled(false);
    
    // Use a custom TransferHandler
    setTransferHandler(new StringTransferHandler());
    
    // Add a MouseListener that responds to mousePressed messages
    // by exporting them to a TransferHandler
    addMouseListener(
        new MouseAdapter()
        // An anonymous inner class that overrides mousePressed() in MouseAdapter
        {
          public void mousePressed(MouseEvent e) 
          {
            JComponent c = (JComponent)e.getSource();
            TransferHandler handler = c.getTransferHandler();
            handler.exportAsDrag(c, e, action);
          }
        }
    );
  }
//]constructor

  // Methods required to be a "text" bean

  /**
   * Get the text on this Component.
   * 
   * This method is required so that this is a bean with the text property.
   * 
   * @return The text (tab delimited)
   */
  public String getText()
  {
    return elements.get(elements.size()-1).getText();
  }

  /**
   * Add a new piece of text to this Component at location 0, 0.
   * 
   * This method is required so that this is a bean with the text property.
   * 
   * @param The text (tab delimited)
   */
  public void setText(String s)
  {
    if ((s == null) && !elements.isEmpty()) 
    {
      elements.remove(elements.size()-1);
      repaint();
    }
    else setText(s, 0, 0);
  }

  // Methods that provide the desired GUI functionality

  /**
   * Render this Component.
   * 
   * @param g  The rendering engine to use.
   */
  public void paint(Graphics g)
  {
    super.paint(g);
    for (StringContent e: elements)
    {
      g.drawString(e.getText(), e.getLocation().x, e.getLocation().y);
    }
  }

  /**
   * Set text on this element at the given location.
   * 
   * @param text  The text to add
   * @param x     The x-coordinate
   * @param y     The y-coordinate
   */
  public void setText(String text, int x, int y)
  {
    elements.add(new StringContent(text, x, y));
  }


  // Useful additional functionality

  /**
   * Get the DnD action associated with this Component.
   *  
   * @return  The action (DnDConstants.ACTION_COPY or DnDConstants.ACTION_MOVE)
   */
  public int getAction()
  {
    return action;
  }

  /**
   * Is drag enabled on this Component?
   * 
   * @return true or false
   */
  public boolean getDragEnabled()
  {
    return dragEnabled;
  }

  /**
   * Set the DnD action associated with this Component.
   *  
   * @param  The action (DnDConstants.ACTION_COPY or DnDConstants.ACTION_MOVE)
   */
  public void setAction(int action)
  {
    if (action == DnDConstants.ACTION_MOVE) this.action = DnDConstants.ACTION_MOVE;
    else                                    this.action = DnDConstants.ACTION_COPY;
  }
  
  /**
   * Determine whether or not drag is enabled on this Component.
   * 
   * @param enabled true to enable; false to disable
   */
  public void setDragEnabled(boolean enabled)
  {
    dragEnabled = enabled;
  }
}
