summaryrefslogtreecommitdiffstats
path: root/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet319.java
blob: e3a57c7031459f2b0d87dc632cb84665e606debd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
/*******************************************************************************
 * Copyright (c) 2000, 2009 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.snippets;

/*
 * Drag and Drop example snippet: drag and drop an object with a
 * custom data transfer type from SWT to AWT/Swing
 * 
 * Note that JRE 1.6 or newer is required on Linux.
 *
 * For a list of all SWT example snippets see
 * http://www.eclipse.org/swt/snippets/
 */
import java.awt.Frame;
import java.awt.datatransfer.*;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetAdapter;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetListener;
import java.io.*;
import java.util.Date;
import javax.swing.JLabel;

import org.eclipse.swt.*;
import org.eclipse.swt.awt.*;
import org.eclipse.swt.dnd.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

public class Snippet319 {

	/* The data flavor must be MIME type-like */
	static final String MIME_TYPE = "custom/myType"; // $NON-NLS-1$

	/* The object being transferred is defined as: */
	static class MyType {
		String name;
		long time;
	}

public static void main(String[] args) {
	new Snippet319().go();
}

public void go() {
	Display display = new Display();
	Shell shell = new Shell(display);
	shell.setBounds(10,10,600,200);

	/* Create SWT controls and add drag source */
	final Label swtLabel = new Label(shell, SWT.BORDER);
	swtLabel.setBounds(10,10,580,50);
	swtLabel.setText("SWT drag source");
	DragSource dragSource = new DragSource(swtLabel, DND.DROP_COPY);
	Transfer[] transfers = new Transfer[] {new MyTypeTransfer()};
	dragSource.setTransfer(transfers);
	dragSource.addDragListener(new DragSourceAdapter() {
		public void dragSetData(DragSourceEvent event) {
			MyType object = new MyType();
			object.name = "content dragged from SWT";
			object.time = System.currentTimeMillis();
			event.data = object;
		}
	});

	/* Create AWT/Swing controls */
	Composite embeddedComposite = new Composite(shell, SWT.EMBEDDED);
	embeddedComposite.setBounds(10, 100, 580, 50);
	embeddedComposite.setLayout(new FillLayout());
	Frame frame = SWT_AWT.new_Frame(embeddedComposite);
	final JLabel jLabel = new JLabel("AWT/Swing drop target");
	frame.add(jLabel);

	/* Register the custom data flavour */
	final DataFlavor flavor = new DataFlavor(MIME_TYPE, "MyType custom flavor");
	/* 
	 * Note that according to jre/lib/flavormap.properties, the preferred way to
	 * augment the default system flavor map is to specify the AWT.DnD.flavorMapFileURL
	 * property in an awt.properties file.
	 * 
	 * This snippet uses the alternate approach below in order to provide a simple
	 * stand-alone snippet that demonstrates the functionality.  This implementation
	 * works well, but if the instanceof check below fails for some reason when used
	 * in a different context then the drop will not be accepted.
	 */
	FlavorMap map = SystemFlavorMap.getDefaultFlavorMap();
	if (map instanceof SystemFlavorMap) {
		SystemFlavorMap systemMap = (SystemFlavorMap)map;
		systemMap.addFlavorForUnencodedNative(MIME_TYPE, flavor);
	}

	/* add drop target */
	DropTargetListener dropTargetListener = new DropTargetAdapter() {
		public void drop(DropTargetDropEvent dropTargetDropEvent) {
			try {
				dropTargetDropEvent.acceptDrop(DnDConstants.ACTION_COPY);
				ByteArrayInputStream inStream = (ByteArrayInputStream)dropTargetDropEvent.getTransferable().getTransferData(flavor);
				int available = inStream.available();
				byte[] bytes = new byte[available];
				inStream.read(bytes);
				MyType object = restoreFromByteArray(bytes);
				String string = object.name + ": " + new Date(object.time).toString();
				jLabel.setText(string);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	};
	new DropTarget(jLabel, dropTargetListener);

	shell.open();
	while (!shell.isDisposed()) {
		if (!display.readAndDispatch()) display.sleep();
	}
	display.dispose();
}


/* SWT custom data transfer implementation */

class MyTypeTransfer extends ByteArrayTransfer {

	final int MIME_TYPE_ID = registerType(MIME_TYPE);

	protected int[] getTypeIds() {
		return new int[] {MIME_TYPE_ID};
	}

	protected String[] getTypeNames() {
		return new String[] {MIME_TYPE};
	}

public void javaToNative(Object object, TransferData transferData) {
	if (!checkMyType(object) || !isSupportedType(transferData)) {
		DND.error(DND.ERROR_INVALID_DATA);
	}
	MyType myType = (MyType)object;
	byte[] bytes = convertToByteArray(myType);
	if (bytes != null) {
		super.javaToNative(bytes, transferData);
	}
}

public Object nativeToJava(TransferData transferData) {
	if (!isSupportedType(transferData)) return null;
	byte[] bytes = (byte[])super.nativeToJava(transferData);
	return bytes == null ? null : restoreFromByteArray(bytes);
}

boolean checkMyType(Object object) {
	if (object == null) return false;
	MyType myType = (MyType)object;
	return myType != null && myType.name != null && myType.name.length() > 0 && myType.time > 0;
}

protected boolean validate(Object object) {
	return checkMyType(object);
}
}


/* shared methods for converting instances of MyType <-> byte[] */

static byte[] convertToByteArray(MyType type) {
	DataOutputStream dataOutStream = null;
	try {
		ByteArrayOutputStream byteOutStream = new ByteArrayOutputStream();
		dataOutStream = new DataOutputStream(byteOutStream);
		byte[] bytes = type.name.getBytes();
		dataOutStream.writeInt(bytes.length);
		dataOutStream.write(bytes);
		dataOutStream.writeLong(type.time);
		return byteOutStream.toByteArray();
	} catch (IOException e) {
		return null;
	} finally {
		if (dataOutStream != null) {
			try {
				dataOutStream.close();
			} catch (IOException e) {}
		}
	}
}

static MyType restoreFromByteArray(byte[] bytes) {
	DataInputStream dataInStream = null;
	try {
		ByteArrayInputStream byteInStream = new ByteArrayInputStream(bytes);
		dataInStream = new DataInputStream(byteInStream);
		int size = dataInStream.readInt();
		byte[] name = new byte[size];
		dataInStream.read(name);
		MyType result = new MyType();
		result.name = new String(name);
		result.time = dataInStream.readLong();
		return result;
	} catch (IOException ex) {
		return null;
	} finally {
		if (dataInStream != null) {
			try {
				dataInStream.close();
			} catch (IOException e) {}
		}
	}
}

}