1 /******************************************************************************* 2 * Copyright (c) 2000, 2008 IBM Corporation and others. 3 * All rights reserved. This program and the accompanying materials 4 * are made available under the terms of the Eclipse Public License v1.0 5 * which accompanies this distribution, and is available at 6 * http://www.eclipse.org/legal/epl-v10.html 7 * 8 * Contributors: 9 * IBM Corporation - initial API and implementation 10 * Port to the D programming language: 11 * Frank Benoit <benoit@tionex.de> 12 *******************************************************************************/ 13 module org.eclipse.swt.dnd.ByteArrayTransfer; 14 15 import org.eclipse.swt.internal.gtk.OS; 16 import org.eclipse.swt.dnd.Transfer; 17 import org.eclipse.swt.dnd.TransferData; 18 import org.eclipse.swt.dnd.DND; 19 import java.lang.all; 20 21 /** 22 * The class <code>ByteArrayTransfer</code> provides a platform specific 23 * mechanism for converting a java <code>byte[]</code> to a platform 24 * specific representation of the byte array and vice versa. 25 * 26 * <p><code>ByteArrayTransfer</code> is never used directly but is sub-classed 27 * by transfer agents that convert between data in a java format such as a 28 * <code>String</code> and a platform specific byte array. 29 * 30 * <p>If the data you are converting <b>does not</b> map to a 31 * <code>byte[]</code>, you should sub-class <code>Transfer</code> directly 32 * and do your own mapping to a platform data type.</p> 33 * 34 * <p>The following snippet shows a subclass of ByteArrayTransfer that transfers 35 * data defined by the class <code>MyType</code>.</p> 36 * 37 * <pre><code> 38 * public class MyType { 39 * public String fileName; 40 * public long fileLength; 41 * public long lastModified; 42 * } 43 * </code></pre> 44 * 45 * <pre><code> 46 * public class MyTypeTransfer extends ByteArrayTransfer { 47 * 48 * private static final String MYTYPENAME = "my_type_name"; 49 * private static final int MYTYPEID = registerType(MYTYPENAME); 50 * private static MyTypeTransfer _instance = new MyTypeTransfer(); 51 * 52 * private MyTypeTransfer() {} 53 * 54 * public static MyTypeTransfer getInstance () { 55 * return _instance; 56 * } 57 * public void javaToNative (Object object, TransferData transferData) { 58 * if (object is null || !(object instanceof MyType[])) return; 59 * 60 * if (isSupportedType(transferData)) { 61 * MyType[] myTypes = (MyType[]) object; 62 * try { 63 * // write data to a byte array and then ask super to convert to pMedium 64 * ByteArrayOutputStream out = new ByteArrayOutputStream(); 65 * DataOutputStream writeOut = new DataOutputStream(out); 66 * for (int i = 0, length = myTypes.length; i < length; i++){ 67 * byte[] buffer = myTypes[i].fileName.getBytes(); 68 * writeOut.writeInt(buffer.length); 69 * writeOut.write(buffer); 70 * writeOut.writeLong(myTypes[i].fileLength); 71 * writeOut.writeLong(myTypes[i].lastModified); 72 * } 73 * byte[] buffer = out.toByteArray(); 74 * writeOut.close(); 75 * 76 * super.javaToNative(buffer, transferData); 77 * 78 * } catch (IOException e) { 79 * } 80 * } 81 * } 82 * public Object nativeToJava(TransferData transferData){ 83 * 84 * if (isSupportedType(transferData)) { 85 * 86 * byte[] buffer = (byte[])super.nativeToJava(transferData); 87 * if (buffer is null) return null; 88 * 89 * MyType[] myData = new MyType[0]; 90 * try { 91 * ByteArrayInputStream in = new ByteArrayInputStream(buffer); 92 * DataInputStream readIn = new DataInputStream(in); 93 * while(readIn.available() > 20) { 94 * MyType datum = new MyType(); 95 * int size = readIn.readInt(); 96 * byte[] name = new byte[size]; 97 * readIn.read(name); 98 * datum.fileName = new String(name); 99 * datum.fileLength = readIn.readLong(); 100 * datum.lastModified = readIn.readLong(); 101 * MyType[] newMyData = new MyType[myData.length + 1]; 102 * System.arraycopy(myData, 0, newMyData, 0, myData.length); 103 * newMyData[myData.length] = datum; 104 * myData = newMyData; 105 * } 106 * readIn.close(); 107 * } catch (IOException ex) { 108 * return null; 109 * } 110 * return myData; 111 * } 112 * 113 * return null; 114 * } 115 * protected String[] getTypeNames(){ 116 * return new String[]{MYTYPENAME}; 117 * } 118 * protected int[] getTypeIds(){ 119 * return new int[] {MYTYPEID}; 120 * } 121 * } 122 * </code></pre> 123 * 124 * @see Transfer 125 */ 126 public abstract class ByteArrayTransfer : Transfer { 127 128 public override TransferData[] getSupportedTypes() { 129 int[] types = getTypeIds(); 130 TransferData[] data = new TransferData[types.length]; 131 for (int i = 0; i < types.length; i++) { 132 data[i] = new TransferData(); 133 data[i].type = cast(void*)types[i]; 134 } 135 return data; 136 } 137 138 public override bool isSupportedType(TransferData transferData){ 139 if (transferData is null) return false; 140 int[] types = getTypeIds(); 141 for (int i = 0; i < types.length; i++) { 142 if (transferData.type is cast(void*)types[i]) return true; 143 } 144 return false; 145 } 146 147 /** 148 * This implementation of <code>javaToNative</code> converts a java 149 * <code>byte[]</code> to a platform specific representation. 150 * 151 * @param object a java <code>byte[]</code> containing the data to be converted 152 * @param transferData an empty <code>TransferData</code> object that will 153 * be filled in on return with the platform specific format of the data 154 * 155 * @see Transfer#nativeToJava 156 */ 157 protected override void javaToNative (Object object, TransferData transferData) { 158 transferData.result = 0; 159 if (!checkByteArray(object) || !isSupportedType(transferData)) { 160 DND.error(DND.ERROR_INVALID_DATA); 161 } 162 byte[] buffer = (cast(ArrayWrapperByte)object).array; 163 if (buffer.length is 0) return; 164 byte* pValue = cast(byte*)OS.g_malloc(buffer.length); 165 if (pValue is null) return; 166 pValue[ 0 .. buffer.length ] = buffer; 167 transferData.length = cast(int)/*64bit*/buffer.length; 168 transferData.format = 8; 169 transferData.pValue = cast(char*)pValue; 170 transferData.result = 1; 171 } 172 173 /** 174 * This implementation of <code>nativeToJava</code> converts a platform specific 175 * representation of a byte array to a java <code>byte[]</code>. 176 * 177 * @param transferData the platform specific representation of the data to be converted 178 * @return a java <code>byte[]</code> containing the converted data if the conversion was 179 * successful; otherwise null 180 * 181 * @see Transfer#javaToNative 182 */ 183 protected override Object nativeToJava(TransferData transferData) { 184 if ( !isSupportedType(transferData) || transferData.pValue is null) return null; 185 int size = transferData.format * transferData.length / 8; 186 if (size is 0) return null; 187 byte* ptr = cast(byte*)transferData.pValue; 188 return new ArrayWrapperByte( ptr[ 0 .. size ].dup ); 189 } 190 191 bool checkByteArray(Object object) { 192 if( object is null ) return false; 193 ArrayWrapperByte arr = cast(ArrayWrapperByte)object; 194 if( arr is null ) return false; 195 return arr.array.length > 0; 196 } 197 }