1 /*
   2  * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25 *  AWT Button is a DragSource and also a transferable object
  26 */
  27 
  28 import java.awt.*;
  29 import java.awt.datatransfer.*;
  30 
  31 import java.awt.image.ImageConsumer;
  32 import java.awt.image.MemoryImageSource;
  33 
  34 import java.awt.dnd.*;
  35 import java.io.*;
  36 
  37 class DnDSource extends Button implements Transferable,
  38         DragGestureListener,
  39         DragSourceListener {
  40     private DataFlavor df;
  41     private transient int dropAction;
  42     private final int dragOperation = DnDConstants.ACTION_COPY | DnDConstants.ACTION_MOVE | DnDConstants.ACTION_LINK;
  43     DragSource dragSource = new DragSource();
  44 
  45     DnDSource(String label) {
  46         super(label);
  47         setBackground(Color.yellow);
  48         setForeground(Color.blue);
  49         df = new DataFlavor(DnDSource.class, "DnDSource");
  50 
  51         dragSource.createDefaultDragGestureRecognizer(
  52                 this,
  53                 dragOperation,
  54                 this
  55         );
  56         dragSource.addDragSourceListener(this);
  57     }
  58 
  59     public void changeCursor(
  60             DragSourceContext dsc,
  61             int ra
  62     ) {
  63         java.awt.Cursor c = null;
  64         if ((ra & DnDConstants.ACTION_LINK) == DnDConstants.ACTION_LINK)
  65             c = DragSource.DefaultLinkDrop;
  66         else if ((ra & DnDConstants.ACTION_MOVE) == DnDConstants.ACTION_MOVE)
  67             c = MyCursor.MOVE;//DragSource.DefaultMoveDrop;
  68         else if ((ra & DnDConstants.ACTION_COPY) == DnDConstants.ACTION_COPY)
  69             c = MyCursor.COPY;
  70         else
  71             c = MyCursor.NO_DROP;
  72         dsc.setCursor(c);
  73     }
  74 
  75     /**
  76      * a Drag gesture has been recognized
  77      */
  78     int iProblem = 0;
  79     String[] problem = {"unready", "throw exeption", "good"};
  80     public void dragGestureRecognized(DragGestureEvent dge) {
  81         System.out.println("starting Drag");
  82         if( !DragSource.isDragImageSupported() ) {
  83             dge.startDrag(
  84                     null,
  85                     this,
  86                     this);
  87         } else {
  88             setLabel("Drag ME! (with " + problem[iProblem] + " image)");
  89             int w = 100;
  90             int h = 100;
  91             int pix[] = new int[w * h];
  92             int index = 0;
  93             for (int y = 0; y < h; y++) {
  94                 int red = (y * 255) / (h - 1);
  95                 for (int x = 0; x < w; x++) {
  96                     int blue = (x * 255) / (w - 1);
  97                     pix[index++] = (255 << 24) | (red << 16) | blue;
  98                 }
  99             }
 100             try{
 101                 dge.startDrag(
 102                         null,
 103                         Toolkit.getDefaultToolkit().createImage(new MemoryImageSource(w, h, pix, 0, w)
 104                             {
 105                                 @Override
 106                                 public void startProduction(ImageConsumer ic)
 107                                 {
 108                                     switch(iProblem){
 109                                     case 0:
 110                                         //incomplite
 111                                         break;
 112                                     case 1:
 113                                         //exception
 114                                         throw new RuntimeException("test exception 1");
 115                                     default:
 116                                         super.startProduction(ic);
 117                                         break;
 118                                     }
 119                                 }
 120                             }
 121                         ),
 122                         new Point(15, 40) {
 123                             @Override
 124                             public double getX() {
 125                                 if(2==iProblem){
 126                                     //never happen
 127                                     throw new RuntimeException("test exception 2");
 128                                 }
 129                                 return x;
 130                             }
 131                             @Override
 132                             public Point getLocation(){
 133                                 //never happen
 134                                 throw new RuntimeException("test exception 3");
 135                             }
 136                         },
 137                         this,
 138                         this);
 139             }catch(InvalidDnDOperationException e){
 140                 if( iProblem<=2 ){
 141                     System.err.println("good exception: " + e.getMessage() );
 142                 } else {
 143                     System.err.println("bad exception");
 144                     e.printStackTrace();
 145                     throw new RuntimeException(e.getMessage());
 146                 }
 147             } finally {
 148                 ++iProblem;
 149             }
 150         }
 151     }
 152 
 153     /**
 154      * as the hotspot enters a platform dependent drop site
 155      */
 156 
 157     public void dragEnter(DragSourceDragEvent dsde) {
 158         System.out.println("[Source] dragEnter");
 159         changeCursor(
 160             dsde.getDragSourceContext(),
 161             dsde.getUserAction() & dsde.getDropAction()
 162         );
 163     }
 164 
 165     /**
 166      * as the hotspot moves over a platform dependent drop site
 167      */
 168     public void dragOver(DragSourceDragEvent dsde) {
 169         System.out.println("[Source] dragOver");
 170         changeCursor(
 171             dsde.getDragSourceContext(),
 172             dsde.getUserAction() & dsde.getDropAction()
 173         );
 174         dropAction = dsde.getUserAction() & dsde.getDropAction();
 175         System.out.println("dropAction = " + dropAction);
 176     }
 177 
 178     /**
 179      * as the hotspot exits a platform dependent drop site
 180      */
 181     public void dragExit(DragSourceEvent dse) {
 182         System.out.println("[Source] dragExit");
 183         changeCursor(
 184                 dse.getDragSourceContext(),
 185                 DnDConstants.ACTION_NONE
 186         );
 187     }
 188 
 189     /**
 190      * as the operation changes
 191      */
 192     public void dragGestureChanged(DragSourceDragEvent dsde) {
 193         System.out.println("[Source] dragGestureChanged");
 194         changeCursor(
 195             dsde.getDragSourceContext(),
 196             dsde.getUserAction() & dsde.getDropAction()
 197         );
 198         dropAction = dsde.getUserAction() & dsde.getDropAction();
 199         System.out.println("dropAction = " + dropAction);
 200     }
 201 
 202 
 203     /**
 204      * as the operation completes
 205      */
 206     public void dragDropEnd(DragSourceDropEvent dsde) {
 207         System.out.println("[Source] dragDropEnd");
 208     }
 209 
 210     public void dropActionChanged(DragSourceDragEvent dsde) {
 211         System.out.println("[Source] dropActionChanged");
 212         dropAction = dsde.getUserAction() & dsde.getDropAction();
 213         System.out.println("dropAction = " + dropAction);
 214     }
 215 
 216     public DataFlavor[] getTransferDataFlavors() {
 217         return new DataFlavor[]{df};
 218     }
 219 
 220     public boolean isDataFlavorSupported(DataFlavor sdf) {
 221         return df.equals(sdf);
 222     }
 223 
 224     public Object getTransferData(DataFlavor tdf) throws UnsupportedFlavorException, IOException {
 225         Object copy = null;
 226         if( !df.equals(tdf) ){
 227             throw new UnsupportedFlavorException(tdf);
 228         }
 229         Container parent = getParent();
 230         switch (dropAction) {
 231             case DnDConstants.ACTION_COPY:
 232                 try {
 233                     copy = this.clone();
 234                 } catch (CloneNotSupportedException e) {
 235                     ByteArrayOutputStream baos = new ByteArrayOutputStream();
 236                     ObjectOutputStream oos = new ObjectOutputStream(baos);
 237 
 238                     oos.writeObject(this);
 239                     ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
 240                     ObjectInputStream ois = new ObjectInputStream(bais);
 241                     try {
 242                         copy = ois.readObject();
 243                     } catch (ClassNotFoundException cnfe) {
 244                         // do nothing
 245                     }
 246                 }
 247                 parent.add(this);
 248                 return copy;
 249 
 250             case DnDConstants.ACTION_MOVE:
 251                 synchronized (this) {
 252                     if (parent != null) {
 253                         parent.remove(this);
 254                         Label label = new Label("[empty]");
 255                         label.setBackground(Color.cyan);
 256                         label.setBounds(this.getBounds());
 257                         parent.add(label);
 258                     }
 259                 }
 260                 return this;
 261 
 262             case DnDConstants.ACTION_LINK:
 263                 return this;
 264 
 265             default:
 266                 return null;
 267         }
 268 
 269     }
 270 }
 271