blob: 829621c5777cf4443426eca9c1690b1dd8ac5f64 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2016 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* 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.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetAdapter;
import java.awt.dnd.DropTargetListener;
import java.io.*;
import java.util.*;
import javax.swing.*;
import org.eclipse.swt.*;
import org.eclipse.swt.awt.*;
import org.eclipse.swt.dnd.*;
import org.eclipse.swt.dnd.DragSource;
import org.eclipse.swt.dnd.DragSourceAdapter;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
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.setText("Snippet 319");
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);
dragSource.setTransfer(new MyTypeTransfer());
dragSource.addDragListener(new DragSourceAdapter() {
@Override
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() {
@Override
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);
@Override
protected int[] getTypeIds() {
return new int[] {MIME_TYPE_ID};
}
@Override
protected String[] getTypeNames() {
return new String[] {MIME_TYPE};
}
@Override
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);
}
}
@Override
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;
}
@Override
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) {}
}
}
}
}