1/*
2 * Copyright (c) 2009, 2013, 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
28import java.awt.*;
29import java.awt.datatransfer.*;
30import java.awt.dnd.*;
31import java.io.*;
32
33class DnDSource extends Button implements Transferable,
34        DragGestureListener,
35        DragSourceListener {
36    private DataFlavor df;
37    private transient int dropAction;
38    private final int dragOperation = DnDConstants.ACTION_COPY | DnDConstants.ACTION_MOVE | DnDConstants.ACTION_LINK;
39    DragSource dragSource = new DragSource();
40
41    DnDSource(String label) {
42        super(label);
43        setBackground(Color.yellow);
44        setForeground(Color.blue);
45        df = new DataFlavor(DnDSource.class, "DnDSource");
46
47        dragSource.createDefaultDragGestureRecognizer(
48                this,
49                dragOperation,
50                this
51        );
52        dragSource.addDragSourceListener(this);
53    }
54
55    public void changeCursor(
56            DragSourceContext dsc,
57            int ra
58    ) {
59        java.awt.Cursor c = null;
60        if ((ra & DnDConstants.ACTION_LINK) == DnDConstants.ACTION_LINK)
61            c = DragSource.DefaultLinkDrop;
62        else if ((ra & DnDConstants.ACTION_MOVE) == DnDConstants.ACTION_MOVE)
63            c = MyCursor.MOVE;//DragSource.DefaultMoveDrop;
64        else if ((ra & DnDConstants.ACTION_COPY) == DnDConstants.ACTION_COPY)
65            c = MyCursor.COPY;
66        else
67            c = MyCursor.NO_DROP;
68        dsc.setCursor(c);
69    }
70
71    /**
72     * a Drag gesture has been recognized
73     */
74
75    public void dragGestureRecognized(DragGestureEvent dge) {
76        System.out.println("starting Drag");
77        try {
78            if (DragSource.isDragImageSupported()) {
79                System.out.println("starting Imaged Drag");
80                dge.startDrag(
81                        null,
82                        new ImageGenerator(50, 100, new Color(0xff, 0xff, 0xff, 0x00) ) {
83                                @Override public void paint(Graphics gr) {
84                                    gr.translate(width/2, height/2);
85                                    ((Graphics2D)gr).setStroke(new BasicStroke(3));
86                                    int R = width/4+5;
87                                    gr.setColor(Color.BLUE);
88                                    gr.fillRect(-R, -R, 2*R, 2*R);
89                                    gr.setColor(Color.CYAN);
90                                    gr.drawRect(-R, -R, 2*R, 2*R);
91
92
93                                    gr.translate(10, 10);
94                                    R -= 5;
95                                    gr.setColor(Color.RED);
96                                    gr.fillOval(-R, -R, 2*R, 2*R);
97                                    gr.setColor(Color.MAGENTA);
98                                    gr.drawOval(-R, -R, 2*R, 2*R);
99                                }
100                        }.getImage(),
101                        new Point(15, 40),
102                        this,
103                        this);
104            } else {
105                dge.startDrag(
106                        null,
107                        this,
108                        this);
109            }
110        } catch (InvalidDnDOperationException e) {
111            e.printStackTrace();
112        }
113    }
114
115    /**
116     * as the hotspot enters a platform dependent drop site
117     */
118
119    public void dragEnter(DragSourceDragEvent dsde) {
120        System.out.println("[Source] dragEnter");
121        changeCursor(
122            dsde.getDragSourceContext(),
123            dsde.getUserAction() & dsde.getDropAction()
124        );
125    }
126
127    /**
128     * as the hotspot moves over a platform dependent drop site
129     */
130    public void dragOver(DragSourceDragEvent dsde) {
131        System.out.println("[Source] dragOver");
132        changeCursor(
133            dsde.getDragSourceContext(),
134            dsde.getUserAction() & dsde.getDropAction()
135        );
136        dropAction = dsde.getUserAction() & dsde.getDropAction();
137        System.out.println("dropAction = " + dropAction);
138    }
139
140    /**
141     * as the hotspot exits a platform dependent drop site
142     */
143    public void dragExit(DragSourceEvent dse) {
144        System.out.println("[Source] dragExit");
145        changeCursor(
146                dse.getDragSourceContext(),
147                DnDConstants.ACTION_NONE
148        );
149    }
150
151    /**
152     * as the operation changes
153     */
154    public void dragGestureChanged(DragSourceDragEvent dsde) {
155        System.out.println("[Source] dragGestureChanged");
156        changeCursor(
157            dsde.getDragSourceContext(),
158            dsde.getUserAction() & dsde.getDropAction()
159        );
160        dropAction = dsde.getUserAction() & dsde.getDropAction();
161        System.out.println("dropAction = " + dropAction);
162    }
163
164
165    /**
166     * as the operation completes
167     */
168    public void dragDropEnd(DragSourceDropEvent dsde) {
169        System.out.println("[Source] dragDropEnd");
170    }
171
172    public void dropActionChanged(DragSourceDragEvent dsde) {
173        System.out.println("[Source] dropActionChanged");
174        dropAction = dsde.getUserAction() & dsde.getDropAction();
175        System.out.println("dropAction = " + dropAction);
176    }
177
178    public DataFlavor[] getTransferDataFlavors() {
179        return new DataFlavor[]{df};
180    }
181
182    public boolean isDataFlavorSupported(DataFlavor sdf) {
183        return df.equals(sdf);
184    }
185
186    public Object getTransferData(DataFlavor tdf) throws UnsupportedFlavorException, IOException {
187        Object copy = null;
188        if( !df.equals(tdf) ){
189            throw new UnsupportedFlavorException(tdf);
190        }
191        Container parent = getParent();
192        switch (dropAction) {
193            case DnDConstants.ACTION_COPY:
194                try {
195                    copy = this.clone();
196                } catch (CloneNotSupportedException e) {
197                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
198                    ObjectOutputStream oos = new ObjectOutputStream(baos);
199
200                    oos.writeObject(this);
201                    ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
202                    ObjectInputStream ois = new ObjectInputStream(bais);
203                    try {
204                        copy = ois.readObject();
205                    } catch (ClassNotFoundException cnfe) {
206                        // do nothing
207                    }
208                }
209                parent.add(this);
210                return copy;
211
212            case DnDConstants.ACTION_MOVE:
213                synchronized (this) {
214                    if (parent != null) {
215                        parent.remove(this);
216                        Label label = new Label("[empty]");
217                        label.setBackground(Color.cyan);
218                        label.setBounds(this.getBounds());
219                        parent.add(label);
220                    }
221                }
222                return this;
223
224            case DnDConstants.ACTION_LINK:
225                return this;
226
227            default:
228                return null;
229        }
230
231    }
232}
233
234