/*******************************************************************************
* Copyright (c) 2012 Arapiki Solutions Inc.
* 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:
* psmith - initial API and
* implementation and/or initial documentation
*******************************************************************************/
package com.buildml.eclipse.utils.dnd;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import org.eclipse.swt.dnd.ByteArrayTransfer;
import org.eclipse.swt.dnd.TransferData;
/**
* A drag/drop Transfer type for transfer BuildML elements between views/editors. An
* "element" is a file, action, package, package folder, etc., which all have internal
* numeric IDs within a BuildStore. Therefore, to move one of these elements, we simply
* need to specify the the top of element and the ID number.
*
* @author Peter Smith <psmith@arapiki.com>
*/
public class BuildMLTransfer extends ByteArrayTransfer {
/*=====================================================================================*
* FIELDS/TYPES
*=====================================================================================*/
/** This Transfer's type name */
private static final String MY_TYPE_NAME = "BuildMLTransferType";
/** The type ID (provided by the drag/drop framework */
private static final int MY_TYPE_ID = registerType(MY_TYPE_NAME);
/** The singleton instance of this class */
private static BuildMLTransfer _instance = new BuildMLTransfer();
/*=====================================================================================*
* CONSTRUCTORS
*=====================================================================================*/
/**
* @return The singleton instance of the BuildMLTransfer class.
*/
public static BuildMLTransfer getInstance() {
return _instance;
}
/*-------------------------------------------------------------------------------------*/
/**
* Private constructor - This class can't be instantiated
*/
private BuildMLTransfer() {}
/*=====================================================================================*
* PUBLIC METHODS
*=====================================================================================*/
/*
* Serialize one or more BuildTransferType objects into their byte-stream representation.
* It is this byte buffer that will be passed from drag-source to drop-target.
*/
@Override
public void javaToNative(Object object, TransferData transferData) {
/* we can only transfer a valid array of BuildMLTransferType */
if ((object == null) || !(object instanceof BuildMLTransferType[])) {
return;
}
if (isSupportedType(transferData)) {
BuildMLTransferType[] myTypes = (BuildMLTransferType[])object;
try {
/* write data to a byte array */
ByteArrayOutputStream out = new ByteArrayOutputStream();
DataOutputStream writeOut = new DataOutputStream(out);
/*
* Write all transferring types in the same buffer. We write
* the type and id as integers, and the BuildStore reference
* using its toString() form.
*/
int length = myTypes.length;
writeOut.writeInt(length);
/* for each BuildMLTransferType in the input array, serialize the object */
for (int i = 0; i < length; i++) {
byte[] buildStoreBuffer = myTypes[i].owner.toString().getBytes();
writeOut.writeInt(buildStoreBuffer.length);
writeOut.write(buildStoreBuffer);
writeOut.writeInt(myTypes[i].type);
writeOut.writeInt(myTypes[i].id);
}
byte[] buffer = out.toByteArray();
writeOut.close();
/* ask our super class to perform the transfer */
super.javaToNative(buffer, transferData);
} catch (IOException e) {
/* won't happen when writing to a byte array */
}
}
}
/*-------------------------------------------------------------------------------------*/
/**
* De-serialized one or more BuildMLTransferType objects from an incoming byte stream
* into a outgoing array of objects. This is used when a byte stream is sent from
* drag-source to drop-target, and needs to be converted back into objects.
*/
@Override
protected Object nativeToJava(TransferData transferData) {
if (isSupportedType(transferData)) {
/* ask our parent class for the raw transferred data */
byte buffer[] = (byte[])super.nativeToJava(transferData);
if (buffer == null) {
return null;
}
/* read the objects from the byte array */
ByteArrayInputStream in = new ByteArrayInputStream(buffer);
DataInputStream readIn = new DataInputStream(in);
BuildMLTransferType[] myData = null;
try {
int length = readIn.readInt();
myData = new BuildMLTransferType[length];
/* for each entry, create a new BuildMLTransferType... */
for (int i = 0; i != length; i++) {
int buildStoreSize = readIn.readInt();
byte[] buildStoreBuffer = new byte[buildStoreSize];
readIn.read(buildStoreBuffer);
int type = readIn.readInt();
int id = readIn.readInt();
myData[i] = new BuildMLTransferType(new String(buildStoreBuffer),
type, id);
}
} catch (IOException e) {
return null;
}
return myData;
}
return null;
}
/*=====================================================================================*
* PROTECTED METHODS
*=====================================================================================*/
/* (non-Javadoc)
* @see org.eclipse.swt.dnd.Transfer#getTypeNames()
*/
@Override
protected String[] getTypeNames() {
return new String[] { MY_TYPE_NAME };
}
/*-------------------------------------------------------------------------------------*/
/* (non-Javadoc)
* @see org.eclipse.swt.dnd.Transfer#getTypeIds()
*/
@Override
protected int[] getTypeIds() {
return new int[] { MY_TYPE_ID };
}
/*-------------------------------------------------------------------------------------*/
}