/*
 * Licensed Materials - Property of Perforce Software, Inc. 
 * © Copyright Perforce Software, Inc. 2014, 2021 
 * © Copyright IBM Corp. 2009, 2014
 * © Copyright ILOG 1996, 2009
 * All Rights Reserved.
 *
 * Note to U.S. Government Users Restricted Rights:
 * The Software and Documentation were developed at private expense and
 * are "Commercial Items" as that term is defined at 48 CFR 2.101,
 * consisting of "Commercial Computer Software" and
 * "Commercial Computer Software Documentation", as such terms are
 * used in 48 CFR 12.212 or 48 CFR 227.7202-1 through 227.7202-4,
 * as applicable.
 */

package dnd;

import java.awt.Cursor;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.DragGestureListener;
import java.awt.dnd.DragGestureRecognizer;
import java.awt.dnd.DragSource;
import java.awt.dnd.DragSourceDragEvent;
import java.awt.dnd.DragSourceDropEvent;
import java.awt.dnd.DragSourceEvent;
import java.awt.dnd.DragSourceListener;

import ilog.views.IlvGraphic;
import ilog.views.IlvManagerView;
import ilog.views.IlvPoint;
import ilog.views.IlvRect;


/**
 * The <code>DragAdapter</code> class allows an <code>IlvManagerView</code>
 * to be a <code>DragSource</code> for Java drag-and-drop mechanism by implementing Java <code>DragSource</code> and
 * <code>DragGesture</code> Listners.
 * @see DropAdapter
 */
public class DragAdapter  
  implements DragSourceListener, DragGestureListener
{
  private static DragSource ds = DragSource.getDefaultDragSource();
  private IlvGraphic currentDrag = null;

  /**
   * It implements the <code>DragGestureListener</code> method to begin a drag-and-drop operation.
   * @param ev The triggered event.
   */
  Override
  public void dragGestureRecognized(DragGestureEvent ev)
  {        
    // Gets the view from the event.
    IlvManagerView view = (IlvManagerView)((DragGestureRecognizer)ev.getSource()).getComponent();

    // Tests if the action is allowed.
    if ((ev.getDragAction() & DnDConstants.ACTION_COPY_OR_MOVE) != 0) {

      // Tries to get the object under the mouse (we only deal with
      // <code>IlvGraphic</code> objects).
      IlvPoint p = new IlvPoint(ev.getDragOrigin().x, ev.getDragOrigin().y);
      currentDrag = view.getManager().getObject(p, view);

      if (currentDrag != null && view.getManager().isSelectable(currentDrag)) {
        // Here we can improve the behavior on platform by allowing <code>DragImage</code>.
        if (DragSource.isDragImageSupported()) {
          // Creation of an image.
        }
        
        // Computation of the position of the mouse pointer in the object.
        view.getTransformer().inverse(p);          
        
        IlvRect rect = currentDrag.boundingBox(null);
        IlvPoint delta = new IlvPoint(p.x - rect.x, p.y - rect.y);
        
        // To remember this position in drop action we set a property on the object.
        currentDrag.setNamedProperty(new DeltaProperty(delta));
        
        // We change the cursor depending on the action type.
        Cursor cursor = (ev.getDragAction() == DnDConstants.ACTION_COPY)?
          DragSource.DefaultCopyDrop:DragSource.DefaultMoveDrop;
        try {
          // Send the <code>IlvGraphic</code> to the drag-and-drop mechanism starting to drag.
          ds.startDrag(ev,
                       cursor,
                       // IlvGraphic implements Transferable and can be directly passed 
                       // to drag n drop mechanism.
                       currentDrag,
                       // this class will be the DragSourceListener
                       this);
        }  catch (Exception ex) {
          System.err.println("Drag cannot be performed");
          // Removes <code>NamedProperty</code> to prevent from polluting memory space.
          currentDrag.removeNamedProperty(DeltaProperty.NAME);
        }
      }
    }
  }
  
  /**
   * It implements the <code>DragSourceListener</code> method to end a drag-and-drop operation.
   * @param dsde The triggered event.
   */
  Override
  public void dragDropEnd(DragSourceDropEvent dsde) 
  { 
    // Gets the view.
    IlvManagerView view = (IlvManagerView)(dsde.getDragSourceContext().getComponent());
    // Removes <code>NamedProperty</code> to prevent from polluting memory space.
    currentDrag.removeNamedProperty(DeltaProperty.NAME);
    // In move action we delete the initial object in case of success.
    if (dsde.getDropSuccess() && ((dsde.getDropAction() & DnDConstants.ACTION_MOVE) != 0)) 
      view.getManager().removeObject(currentDrag, true);
    currentDrag = null;
  }

  // In this simple example we do not redefine the following methods:
  Override
  public void dropActionChanged(DragSourceDragEvent dsde) 
  {
  }
  public void dragGestureChanged(DragSourceDragEvent dsde) 
  {
  }  
  Override
  public void dragEnter(DragSourceDragEvent dsde) 
  { 
  }
  Override
  public void dragOver(DragSourceDragEvent dsde) 
  { 
  }  
  Override
  public void dragExit(DragSourceEvent dse) 
  {
  }
}