/*
 * 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.
 */

import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;

//import ilog.views.util.IlvProductUtil;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

import ilog.views.IlvManager;
import ilog.views.IlvManagerView;
import ilog.views.IlvManagerViewInteractor;
import ilog.views.IlvPoint;
import ilog.views.IlvRect;
import ilog.views.IlvTransformer;

/**
 * Interactor class that lets you drag a rectangle, and trigger a
 * method when it is done.
 */
public class DragRectangleInteractor
extends IlvManagerViewInteractor
{
  /**
   * The anchor point of the rectangle.
   */
  private final  IlvPoint _start = new IlvPoint();

  /**
   * The rectangle when dragging.
   */
  private final  IlvRect _rectangle = new IlvRect();

  /** 
   * True if we are dragging.
   */
  private boolean _dragging = false;
  
  /**
   * Constructs and initializes a new instance of a drag rectangle
   * interactor.
   */
  public DragRectangleInteractor()
  {
    enableEvents(AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK);
  }

  Override
  protected void processMouseEvent(MouseEvent event)
  {
    switch (event.getID()) {
    case MouseEvent.MOUSE_PRESSED: {
      if (_dragging)
        break;
      if ((event.getModifiersEx() & InputEvent.BUTTON2_DOWN_MASK) == 0 &&
          (event.getModifiersEx() & InputEvent.BUTTON3_DOWN_MASK) == 0) {
        _dragging = true;
        IlvTransformer t = getTransformer();
        _start.move(event.getX(), event.getY());
        t.inverse(_start);

        _rectangle.width = 0;
        _rectangle.height = 0;
        event.consume();
      }
      break;
    }
    case MouseEvent.MOUSE_RELEASED:
      if (_dragging) {
        _dragging = false;
        
        drawGhost(); // erase the ghost by redrawing in XOR

        

        fireRectangleDraggedEvent(new IlvRect(_rectangle), event);
        
        // avoid redraw of the ghost after end of interaction
    _rectangle.width = 0; 
    _rectangle.height = 0;
        event.consume();
      }
    }
    super.processMouseEvent(event);
  }

  Override
  protected void processMouseMotionEvent(MouseEvent event)
  {
    if (event.getID() == MouseEvent.MOUSE_DRAGGED &&
        _dragging) {      
      drawGhost(); // erase the ghost by redrawing in XOR
      IlvTransformer t = getTransformer();
      IlvPoint p = new IlvPoint(event.getX(), event.getY());
      ensureVisible(p);
      _rectangle.reshape(_start.x, _start.y, 0,0);
      t.inverse(p);
      _rectangle.add(p.x, p.y);
      drawGhost();
      event.consume();
    }
    super.processMouseMotionEvent(event);
  }

  /**
   * Draws the dragged rectangle in xor mode.
   */
  Override
  protected void drawGhost(Graphics g)
  {
    if (_rectangle.width > 0 && _rectangle.height >0) {
      IlvRect rect = new IlvRect(_rectangle);
      IlvTransformer t = getTransformer();
      if (t != null)
        t.apply(rect);
      if (rect.width > 0 && rect.height >0) {
        g.drawRect((int)Math.floor(rect.x), 
                   (int)Math.floor(rect.y),
                   (int)Math.floor(rect.width),
                   (int)Math.floor(rect.height));
      }
    }
  }

  /**
   * This method is called when the user
   * releases the mouse button after the drag.
   * @param event the mouse released event that generates this event.
   * @param rectangle the dragged rectangle.
   */
  protected void
    fireRectangleDraggedEvent(IlvRect rectangle, java.awt.event.MouseEvent event) 
  {
    System.out.println("Rectangle dragged " + rectangle);
  }
 
  public static void main(String[] args)
  {
    // This sample uses JViews Diagrammer features. When deploying an
    // application that includes this code, you need to be in possession
    // of a Perforce JViews Diagrammer Deployment license.
//    IlvProductUtil.DeploymentLicenseRequired(
//        IlvProductUtil.JViews_Diagrammer_Deployment);

    // Sun recommends that to put the entire GUI initialization into the
    // AWT thread
    SwingUtilities.invokeLater(
      new Runnable() {
        Override
        public void run() {
          JFrame f = new JFrame();
          f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          f.setSize(new Dimension(300, 300));
          IlvManager mgr = new IlvManager();

          IlvManagerView v = new IlvManagerView(mgr);

          v.pushInteractor(new DragRectangleInteractor());

          f.getContentPane().setLayout(new BorderLayout());
          f.getContentPane().add("Center", v);
          f.setVisible(true);
        }
      });
  }
}