root/dwt/dnd/ByteArrayTransfer.d

Revision 320:da968414c383, 7.9 kB (checked in by Frank Benoit <benoit@tionex.de>, 2 months ago)

Merge changes SWT 3.4.1

Line 
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 dwt.dnd.ByteArrayTransfer;
14
15 import dwt.internal.ole.win32.COM;
16 import dwt.internal.ole.win32.OBJIDL;
17 import dwt.internal.win32.OS;
18
19 import dwt.dnd.DND;
20 import dwt.dnd.Transfer;
21 import dwt.dnd.TransferData;
22
23 import dwt.dwthelper.utils;
24
25 /**
26  * The class <code>ByteArrayTransfer</code> provides a platform specific
27  * mechanism for converting a java <code>byte[]</code> to a platform
28  * specific representation of the byte array and vice versa.
29  *
30  * <p><code>ByteArrayTransfer</code> is never used directly but is sub-classed
31  * by transfer agents that convert between data in a java format such as a
32  * <code>String</code> and a platform specific byte array.
33  *
34  * <p>If the data you are converting <b>does not</b> map to a
35  * <code>byte[]</code>, you should sub-class <code>Transfer</code> directly
36  * and do your own mapping to a platform data type.</p>
37  *
38  * <p>The following snippet shows a subclass of ByteArrayTransfer that transfers
39  * data defined by the class <code>MyType</code>.</p>
40  *
41  * <pre><code>
42  * public class MyType {
43  *  public String fileName;
44  *  public long fileLength;
45  *  public long lastModified;
46  * }
47  * </code></pre>
48  *
49  * <pre><code>
50  * public class MyTypeTransfer extends ByteArrayTransfer {
51  *
52  *  private static final String MYTYPENAME = "my_type_name";
53  *  private static final int MYTYPEID = registerType(MYTYPENAME);
54  *  private static MyTypeTransfer _instance = new MyTypeTransfer();
55  *
56  * private MyTypeTransfer() {}
57  *
58  * public static MyTypeTransfer getInstance () {
59  *  return _instance;
60  * }
61  * public void javaToNative (Object object, TransferData transferData) {
62  *  if (object is null || !(object instanceof MyType[])) return;
63  *
64  *  if (isSupportedType(transferData)) {
65  *      MyType[] myTypes = (MyType[]) object;
66  *      try {
67  *          // write data to a byte array and then ask super to convert to pMedium
68  *          ByteArrayOutputStream out = new ByteArrayOutputStream();
69  *          DataOutputStream writeOut = new DataOutputStream(out);
70  *          for (int i = 0, length = myTypes.length; i &lt; length;  i++){
71  *              byte[] buffer = myTypes[i].fileName.getBytes();
72  *              writeOut.writeInt(buffer.length);
73  *              writeOut.write(buffer);
74  *              writeOut.writeLong(myTypes[i].fileLength);
75  *              writeOut.writeLong(myTypes[i].lastModified);
76  *          }
77  *          byte[] buffer = out.toByteArray();
78  *          writeOut.close();
79  *
80  *          super.javaToNative(buffer, transferData);
81  *
82  *      } catch (IOException e) {
83  *      }
84  *  }
85  * }
86  * public Object nativeToJava(TransferData transferData){
87  *
88  *  if (isSupportedType(transferData)) {
89  *
90  *      byte[] buffer = (byte[])super.nativeToJava(transferData);
91  *      if (buffer is null) return null;
92  *
93  *      MyType[] myData = new MyType[0];
94  *      try {
95  *          ByteArrayInputStream in = new ByteArrayInputStream(buffer);
96  *          DataInputStream readIn = new DataInputStream(in);
97  *          while(readIn.available() > 20) {
98  *              MyType datum = new MyType();
99  *              int size = readIn.readInt();
100  *              byte[] name = new byte[size];
101  *              readIn.read(name);
102  *              datum.fileName = new String(name);
103  *              datum.fileLength = readIn.readLong();
104  *              datum.lastModified = readIn.readLong();
105  *              MyType[] newMyData = new MyType[myData.length + 1];
106  *              System.arraycopy(myData, 0, newMyData, 0, myData.length);
107  *              newMyData[myData.length] = datum;
108  *              myData = newMyData;
109  *          }
110  *          readIn.close();
111  *      } catch (IOException ex) {
112  *          return null;
113  *      }
114  *      return myData;
115  *  }
116  *
117  *  return null;
118  * }
119  * protected String[] getTypeNames(){
120  *  return new String[]{MYTYPENAME};
121  * }
122  * protected int[] getTypeIds(){
123  *  return new int[] {MYTYPEID};
124  * }
125  * }
126  * </code></pre>
127  *
128  * @see Transfer
129  */
130 public abstract class ByteArrayTransfer : Transfer {
131
132 public TransferData[] getSupportedTypes() {
133     int[] types = getTypeIds();
134     TransferData[] data = new TransferData[types.length];
135     for (int i = 0; i < types.length; i++) {
136         data[i] = new TransferData();
137         data[i].type = types[i];
138         data[i].formatetc = new FORMATETC();
139         data[i].formatetc.cfFormat = types[i];
140         data[i].formatetc.dwAspect = COM.DVASPECT_CONTENT;
141         data[i].formatetc.lindex = -1;
142         data[i].formatetc.tymed = COM.TYMED_HGLOBAL;
143     }
144     return data;
145 }
146
147 public bool isSupportedType(TransferData transferData){
148     if (transferData is null) return false;
149     int[] types = getTypeIds();
150     for (int i = 0; i < types.length; i++) {
151         FORMATETC* format = transferData.formatetc;
152         if (format.cfFormat is types[i] &&
153             (format.dwAspect & COM.DVASPECT_CONTENT) is COM.DVASPECT_CONTENT &&
154             (format.tymed & COM.TYMED_HGLOBAL) is COM.TYMED_HGLOBAL  )
155             return true;
156     }
157     return false;
158 }
159
160 /**
161  * This implementation of <code>javaToNative</code> converts a java
162  * <code>byte[]</code> to a platform specific representation.
163  *
164  * @param object a java <code>byte[]</code> containing the data to be converted
165  * @param transferData an empty <code>TransferData</code> object that will
166  *      be filled in on return with the platform specific format of the data
167  *
168  * @see Transfer#nativeToJava
169  */
170 protected void javaToNative (Object object, TransferData transferData) {
171     if (!checkByteArray(object) || !isSupportedType(transferData)) {
172         DND.error(DND.ERROR_INVALID_DATA);
173     }
174     // Allocate the memory because the caller (DropTarget) has not handed it in
175     // The caller of this method must release the data when it is done with it.
176     byte[] data = (cast(ArrayWrapperByte)object).array;
177     int size = data.length;
178     auto newPtr = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, size);
179     OS.MoveMemory(newPtr, data.ptr, size);
180     transferData.stgmedium = new STGMEDIUM();
181     transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
182     transferData.stgmedium.unionField = newPtr;
183     transferData.stgmedium.pUnkForRelease = null;
184     transferData.result = COM.S_OK;
185 }
186
187 /**
188  * This implementation of <code>nativeToJava</code> converts a platform specific
189  * representation of a byte array to a java <code>byte[]</code>.
190  *
191  * @param transferData the platform specific representation of the data to be converted
192  * @return a java <code>byte[]</code> containing the converted data if the conversion was
193  *      successful; otherwise null
194  *
195  * @see Transfer#javaToNative
196  */
197 protected Object nativeToJava(TransferData transferData) {
198     if (!isSupportedType(transferData) || transferData.pIDataObject is null)  return null;
199
200     IDataObject data = transferData.pIDataObject;
201     data.AddRef();
202     FORMATETC* formatetc = transferData.formatetc;
203     STGMEDIUM* stgmedium = new STGMEDIUM();
204     stgmedium.tymed = COM.TYMED_HGLOBAL;
205     transferData.result = getData(data, formatetc, stgmedium);
206     data.Release();
207     if (transferData.result !is COM.S_OK) return null;
208     auto hMem = stgmedium.unionField;
209     int size = OS.GlobalSize(hMem);
210     byte[] buffer = new byte[size];
211     auto ptr = OS.GlobalLock(hMem);
212     OS.MoveMemory(buffer.ptr, ptr, size);
213     OS.GlobalUnlock(hMem);
214     OS.GlobalFree(hMem);
215     return new ArrayWrapperByte(buffer);
216 }
217
218 bool checkByteArray(Object object) {
219     return (object !is null && ( null !is cast(ArrayWrapperByte)object) && (cast(ArrayWrapperByte)object).array.length > 0);
220 }
221 }
Note: See TracBrowser for help on using the browser.