content: /*
   * Copyright (c) 1997 - 2016
   * Actelion Pharmaceuticals Ltd.
   * Gewerbestrasse 16
   * CH-4123 Allschwil, Switzerland
   *
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions are met:
   *
   * 1. Redistributions of source code must retain the above copyright notice, this
   *    list of conditions and the following disclaimer.
   * 2. Redistributions in binary form must reproduce the above copyright notice,
   *    this list of conditions and the following disclaimer in the documentation
   *    and/or other materials provided with the distribution.
   * 3. Neither the name of the the copyright holder nor the
   *    names of its contributors may be used to endorse or promote products
   *    derived from this software without specific prior written permission.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
   * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   *
   * @author Christian Rufener
   */
  
  package com.actelion.research.gui.dnd;
  
  import com.actelion.research.chem.AbstractDepictor;
  import com.actelion.research.chem.ExtendedDepictor;
  import com.actelion.research.chem.dnd.ChemistryFlavors;
  import com.actelion.research.chem.reaction.Reaction;
  import com.actelion.research.gui.generic.GenericRectangle;
  import com.actelion.research.gui.swing.SwingDrawContext;
  
  import java.awt.*;
  import java.awt.datatransfer.Transferable;
  import java.awt.datatransfer.UnsupportedFlavorException;
  import java.awt.dnd.*;
  import java.awt.image.BufferedImage;
  import java.io.IOException;
  
  
  public abstract class ReactionDragAdapter implements DragSourceListener /*,DragSourceMotionListener*/ {
  	int mAllowedDragAction;
  	Cursor cursor = null;
  
  	public ReactionDragAdapter(Component c) {
  //        DragSource ds = new DragSource();
  //        ds.addDragSourceListener(new WindowMovingDragSourceListener());
  
  		DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(c, DnDConstants.ACTION_COPY_OR_MOVE, new DGListener());
  		mAllowedDragAction = DnDConstants.ACTION_COPY_OR_MOVE;
  	}
  
  	public void allowDrag(boolean allow) {
  		if (allow)
  			mAllowedDragAction = DnDConstants.ACTION_COPY_OR_MOVE;
  		else
  			mAllowedDragAction = DnDConstants.ACTION_NONE;
  	}
  
  	public abstract Transferable getTransferable(Point origin);
  
  	public void onDragEnter() {
  
  	}
  
  	public void onDragOver() {
  
  	}
  
  	public void onDragExit() {
  
  	}
  
  	public final void dragDropEnd(DragSourceDropEvent e) {
  	}
  
  	public final void dragEnter(DragSourceDragEvent e) {
  		DragSourceContext context = e.getDragSourceContext();
  		int dropAction = e.getDropAction();
  		if ((dropAction & mAllowedDragAction) != 0) {
  //            if (cursor != null)
  //                context.setCursor(cursor);
  //            else
  			context.setCursor(DragSource.DefaultCopyDrop);
  		} else {
  			context.setCursor(DragSource.DefaultCopyNoDrop);
  		}
  		onDragEnter();
  	}
  
  	public final void dragOver(DragSourceDragEvent e)
  	{
  		onDragOver();
  	}
  
  	public final void dragExit(DragSourceEvent e)
  	{
  		onDragExit();
  	}
  
  	public final void dropActionChanged(DragSourceDragEvent e) {
  		DragSourceContext context = e.getDragSourceContext();
  		int dropAction = e.getDropAction();
  		if ((dropAction & mAllowedDragAction) != 0) {
  //            if (cursor != null)
  //                context.setCursor(cursor);
  //            else
  			context.setCursor(DragSource.DefaultCopyDrop);
  		} else {
  			context.setCursor(DragSource.DefaultCopyNoDrop);
  		}
  	}
  
  
  //    class WindowMovingDragSourceListener extends DragSourceAdapter implements DragSourceMotionListener {
  //
  //        private Window win;
  //        private boolean firstCall = true;
  //
  //        public WindowMovingDragSourceListener(Window w) {
  //            win = w;
  //        }
  //
  //        public void dragDropEnd(DragSourceDropEvent dsde) {
  //            System.err.println("dragDropEnd(): " + dsde);
  //            win.setVisible(false);
  //            firstCall = true;
  //        }
  //
  //        public void dragMouseMoved(DragSourceDragEvent dsde) {
  //            Point p = dsde.getLocation();
  //            p.translate(32, 16);
  //            win.setLocation(p);
  //            if (firstCall) {
  //                win.setVisible(true);
  //                firstCall = false;
  //            }
  //        }
  //    }
  
  	class DGListener implements DragGestureListener {
  		public void dragGestureRecognized(DragGestureEvent e) {
  			onDragBegin(e);
  		}
  	}
  
  
  	protected void onDragBegin(DragGestureEvent e) {
  		cursor = null;
  		if ((e.getDragAction() & mAllowedDragAction) != 0) {
  			Transferable transferable = getTransferable(e.getDragOrigin());
  			if (transferable != null) {
  				try {
  					Image img = null;
  					if (DragSource.isDragImageSupported() && (img = drawDragImage(transferable,400,400)) != null) {
  						e.startDrag(DragSource.DefaultCopyDrop, img, new Point(200, 200), transferable, this);
  					} else {
  						e.startDrag(cursor, transferable, this);
  					}
  				} catch (InvalidDnDOperationException idoe) {
  					System.err.println(idoe);
  				}
  			}
  		}
  	}
  
  	public Image drawDragImage(Transferable transferable,int width,int height) {
  		if (transferable instanceof ReactionTransferable) {
  			try {
  				MoleculeTransferable t = (MoleculeTransferable) transferable;
  				Object o = t.getTransferData(ChemistryFlavors.DF_SERIALIZED_REACTION);
  				if (o instanceof Reaction) {
  					Reaction rxn = (Reaction) o;
  					ExtendedDepictor depict = new ExtendedDepictor(rxn, null, false);
  					BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
  					Graphics g = img.getGraphics();
  					((Graphics2D)g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  					((Graphics2D)g).setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
  					SwingDrawContext context = new SwingDrawContext((Graphics2D)g);
  					depict.validateView(context, new GenericRectangle(0, 0, width, height), AbstractDepictor.cModeInflateToMaxAVBL);
  					depict.paint(context);
  					return img;
  				}
  			} catch (IOException e1) {
  				System.err.println(e1);
  			} catch (UnsupportedFlavorException e1) {
  				System.err.println(e1);
  			}
  		}
  		return null;
  	}
  
  
  //    final Window w = new Window() {
  //                public void paint(Graphics g) {
  //                    g.drawString("image", 5, 20); // or render an image via g.drawImage()
  //                }
  //            };
  
  }
  