# HG changeset patch
# User Frank Benoit If the data you are converting does not map to a
+ * The following snippet shows a subclass of ByteArrayTransfer that transfers
+ * data defined by the class IMPORTANT: This class is not intended to be subclassed.
+ * The DWT class library is intended to be subclassed
+ * only at specific, controlled points. This method enforces this
+ * rule unless it is overridden.
+ *
+ * IMPORTANT: By providing an implementation of this
+ * method that allows a subclass of a class which does not
+ * normally allow subclassing to be created, the implementer
+ * agrees to be fully responsible for the fact that any such
+ * subclass will likely fail between DWT releases and will be
+ * strongly platform specific. No support is provided for
+ * user-written classes which are implemented in this fashion.
+ *
+ * The ability to subclass outside of the allowed DWT classes
+ * is intended purely to enable those not on the DWT development
+ * team to implement patches in order to get around specific
+ * limitations in advance of when those limitations can be
+ * addressed by the team. Subclassing should not be attempted
+ * without an intimate and detailed understanding of the hierarchy.
+ *
+ * Currently, it is an error to invoke any method (other than
+ *
+ * In future releases of DWT, there may be more or fewer error
+ * checks and exceptions may be thrown for different reasons.
+ * Note that there are clipboard assistant applications that take ownership
+ * of data or make copies of data when it is placed on the clipboard. In these
+ * cases, it may not be possible to clear the clipboard. The clipboards value is either one of the clipboard constants defined in
+ * class NOTE: On some platforms the data will not be available once the application
+ * has exited or the display has been disposed. The following snippet shows text and RTF text being retrieved from the
+ * clipboard: The following snippet shows text and RTF text being retrieved from the
+ * clipboard: The clipboards value is either one of the clipboard constants defined in
+ * class
+ * This method gets the dispose state for the clipboard.
+ * When a clipboard has been disposed, it is an error to
+ * invoke any other method using the clipboard.
+ * NOTE: On some platforms, the data is immediately copied to the system
+ * clipboard but on other platforms it is provided upon request. As a result,
+ * if the application modifies the data object it has set on the clipboard, that
+ * modification may or may not be available when the data is subsequently
+ * requested. The following snippet shows text and RTF text being set on the copy/paste
+ * clipboard:
+ * NOTE: ERROR_CANNOT_SET_CLIPBOARD should be an DWTException, since it is a
+ * recoverable error, but can not be changed due to backward compatibility. NOTE: On some platforms, the data is immediately copied to the specified
+ * clipboard but on other platforms it is provided upon request. As a result,
+ * if the application modifies the data object it has set on the clipboard, that
+ * modification may or may not be available when the data is subsequently
+ * requested. The clipboards value is either one of the clipboard constants defined in
+ * class The following snippet shows text and RTF text being set on the copy/paste
+ * clipboard:
+ * NOTE: ERROR_CANNOT_SET_CLIPBOARD should be an DWTException, since it is a
+ * recoverable error, but can not be changed due to backward compatibility. The clipboards value is either one of the clipboard constants defined in
+ * class Note:
+ * In DND, errors are reported by throwing one of three exceptions:
+ * ByteArrayTransfer
provides a platform specific
+ * mechanism for converting a java byte[]
to a platform
+ * specific representation of the byte array and vice versa. See
+ * Transfer
for additional information.
+ *
+ * ByteArrayTransfer
is never used directly but is sub-classed
+ * by transfer agents that convert between data in a java format such as a
+ * String
and a platform specific byte array.
+ *
+ * byte[]
, you should sub-class Transfer
directly
+ * and do your own mapping to a platform data type.MyType
.
+ *
+ *
+ * public class MyType {
+ * public String fileName;
+ * public long fileLength;
+ * public long lastModified;
+ * }
+ *
+ */
+public abstract class ByteArrayTransfer : Transfer {
+
+public TransferData[] getSupportedTypes() {
+ int[] types = getTypeIds();
+ TransferData[] data = new TransferData[types.length];
+ for (int i = 0; i < types.length; i++) {
+ data[i] = new TransferData();
+ data[i].type = types[i];
+ data[i].formatetc = new FORMATETC();
+ data[i].formatetc.cfFormat = types[i];
+ data[i].formatetc.dwAspect = COM.DVASPECT_CONTENT;
+ data[i].formatetc.lindex = -1;
+ data[i].formatetc.tymed = COM.TYMED_HGLOBAL;
+ }
+ return data;
+}
+
+public bool isSupportedType(TransferData transferData){
+ if (transferData is null) return false;
+ int[] types = getTypeIds();
+ for (int i = 0; i < types.length; i++) {
+ FORMATETC* format = transferData.formatetc;
+ if (format.cfFormat is types[i] &&
+ (format.dwAspect & COM.DVASPECT_CONTENT) is COM.DVASPECT_CONTENT &&
+ (format.tymed & COM.TYMED_HGLOBAL) is COM.TYMED_HGLOBAL )
+ return true;
+ }
+ return false;
+}
+
+/**
+ * This implementation of
+ * public class MyTypeTransfer extends ByteArrayTransfer {
+ *
+ * private static final String MYTYPENAME = "my_type_name";
+ * private static final int MYTYPEID = registerType(MYTYPENAME);
+ * private static MyTypeTransfer _instance = new MyTypeTransfer();
+ *
+ * private MyTypeTransfer() {}
+ *
+ * public static MyTypeTransfer getInstance () {
+ * return _instance;
+ * }
+ * public void javaToNative (Object object, TransferData transferData) {
+ * if (object is null || !(object instanceof MyType[])) return;
+ *
+ * if (isSupportedType(transferData)) {
+ * MyType[] myTypes = (MyType[]) object;
+ * try {
+ * // write data to a byte array and then ask super to convert to pMedium
+ * ByteArrayOutputStream out = new ByteArrayOutputStream();
+ * DataOutputStream writeOut = new DataOutputStream(out);
+ * for (int i = 0, length = myTypes.length; i < length; i++){
+ * byte[] buffer = myTypes[i].fileName.getBytes();
+ * writeOut.writeInt(buffer.length);
+ * writeOut.write(buffer);
+ * writeOut.writeLong(myTypes[i].fileLength);
+ * writeOut.writeLong(myTypes[i].lastModified);
+ * }
+ * byte[] buffer = out.toByteArray();
+ * writeOut.close();
+ *
+ * super.javaToNative(buffer, transferData);
+ *
+ * } catch (IOException e) {
+ * }
+ * }
+ * }
+ * public Object nativeToJava(TransferData transferData){
+ *
+ * if (isSupportedType(transferData)) {
+ *
+ * byte[] buffer = (byte[])super.nativeToJava(transferData);
+ * if (buffer is null) return null;
+ *
+ * MyType[] myData = new MyType[0];
+ * try {
+ * ByteArrayInputStream in = new ByteArrayInputStream(buffer);
+ * DataInputStream readIn = new DataInputStream(in);
+ * while(readIn.available() > 20) {
+ * MyType datum = new MyType();
+ * int size = readIn.readInt();
+ * byte[] name = new byte[size];
+ * readIn.read(name);
+ * datum.fileName = new String(name);
+ * datum.fileLength = readIn.readLong();
+ * datum.lastModified = readIn.readLong();
+ * MyType[] newMyData = new MyType[myData.length + 1];
+ * System.arraycopy(myData, 0, newMyData, 0, myData.length);
+ * newMyData[myData.length] = datum;
+ * myData = newMyData;
+ * }
+ * readIn.close();
+ * } catch (IOException ex) {
+ * return null;
+ * }
+ * return myData;
+ * }
+ *
+ * return null;
+ * }
+ * protected String[] getTypeNames(){
+ * return new String[]{MYTYPENAME};
+ * }
+ * protected int[] getTypeIds(){
+ * return new int[] {MYTYPEID};
+ * }
+ * }
+ *
javaToNative
converts a java
+ * byte[]
to a platform specific representation. For additional
+ * information see Transfer#javaToNative
.
+ *
+ * @see Transfer#javaToNative
+ *
+ * @param object a java byte[]
containing the data to be converted
+ * @param transferData an empty TransferData
object; this
+ * object will be filled in on return with the platform specific format of the data
+ */
+protected void javaToNative (Object object, TransferData transferData) {
+ if (!checkByteArray(object) || !isSupportedType(transferData)) {
+ DND.error(DND.ERROR_INVALID_DATA);
+ }
+ // Allocate the memory because the caller (DropTarget) has not handed it in
+ // The caller of this method must release the data when it is done with it.
+ byte[] data = (cast(ArrayWrapperByte)object).array;
+ int size = data.length;
+ auto newPtr = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, size);
+ OS.MoveMemory(newPtr, data.ptr, size);
+ transferData.stgmedium = new STGMEDIUM();
+ transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
+ transferData.stgmedium.unionField = newPtr;
+ transferData.stgmedium.pUnkForRelease = null;
+ transferData.result = COM.S_OK;
+}
+
+/**
+ * This implementation of nativeToJava
converts a platform specific
+ * representation of a byte array to a java byte[]
.
+ * For additional information see Transfer#nativeToJava
.
+ *
+ * @see Transfer#nativeToJava
+ *
+ * @param transferData the platform specific representation of the data to be
+ * been converted
+ * @return a java byte[]
containing the converted data if the
+ * conversion was successful; otherwise null
+ */
+protected Object nativeToJava(TransferData transferData) {
+ if (!isSupportedType(transferData) || transferData.pIDataObject is null) return null;
+
+ IDataObject data = transferData.pIDataObject;
+ data.AddRef();
+ FORMATETC* formatetc = transferData.formatetc;
+ STGMEDIUM* stgmedium = new STGMEDIUM();
+ stgmedium.tymed = COM.TYMED_HGLOBAL;
+ transferData.result = data.GetData(formatetc, stgmedium);
+ data.Release();
+ if (transferData.result !is COM.S_OK) return null;
+ auto hMem = stgmedium.unionField;
+ int size = OS.GlobalSize(hMem);
+ byte[] buffer = new byte[size];
+ auto ptr = OS.GlobalLock(hMem);
+ OS.MoveMemory(buffer.ptr, ptr, size);
+ OS.GlobalUnlock(hMem);
+ OS.GlobalFree(hMem);
+ return new ArrayWrapperByte(buffer);
+}
+
+bool checkByteArray(Object object) {
+ return (object !is null && ( null !is cast(ArrayWrapperByte)object) && (cast(ArrayWrapperByte)object).array.length > 0);
+}
+}
diff -r fa7d7d66b9ed -r 242e33c0e383 dwt/dnd/Clipboard.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/Clipboard.d Wed Feb 13 04:51:22 2008 +0100
@@ -0,0 +1,814 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 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
+ * Port to the D programming language:
+ * Frank Benoit Clipboard
provides a mechanism for transferring data from one
+ * application to another or within an application.
+ *
+ *
+ *
+ *
+ * @see Clipboard#dispose
+ * @see Clipboard#checkSubclass
+ */
+public this(Display display) {
+ checkSubclass ();
+ if (display is null) {
+ display = Display.getCurrent();
+ if (display is null) {
+ display = Display.getDefault();
+ }
+ }
+ if (display.getThread() !is Thread.getThis()) {
+ DND.error(DWT.ERROR_THREAD_INVALID_ACCESS);
+ }
+ this.display = display;
+ TCHAR* chFormatName = StrToTCHARz(0, "Preferred DropEffect"); //$NON-NLS-1$
+ CFSTR_PREFERREDDROPEFFECT = OS.RegisterClipboardFormat(chFormatName);
+ createCOMInterfaces();
+ this.AddRef();
+}
+
+/**
+ * Checks that this class can be subclassed.
+ *
+ *
+ */
+protected void checkSubclass () {
+ char[] name = this.classinfo.name;
+ char[] validName = Clipboard.classinfo.name;
+ if (validName!=/*eq*/name) {
+ DND.error (DWT.ERROR_INVALID_SUBCLASS);
+ }
+}
+
+/**
+ * Throws an DWTException
if the receiver can not
+ * be accessed by the caller. This may include both checks on
+ * the state of the receiver and more generally on the entire
+ * execution context. This method should be called by
+ * widget implementors to enforce the standard DWT invariants.
+ * isDisposed()
) on a widget that has had its
+ * dispose()
method called. It is also an error
+ * to call widget methods from any thread that is different
+ * from the thread that created the widget.
+ *
+ *
+ */
+protected void checkWidget () {
+ Display display = this.display;
+ if (display is null) DND.error (DWT.ERROR_WIDGET_DISPOSED);
+ if (display.getThread() !is Thread.getThis ()) DND.error (DWT.ERROR_THREAD_INVALID_ACCESS);
+ if (display.isDisposed()) DND.error(DWT.ERROR_WIDGET_DISPOSED);
+}
+
+/**
+ * If this clipboard is currently the owner of the data on the system clipboard,
+ * clear the contents. If this clipboard is not the owner, then nothing is done.
+ * Note that there are clipboard assistant applications that take ownership of
+ * data or make copies of data when it is placed on the clipboard. In these
+ * cases, it may not be possible to clear the clipboard.
+ *
+ * @exception DWTException
+ *
+ *
+ * @since 3.1
+ */
+public void clearContents() {
+ clearContents(DND.CLIPBOARD);
+}
+
+/**
+ * If this clipboard is currently the owner of the data on the specified
+ * clipboard, clear the contents. If this clipboard is not the owner, then
+ * nothing is done.
+ *
+ * DND
, or must be built by bitwise OR'ing together
+ * (that is, using the int
"|" operator) two or more
+ * of those DND
clipboard constants.
+ *
+ *
+ * @see DND#CLIPBOARD
+ * @see DND#SELECTION_CLIPBOARD
+ *
+ * @since 3.1
+ */
+public void clearContents(int clipboards) {
+ checkWidget();
+ if ((clipboards & DND.CLIPBOARD) !is 0) {
+ /* OleIsCurrentClipboard([in] pDataObject)
+ * The argument pDataObject is owned by the caller so reference count does not
+ * need to be incremented.
+ */
+ if (COM.OleIsCurrentClipboard(this.iDataObject) is COM.S_OK) {
+ /* OleSetClipboard([in] pDataObject)
+ * The argument pDataObject is owned by the caller so reference count does not
+ * need to be incremented.
+ */
+ COM.OleSetClipboard(null);
+ }
+ }
+}
+
+/**
+ * Disposes of the operating system resources associated with the clipboard.
+ * The data will still be available on the system clipboard after the dispose
+ * method is called.
+ *
+ *
+ *
+ */
+public void dispose () {
+ if (isDisposed()) return;
+ if (display.getThread() !is Thread.getThis ()) DND.error(DWT.ERROR_THREAD_INVALID_ACCESS);
+ /* OleIsCurrentClipboard([in] pDataObject)
+ * The argument pDataObject is owned by the caller so reference count does not
+ * need to be incremented.
+ */
+ if (COM.OleIsCurrentClipboard(this.iDataObject) is COM.S_OK) {
+ COM.OleFlushClipboard();
+ }
+ this.Release();
+ display = null;
+}
+
+/**
+ * Retrieve the data of the specified type currently available on the system
+ * clipboard. Refer to the specific subclass of Transfer
to
+ * determine the type of object returned.
+ *
+ *
+ *
+ * @param transfer the transfer agent for the type of data being requested
+ * @return the data obtained from the clipboard or null if no data of this type is available
+ *
+ * @exception DWTException
+ * Clipboard clipboard = new Clipboard(display);
+ * TextTransfer textTransfer = TextTransfer.getInstance();
+ * String textData = (String)clipboard.getContents(textTransfer);
+ * if (textData !is null) System.out.println("Text is "+textData);
+ * RTFTransfer rtfTransfer = RTFTransfer.getInstance();
+ * String rtfData = (String)clipboard.getContents(rtfTransfer);
+ * if (rtfData !is null) System.out.println("RTF Text is "+rtfData);
+ * clipboard.dispose();
+ *
+ *
+ * @exception IllegalArgumentException
+ *
+ *
+ * @see Transfer
+ */
+public Object getContents(Transfer transfer) {
+ return getContents(transfer, DND.CLIPBOARD);
+}
+/**
+ * Retrieve the data of the specified type currently available on the specified
+ * clipboard. Refer to the specific subclass of Transfer
to
+ * determine the type of object returned.
+ *
+ *
+ *
+ *
+ * Clipboard clipboard = new Clipboard(display);
+ * TextTransfer textTransfer = TextTransfer.getInstance();
+ * String textData = (String)clipboard.getContents(textTransfer);
+ * if (textData !is null) System.out.println("Text is "+textData);
+ * RTFTransfer rtfTransfer = RTFTransfer.getInstance();
+ * String rtfData = (String)clipboard.getContents(rtfTransfer, DND.CLIPBOARD);
+ * if (rtfData !is null) System.out.println("RTF Text is "+rtfData);
+ * clipboard.dispose();
+ *
DND
, or must be built by bitwise OR'ing together
+ * (that is, using the int
"|" operator) two or more
+ * of those DND
clipboard constants.
+ *
+ * @exception IllegalArgumentException
+ *
+ *
+ * @see Transfer
+ * @see DND#CLIPBOARD
+ * @see DND#SELECTION_CLIPBOARD
+ *
+ * @since 3.1
+ */
+public Object getContents(Transfer transfer, int clipboards) {
+ checkWidget();
+ if (transfer is null) DND.error(DWT.ERROR_NULL_ARGUMENT);
+ if ((clipboards & DND.CLIPBOARD) is 0) return null;
+ /*
+ * Bug in Windows. When a new application takes control
+ * of the clipboard, other applications may open the
+ * clipboard to determine if they want to record the
+ * clipboard updates. When this happens, the clipboard
+ * can not be accessed until the other application is
+ * finished. To allow the other applications to release
+ * the clipboard, use PeekMessage() to enable cross thread
+ * message sends.
+ */
+ IDataObject dataObject;
+ int retryCount = 0;
+ /* OleGetClipboard([out] ppDataObject).
+ * AddRef has already been called on ppDataObject by the callee and must be released by the caller.
+ */
+ int result = COM.OleGetClipboard(&dataObject);
+ while (result !is COM.S_OK && retryCount++ < 10) {
+ try {Thread.sleep(0.050);} catch (Exception t) {}
+ MSG msg;
+ OS.PeekMessage(&msg, null, 0, 0, OS.PM_NOREMOVE | OS.PM_NOYIELD);
+ result = COM.OleGetClipboard(&dataObject);
+ }
+ if (result !is COM.S_OK) return null;
+ try {
+ TransferData[] allowed = transfer.getSupportedTypes();
+ for (int i = 0; i < allowed.length; i++) {
+ if (dataObject.QueryGetData(allowed[i].formatetc) is COM.S_OK) {
+ TransferData data = allowed[i];
+ data.pIDataObject = dataObject;
+ return transfer.nativeToJava(data);
+ }
+ }
+ } finally {
+ dataObject.Release();
+ }
+ return null; // No data available for this transfer
+}
+/**
+ * Returns true
if the clipboard has been disposed,
+ * and false
otherwise.
+ * true
when the widget is disposed and false
otherwise
+ *
+ * @since 3.0
+ */
+public bool isDisposed () {
+ return (display is null);
+}
+
+/**
+ * Place data of the specified type on the system clipboard. More than one type
+ * of data can be placed on the system clipboard at the same time. Setting the
+ * data clears any previous data from the system clipboard, regardless of type.
+ *
+ *
+ *
+ * @param data the data to be set in the clipboard
+ * @param dataTypes the transfer agents that will convert the data to its
+ * platform specific format; each entry in the data array must have a
+ * corresponding dataType
+ *
+ * @exception IllegalArgumentException
+ * Clipboard clipboard = new Clipboard(display);
+ * String textData = "Hello World";
+ * String rtfData = "{\\rtf1\\b\\i Hello World}";
+ * TextTransfer textTransfer = TextTransfer.getInstance();
+ * RTFTransfer rtfTransfer = RTFTransfer.getInstance();
+ * Transfer[] transfers = new Transfer[]{textTransfer, rtfTransfer};
+ * Object[] data = new Object[]{textData, rtfData};
+ * clipboard.setContents(data, transfers);
+ * clipboard.dispose();
+ *
+ *
+ * @exception DWTException
+ *
+ * @exception DWTError
+ *
+ *
+ * DND
, or must be built by bitwise OR'ing together
+ * (that is, using the int
"|" operator) two or more
+ * of those DND
clipboard constants.
+ *
+ * @param data the data to be set in the clipboard
+ * @param dataTypes the transfer agents that will convert the data to its
+ * platform specific format; each entry in the data array must have a
+ * corresponding dataType
+ * @param clipboards on which to set the data
+ *
+ * @exception IllegalArgumentException
+ * Clipboard clipboard = new Clipboard(display);
+ * String textData = "Hello World";
+ * String rtfData = "{\\rtf1\\b\\i Hello World}";
+ * TextTransfer textTransfer = TextTransfer.getInstance();
+ * RTFTransfer rtfTransfer = RTFTransfer.getInstance();
+ * Transfer[] transfers = new Transfer[]{textTransfer, rtfTransfer};
+ * Object[] data = new Object[]{textData, rtfData};
+ * clipboard.setContents(data, transfers, DND.CLIPBOARD);
+ * clipboard.dispose();
+ *
+ *
+ * @exception DWTException
+ *
+ * @exception DWTError
+ *
+ *
+ *
+ *
+ *
+ * @see Transfer#isSupportedType
+ *
+ * @since 3.0
+ */
+public TransferData[] getAvailableTypes() {
+ return getAvailableTypes(DND.CLIPBOARD);
+}
+
+/**
+ * Returns an array of the data types currently available on the specified
+ * clipboard. Use with Transfer.isSupportedType.
+ *
+ * DND
, or must be built by bitwise OR'ing together
+ * (that is, using the int
"|" operator) two or more
+ * of those DND
clipboard constants.
+ *
+ *
+ * @see Transfer#isSupportedType
+ * @see DND#CLIPBOARD
+ * @see DND#SELECTION_CLIPBOARD
+ *
+ * @since 3.1
+ */
+public TransferData[] getAvailableTypes(int clipboards) {
+ checkWidget();
+ if ((clipboards & DND.CLIPBOARD) is 0) return null;
+ FORMATETC*[] types = _getAvailableTypes();
+ TransferData[] data = new TransferData[types.length];
+ for (int i = 0; i < types.length; i++) {
+ data[i] = new TransferData();
+ data[i].type = types[i].cfFormat;
+ data[i].formatetc = types[i];
+ }
+ return data;
+}
+
+/**
+ * Returns a platform specific list of the data types currently available on the
+ * system clipboard.
+ *
+ * getAvailableTypeNames
is a utility for writing a Transfer
+ * sub-class. It should NOT be used within an application because it provides
+ * platform specific information.
+ *
+ */
+public char[][] getAvailableTypeNames() {
+ checkWidget();
+ FORMATETC*[] types = _getAvailableTypes();
+ char[][] names = new char[][](types.length);
+ int maxSize = 128;
+ for (int i = 0; i < types.length; i++){
+ TCHAR[] buffer = NewTCHARs(0, maxSize);
+ int size = OS.GetClipboardFormatName(types[i].cfFormat, buffer.ptr, maxSize);
+ if (size !is 0) {
+ names[i] = TCHARzToStr(buffer.ptr)[0..size];
+ } else {
+ switch (types[i].cfFormat) {
+ case COM.CF_HDROP: names[i] = "CF_HDROP"; break; //$NON-NLS-1$
+ case COM.CF_TEXT: names[i] = "CF_TEXT"; break; //$NON-NLS-1$
+ case COM.CF_BITMAP: names[i] = "CF_BITMAP"; break; //$NON-NLS-1$
+ case COM.CF_METAFILEPICT: names[i] = "CF_METAFILEPICT"; break; //$NON-NLS-1$
+ case COM.CF_SYLK: names[i] = "CF_SYLK"; break; //$NON-NLS-1$
+ case COM.CF_DIF: names[i] = "CF_DIF"; break; //$NON-NLS-1$
+ case COM.CF_TIFF: names[i] = "CF_TIFF"; break; //$NON-NLS-1$
+ case COM.CF_OEMTEXT: names[i] = "CF_OEMTEXT"; break; //$NON-NLS-1$
+ case COM.CF_DIB: names[i] = "CF_DIB"; break; //$NON-NLS-1$
+ case COM.CF_PALETTE: names[i] = "CF_PALETTE"; break; //$NON-NLS-1$
+ case COM.CF_PENDATA: names[i] = "CF_PENDATA"; break; //$NON-NLS-1$
+ case COM.CF_RIFF: names[i] = "CF_RIFF"; break; //$NON-NLS-1$
+ case COM.CF_WAVE: names[i] = "CF_WAVE"; break; //$NON-NLS-1$
+ case COM.CF_UNICODETEXT: names[i] = "CF_UNICODETEXT"; break; //$NON-NLS-1$
+ case COM.CF_ENHMETAFILE: names[i] = "CF_ENHMETAFILE"; break; //$NON-NLS-1$
+ case COM.CF_LOCALE: names[i] = "CF_LOCALE"; break; //$NON-NLS-1$
+ case COM.CF_MAX: names[i] = "CF_MAX"; break; //$NON-NLS-1$
+ default: names[i] = "UNKNOWN"; //$NON-NLS-1$
+ }
+ }
+ }
+ return names;
+}
+
+private FORMATETC*[] _getAvailableTypes() {
+ FORMATETC*[] types = null;
+ IDataObject dataObject;
+ /* OleGetClipboard([out] ppDataObject).
+ * AddRef has already been called on ppDataObject by the callee and must be released by the caller.
+ */
+ if (COM.OleGetClipboard(&dataObject) !is COM.S_OK) return types;
+ IEnumFORMATETC enumFormatetc;
+ /* EnumFormatEtc([in] dwDirection, [out] ppenumFormatetc)
+ * AddRef has already been called on ppenumFormatetc by the callee and must be released by the caller.
+ */
+ int rc = dataObject.EnumFormatEtc(COM.DATADIR_GET, &enumFormatetc);
+ dataObject.Release();
+ if (rc !is COM.S_OK)return types;
+ // Loop over enumerator and save any types that match what we are looking for
+ //auto rgelt = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, FORMATETC.sizeof);
+ uint[1] pceltFetched;
+ FORMATETC rgelt;
+ enumFormatetc.Reset();
+ while (enumFormatetc.Next(1, &rgelt, pceltFetched.ptr) is COM.S_OK && pceltFetched[0] is 1) {
+ FORMATETC* formatetc = new FORMATETC();
+ COM.MoveMemory(formatetc, &rgelt, FORMATETC.sizeof);
+ FORMATETC*[] newTypes = new FORMATETC*[types.length + 1];
+ SimpleType!(FORMATETC*).arraycopy(types, 0, newTypes, 0, types.length);
+ newTypes[types.length] = formatetc;
+ types = newTypes;
+ }
+ //OS.GlobalFree(rgelt);
+ enumFormatetc.Release();
+ return types;
+}
+}
+
+private class _IDataObjectImpl : IDataObject {
+
+ Clipboard parent;
+ this(Clipboard p) { parent = p; }
+extern (Windows):
+ // interface of IUnknown
+ HRESULT QueryInterface(GUID* riid, void ** ppvObject) { return parent.QueryInterface(riid, ppvObject); }
+ ULONG AddRef() { return parent.AddRef(); }
+ ULONG Release() { return parent.Release(); }
+
+ // interface IDataObject
+ LRESULT GetData( FORMATETC *pFormatetc, STGMEDIUM *pmedium) { return parent.GetData(pFormatetc, pmedium); }
+ LRESULT GetDataHere(FORMATETC * pFormatetc, STGMEDIUM * pmedium) { return COM.E_NOTIMPL; }
+ LRESULT QueryGetData(FORMATETC* pFormatetc) { return parent.QueryGetData(pFormatetc); }
+ LRESULT GetCanonicalFormatEtc(FORMATETC* pFormatetcIn, FORMATETC* pFormatetcOut) { return COM.E_NOTIMPL; }
+ LRESULT SetData(FORMATETC* pFormatetc, STGMEDIUM * pmedium, BOOL fRelease) { return COM.E_NOTIMPL; }
+ LRESULT EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC * ppenumFormatetc) { return parent.EnumFormatEtc(dwDirection, ppenumFormatetc); }
+ LRESULT DAdvise(FORMATETC* pFormatetc, DWORD advf, IAdviseSink pAdvSink, DWORD* pdwConnection) { return COM.E_NOTIMPL; }
+ LRESULT DUnadvise(DWORD dwConnection) { return COM.E_NOTIMPL; }
+ LRESULT EnumDAdvise(IEnumSTATDATA * ppenumAdvise) { return COM.E_NOTIMPL; }
+}
+
diff -r fa7d7d66b9ed -r 242e33c0e383 dwt/dnd/DND.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/DND.d Wed Feb 13 04:51:22 2008 +0100
@@ -0,0 +1,272 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 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
+ * Port to the D programming language:
+ * Frank Benoit hresult
argument should be either 0, or the
+ * platform specific error code.
+ *
+ *
+ * This method provides the logic which maps between error codes
+ * and one of the above exceptions.
+ *
DragSource
defines the source object for a drag and drop transfer.
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ * + *A drag source is the object which originates a drag and drop operation. For the specified widget,
+ * it defines the type of data that is available for dragging and the set of operations that can
+ * be performed on that data. The operations can be any bit-wise combination of DND.MOVE, DND.COPY or
+ * DND.LINK. The type of data that can be transferred is specified by subclasses of Transfer such as
+ * TextTransfer or FileTransfer. The type of data transferred can be a predefined system type or it
+ * can be a type defined by the application. For instructions on how to define your own transfer type,
+ * refer to ByteArrayTransfer
.
You may have several DragSources in an application but you can only have one DragSource + * per Control. Data dragged from this DragSource can be dropped on a site within this application + * or it can be dropped on another application such as an external Text editor.
+ * + *The application supplies the content of the data being transferred by implementing the
+ * DragSourceListener
and associating it with the DragSource via DragSource#addDragListener.
When a successful move operation occurs, the application is required to take the appropriate + * action to remove the data from its display and remove any associated operating system resources or + * internal references. Typically in a move operation, the drop target makes a copy of the data + * and the drag source deletes the original. However, sometimes copying the data can take a long + * time (such as copying a large file). Therefore, on some platforms, the drop target may actually + * move the data in the operating system rather than make a copy. This is usually only done in + * file transfers. In this case, the drag source is informed in the DragEnd event that a + * DROP_TARGET_MOVE was performed. It is the responsibility of the drag source at this point to clean + * up its displayed information. No action needs to be taken on the operating system resources.
+ * + *The following example shows a Label widget that allows text to be dragged from it.
+ * + *
+ * // Enable a label as a Drag Source
+ * Label label = new Label(shell, DWT.NONE);
+ * // This example will allow text to be dragged
+ * Transfer[] types = new Transfer[] {TextTransfer.getInstance()};
+ * // This example will allow the text to be copied or moved to the drop target
+ * int operations = DND.DROP_MOVE | DND.DROP_COPY;
+ *
+ * DragSource source = new DragSource(label, operations);
+ * source.setTransfer(types);
+ * source.addDragListener(new DragSourceListener() {
+ * public void dragStart(DragSourceEvent e) {
+ * // Only start the drag if there is actually text in the
+ * // label - this text will be what is dropped on the target.
+ * if (label.getText().length() is 0) {
+ * event.doit = false;
+ * }
+ * };
+ * public void dragSetData(DragSourceEvent event) {
+ * // A drop has been performed, so provide the data of the
+ * // requested type.
+ * // (Checking the type of the requested data is only
+ * // necessary if the drag source supports more than
+ * // one data type but is shown here as an example).
+ * if (TextTransfer.getInstance().isSupportedType(event.dataType)){
+ * event.data = label.getText();
+ * }
+ * }
+ * public void dragFinished(DragSourceEvent event) {
+ * // A Move operation has been performed so remove the data
+ * // from the source
+ * if (event.detail is DND.DROP_MOVE)
+ * label.setText("");
+ * }
+ * });
+ *
+ *
+ *
+ * DragSource
to handle dragging from the specified Control
.
+ * Creating an instance of a DragSource may cause system resources to be allocated depending on the platform.
+ * It is therefore mandatory that the DragSource instance be disposed when no longer required.
+ *
+ * @param control the Control
that the user clicks on to initiate the drag
+ * @param style the bitwise OR'ing of allowed operations; this may be a combination of any of
+ * DND.DROP_NONE, DND.DROP_COPY, DND.DROP_MOVE, DND.DROP_LINK
+ *
+ * @exception DWTException NOTE: ERROR_CANNOT_INIT_DRAG should be an DWTException, since it is a + * recoverable error, but can not be changed due to backward compatibility.
+ * + * @see Widget#dispose + * @see DragSource#checkSubclass + * @see DND#DROP_NONE + * @see DND#DROP_COPY + * @see DND#DROP_MOVE + * @see DND#DROP_LINK + */ +public this(Control control, int style) { + super(control, checkStyle(style)); + this.control = control; + if (control.getData(DRAGSOURCEID) !is null) { + DND.error(DND.ERROR_CANNOT_INIT_DRAG); + } + control.setData(DRAGSOURCEID, this); + createCOMInterfaces(); + this.AddRef(); + + controlListener = new Listener() { + public void handleEvent(Event event) { + if (event.type is DWT.Dispose) { + if (!DragSource.this.isDisposed()) { + DragSource.this.dispose(); + } + } + if (event.type is DWT.DragDetect) { + if (!DragSource.this.isDisposed()) { + DragSource.this.drag(event); + } + } + } + }; + control.addListener(DWT.Dispose, controlListener); + control.addListener(DWT.DragDetect, controlListener); + + this.addListener(DWT.Dispose, new Listener() { + public void handleEvent(Event e) { + DragSource.this.onDispose(); + } + }); + + Object effect = control.getData(DEFAULT_DRAG_SOURCE_EFFECT); + if (effect instanceof DragSourceEffect) { + dragEffect = (DragSourceEffect) effect; + } else if (control instanceof Tree) { + dragEffect = new TreeDragSourceEffect((Tree) control); + } else if (control instanceof Table) { + dragEffect = new TableDragSourceEffect((Table) control); + } +} + +static int checkStyle(int style) { + if (style is DWT.NONE) return DND.DROP_MOVE; + return style; +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when a drag and drop operation is in progress, by sending + * it one of the messages defined in theDragSourceListener
+ * interface.
+ *
+ * dragStart
is called when the user has begun the actions required to drag the widget.
+ * This event gives the application the chance to decide if a drag should be started.
+ * dragSetData
is called when the data is required from the drag source.
+ * dragFinished
is called when the drop has successfully completed (mouse up
+ * over a valid target) or has been terminated (such as hitting the ESC key). Perform cleanup
+ * such as removing data from the source side on a successful move operation.
+ * DragSourceListener
interface.
+ *
+ * Classes that wish to deal with DragSourceEvent
s can
+ * extend this class and override only the methods which they are
+ * interested in.
dragStart
permits the drag operation to start.
+ * For additional information see DragSourceListener.dragStart
.
+ */
+ public void dragStart(DragSourceEvent event){}
+ /**
+ * This implementation of dragFinished
does nothing.
+ * For additional information see DragSourceListener.dragFinished
.
+ */
+ public void dragFinished(DragSourceEvent event){}
+ /**
+ * This implementation of dragSetData
does nothing.
+ * For additional information see DragSourceListener.dragSetData
.
+ */
+ public void dragSetData(DragSourceEvent event){}
+}
diff -r fa7d7d66b9ed -r 242e33c0e383 dwt/dnd/DragSourceEffect.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/DragSourceEffect.d Wed Feb 13 04:51:22 2008 +0100
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2007 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
+ * Port to the D programming language:
+ * Frank Benoit The drag source effect has the same API as the
+ * DragSourceAdapter
so that it can provide custom visual
+ * feedback when a DragSourceEvent
occurs.
+ *
Classes that wish to provide their own drag source effect such as
+ * displaying a default source image during a drag can extend the DragSourceEffect
+ * class, override the DragSourceAdapter.dragStart
method and set
+ * the field DragSourceEvent.image
with their own image.
+ * The image should be disposed when DragSourceAdapter.dragFinished
is called.
+ *
DragSourceEffect
to handle drag effect from the specified Control
.
+ *
+ * @param control the Control
that the user clicks on to initiate the drag
+ *
+ * @exception IllegalArgumentException Flag to determine if the drag and drop operation should proceed. + * The application can set this value to false to prevent the drag from starting. + * Set to true by default.
+ * + *In dragFinished:
+ *Flag to indicate if the operation was performed successfully. + * True if the operation was performed successfully.
+ */ + public bool doit; + + /** + * In dragStart, the x coordinate (relative to the control) of the + * position the mouse went down to start the drag. + * @since 3.2 + */ + public int x; + /** + * In dragStart, the y coordinate (relative to the control) of the + * position the mouse went down to start the drag . + * @since 3.2 + */ + public int y; + + /** + * The type of data requested. + * Data provided in the data field must be of the same type. + */ + public TransferData dataType; + + /** + * The drag source image to be displayed during the drag. + *A value of null indicates that no drag image will be displayed.
+ *The default value is null.
+ * + * @since 3.3 + */ + public Image image; + + static const long serialVersionUID = 3257002142513770808L; + +/** + * Constructs a new instance of this class based on the + * information in the given untyped event. + * + * @param e the untyped event containing the information + */ +public this(DNDEvent e) { + super( cast(Event) e ); + this.data = e.data; + this.detail = e.detail; + this.doit = e.doit; + this.dataType = e.dataType; + this.x = e.x; + this.y = e.y; + this.image = e.image; +} +void updateEvent(DNDEvent e) { + e.widget = this.widget; + e.time = this.time; + e.data = this.data; + e.detail = this.detail; + e.doit = this.doit; + e.dataType = this.dataType; + e.x = this.x; + e.y = this.y; + e.image = this.image; +} +} diff -r fa7d7d66b9ed -r 242e33c0e383 dwt/dnd/DragSourceListener.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/dnd/DragSourceListener.d Wed Feb 13 04:51:22 2008 +0100 @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 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 + * Port to the D programming language: + * Frank BenoitDragSourceListener
class provides event notification to the application for DragSource events.
+ *
+ * When the user drops data on a DropTarget
, the application which defines the DragSource
+ * must provide the dropped data by implementing dragSetData
. In the dragSetData, the application
+ * must support all the data types that were specified in the DragSource#setTransfer method.
After the drop has completed successfully or has been aborted, the application which defines the
+ * DragSource
is required to take the appropriate cleanup action. In the case of a successful
+ * move operation, the application must remove the data that was transferred.
The following fields in the DragSourceEvent apply: + *
The following fields in the DragSourceEvent apply: + *
The following fields in the DragSourceEvent apply: + *
DropTarget
defines the target object for a drag and drop transfer.
+ *
+ * IMPORTANT: This class is not intended to be subclassed.
+ *
+ * This class identifies the Control
over which the user must position the cursor
+ * in order to drop the data being transferred. It also specifies what data types can be dropped on
+ * this control and what operations can be performed. You may have several DropTragets in an
+ * application but there can only be a one to one mapping between a Control
and a DropTarget
.
+ * The DropTarget can receive data from within the same application or from other applications
+ * (such as text dragged from a text editor like Word).
+ * int operations = DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK;
+ * Transfer[] types = new Transfer[] {TextTransfer.getInstance()};
+ * DropTarget target = new DropTarget(label, operations);
+ * target.setTransfer(types);
+ *
+ *
+ * The application is notified of data being dragged over this control and of when a drop occurs by
+ * implementing the interface DropTargetListener
which uses the class
+ * DropTargetEvent
. The application can modify the type of drag being performed
+ * on this Control at any stage of the drag by modifying the event.detail
field or the
+ * event.currentDataType
field. When the data is dropped, it is the responsibility of
+ * the application to copy this data for its own purposes.
+ *
+ *
+ *
+ *
+ * target.addDropListener (new DropTargetListener() {
+ * public void dragEnter(DropTargetEvent event) {};
+ * public void dragOver(DropTargetEvent event) {};
+ * public void dragLeave(DropTargetEvent event) {};
+ * public void dragOperationChanged(DropTargetEvent event) {};
+ * public void dropAccept(DropTargetEvent event) {}
+ * public void drop(DropTargetEvent event) {
+ * // A drop has occurred, copy over the data
+ * if (event.data is null) { // no data to copy, indicate failure in event.detail
+ * event.detail = DND.DROP_NONE;
+ * return;
+ * }
+ * label.setText ((String) event.data); // data copied to label text
+ * }
+ * });
+ *
DropTarget
to allow data to be dropped on the specified
+ * Control
.
+ * Creating an instance of a DropTarget may cause system resources to be allocated
+ * depending on the platform. It is therefore mandatory that the DropTarget instance
+ * be disposed when no longer required.
+ *
+ * @param control the Control
over which the user positions the cursor to drop the data
+ * @param style the bitwise OR'ing of allowed operations; this may be a combination of any of
+ * DND.DROP_NONE, DND.DROP_COPY, DND.DROP_MOVE, DND.DROP_LINK
+ *
+ * @exception DWTException NOTE: ERROR_CANNOT_INIT_DROP should be an DWTException, since it is a + * recoverable error, but can not be changed due to backward compatibility.
+ * + * @see Widget#dispose + * @see DropTarget#checkSubclass + * @see DND#DROP_NONE + * @see DND#DROP_COPY + * @see DND#DROP_MOVE + * @see DND#DROP_LINK + */ +public this(Control control, int style) { + super (control, checkStyle(style)); + this.control = control; + if (control.getData(DROPTARGETID) !is null) { + DND.error(DND.ERROR_CANNOT_INIT_DROP); + } + control.setData(DROPTARGETID, this); + createCOMInterfaces(); + this.AddRef(); + + if (COM.CoLockObjectExternal(iDropTarget.getAddress(), true, true) !is COM.S_OK) + DND.error(DND.ERROR_CANNOT_INIT_DROP); + if (COM.RegisterDragDrop( control.handle, iDropTarget.getAddress()) !is COM.S_OK) + DND.error(DND.ERROR_CANNOT_INIT_DROP); + + controlListener = new Listener () { + public void handleEvent (Event event) { + if (!DropTarget.this.isDisposed()){ + DropTarget.this.dispose(); + } + } + }; + control.addListener (DWT.Dispose, controlListener); + + this.addListener(DWT.Dispose, new Listener () { + public void handleEvent (Event event) { + onDispose(); + } + }); + + Object effect = control.getData(DEFAULT_DROP_TARGET_EFFECT); + if (effect instanceof DropTargetEffect) { + dropEffect = (DropTargetEffect) effect; + } else if (control instanceof Table) { + dropEffect = new TableDropTargetEffect((Table) control); + } else if (control instanceof Tree) { + dropEffect = new TreeDropTargetEffect((Tree) control); + } +} + +static int checkStyle (int style) { + if (style is DWT.NONE) return DND.DROP_MOVE; + return style; +} + +/** + * Adds the listener to the collection of listeners who will + * be notified when a drag and drop operation is in progress, by sending + * it one of the messages defined in theDropTargetListener
+ * interface.
+ *
+ * dragEnter
is called when the cursor has entered the drop target boundaries
+ * dragLeave
is called when the cursor has left the drop target boundaries and just before
+ * the drop occurs or is cancelled.
+ * dragOperationChanged
is called when the operation being performed has changed
+ * (usually due to the user changing the selected modifier key(s) while dragging)
+ * dragOver
is called when the cursor is moving over the drop target
+ * dropAccept
is called just before the drop is performed. The drop target is given
+ * the chance to change the nature of the drop or veto the drop by setting the event.detail
field
+ * drop
is called when the data is being dropped
+ * DropTargetListener
interface.
+ *
+ * Classes that wish to deal with DropTargetEvent
s can
+ * extend this class and override only the methods which they are
+ * interested in.
+ *
dragEnter
permits the default
+ * operation defined in event.detail
to be performed on the current data type
+ * defined in event.currentDataType
.
+ * For additional information see DropTargetListener.dragEnter
.
+ */
+public void dragEnter(DropTargetEvent event){}
+/**
+ * This implementation of dragLeave
does nothing.
+ * For additional information see DropTargetListener.dragOperationChanged
.
+ */
+public void dragLeave(DropTargetEvent event){}
+/**
+ * This implementation of dragOperationChanged
permits the default
+ * operation defined in event.detail
to be performed on the current data type
+ * defined in event.currentDataType
.
+ * For additional information see DropTargetListener.dragOperationChanged
.
+ */
+public void dragOperationChanged(DropTargetEvent event){}
+/**
+ * This implementation of dragOver
permits the default
+ * operation defined in event.detail
to be performed on the current data type
+ * defined in event.currentDataType
.
+ * For additional information see DropTargetListener.dragOver
.
+ */
+public void dragOver(DropTargetEvent event){}
+/**
+ * This implementation of drop
does nothing.
+ * For additional information see DropTargetListener.drop
.
+ */
+public void drop(DropTargetEvent event){}
+/**
+ * This implementation of dropAccept
permits the default
+ * operation defined in event.detail
to be performed on the current data type
+ * defined in event.currentDataType
.
+ * For additional information see DropTargetListener.dropAccept
.
+ */
+public void dropAccept(DropTargetEvent event){}
+
+}
diff -r fa7d7d66b9ed -r 242e33c0e383 dwt/dnd/DropTargetEffect.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/DropTargetEffect.d Wed Feb 13 04:51:22 2008 +0100
@@ -0,0 +1,178 @@
+/*******************************************************************************
+ * Copyright (c) 2007 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
+ * Port to the D programming language:
+ * Frank Benoit The drop target effect has the same API as the
+ * DropTargetAdapter
so that it can provide custom visual
+ * feedback when a DropTargetEvent
occurs.
+ *
Classes that wish to provide their own drag under effect
+ * can extend the DropTargetEffect
and override any applicable methods
+ * in DropTargetAdapter
to display their own drag under effect.
The feedback value is either one of the FEEDBACK constants defined in
+ * class DND
which is applicable to instances of this class,
+ * or it must be built by bitwise OR'ing together
+ * (that is, using the int
"|" operator) two or more
+ * of those DND
effect constants.
+ *
+ *
DropTargetEffect
to handle the drag under effect on the specified
+ * Control
.
+ *
+ * @param control the Control
over which the user positions the cursor to drop the data
+ *
+ * @exception IllegalArgumentException Display
+ */
+ public int x;
+
+ /**
+ * The y-cordinate of the cursor relative to the Display
+ */
+ public int y;
+
+ /**
+ * The operation being performed.
+ * @see DND#DROP_NONE
+ * @see DND#DROP_MOVE
+ * @see DND#DROP_COPY
+ * @see DND#DROP_LINK
+ */
+ public int detail;
+
+ /**
+ * A bitwise OR'ing of the operations that the DragSource can support
+ * (e.g. DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK).
+ * The detail value must be a member of this list or DND.DROP_NONE.
+ * @see DND#DROP_NONE
+ * @see DND#DROP_MOVE
+ * @see DND#DROP_COPY
+ * @see DND#DROP_LINK
+ */
+ public int operations;
+
+ /**
+ * A bitwise OR'ing of the drag under effect feedback to be displayed to the user
+ * (e.g. DND.FEEDBACK_SELECT | DND.FEEDBACK_SCROLL | DND.FEEDBACK_EXPAND).
+ * A value of DND.FEEDBACK_NONE indicates that no drag under effect will be displayed.
+ *Feedback effects will only be applied if they are applicable.
+ *The default value is DND.FEEDBACK_SELECT.
+ * @see DND#FEEDBACK_NONE + * @see DND#FEEDBACK_SELECT + * @see DND#FEEDBACK_INSERT_BEFORE + * @see DND#FEEDBACK_INSERT_AFTER + * @see DND#FEEDBACK_SCROLL + * @see DND#FEEDBACK_EXPAND + */ + public int feedback; + + /** + * If the associated control is a table or tree, this field contains the item located + * at the cursor coordinates. + */ + public Widget item; + + /** + * The type of data that will be dropped. + */ + public TransferData currentDataType; + + /** + * A list of the types of data that the DragSource is capable of providing. + * The currentDataType must be a member of this list. + */ + public TransferData[] dataTypes; + + static const long serialVersionUID = 3256727264573338678L; + +/** + * Constructs a new instance of this class based on the + * information in the given untyped event. + * + * @param e the untyped event containing the information + */ +public this(DNDEvent e) { + super(cast(Event)e); + this.data = e.data; + this.x = e.x; + this.y = e.y; + this.detail = e.detail; + this.currentDataType = e.dataType; + this.dataTypes = e.dataTypes; + this.operations = e.operations; + this.feedback = e.feedback; + this.item = e.item; +} +void updateEvent(DNDEvent e) { + e.widget = this.widget; + e.time = this.time; + e.data = this.data; + e.x = this.x; + e.y = this.y; + e.detail = this.detail; + e.dataType = this.currentDataType; + e.dataTypes = this.dataTypes; + e.operations = this.operations; + e.feedback = this.feedback; + e.item = this.item; +} +} diff -r fa7d7d66b9ed -r 242e33c0e383 dwt/dnd/DropTargetListener.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/dnd/DropTargetListener.d Wed Feb 13 04:51:22 2008 +0100 @@ -0,0 +1,253 @@ +/******************************************************************************* + * Copyright (c) 2000, 2003 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 + * Port to the D programming language: + * Frank BenoitDropTargetListener
class provides event notification to the application
+ * for DropTarget events.
+ *
+ * As the user moves the cursor into, over and out of a Control that has been designated + * as a DropTarget, events indicate what operation can be performed and what data can be + * transferred if a drop where to occur at that point. + * The application can respond to these events and change the type of data that will + * be dropped by modifying event.currentDataType, or change the operation that will be performed + * by modifying the event.detail field or stop any drop from happening on the current target + * by setting the event.detail field to DND_DROP_NONE.
+ * + *When the user causes a drop to happen by releasing the mouse over a valid drop target, + * the application has one last chance to change the data type of the drop through the + * DropAccept event. If the drop is still allowed, the DropAccept event is immediately + * followed by the Drop event. In the Drop event, the application can still change the + * operation that is performed but the data type is fixed.
+ * + * @see DropTargetEvent + * + */ +public interface DropTargetListener : DWTEventListener { + +/** + * The cursor has entered the drop target boundaries. + * + *The following fields in the DropTargetEvent apply: + *
The operation
value is determined by the modifier keys pressed by the user.
+ * If no keys are pressed the event.detail
field is set to DND.DROP_DEFAULT.
+ * If the application does not set the event.detail
to something other
+ * than DND.DROP_DEFAULT
the operation will be set to the platform defined standard
+ * default.
The currentDataType
is determined by the first transfer agent specified in
+ * setTransfer() that matches a data type provided by the drag source.
It is possible to get a DragEnter event when the drag source does not provide any matching data. + * In this case, the default operation is DND.DROP_NONE and the currentDataType is null.
+ * + *The application can change the operation that will be performed by modifying the
+ * detail
field but the choice must be one of the values in the operations
+ * field or DND.DROP_NONE.
The application can also change the type of data being requested by
+ * modifying the currentDataTypes
field but the value must be one of the values
+ * in the dataTypes
list.
The following fields in the DropTargetEvent apply: + *
The following fields in the DropTargetEvent apply: + *
The operation
value is determined by the modifier keys pressed by the user.
+ * If no keys are pressed the event.detail
field is set to DND.DROP_DEFAULT.
+ * If the application does not set the event.detail
to something other than
+ * DND.DROP_DEFAULT
the operation will be set to the platform defined standard default.
The currentDataType
value is determined by the value assigned to
+ * currentDataType
in previous dragEnter and dragOver calls.
The application can change the operation that will be performed by modifying the
+ * detail
field but the choice must be one of the values in the operations
+ * field.
The application can also change the type of data being requested by modifying
+ * the currentDataTypes
field but the value must be one of the values in the
+ * dataTypes
list.
The following fields in the DropTargetEvent apply: + *
The operation
value is determined by the value assigned to
+ * currentDataType
in previous dragEnter and dragOver calls.
The currentDataType
value is determined by the value assigned to
+ * currentDataType
in previous dragEnter and dragOver calls.
The application can change the operation that will be performed by modifying the
+ * detail
field but the choice must be one of the values in the operations
+ * field.
The application can also change the type of data being requested by modifying the
+ * currentDataTypes
field but the value must be one of the values in the
+ * dataTypes
list.
NOTE: At this point the data
field is null. On some platforms, it is possible
+ * to obtain the data being transferred before the transfer occurs but in most platforms this is
+ * not possible. On those platforms where the data is available, the application can access the
+ * data as follows:
+ * public void dragOver(DropTargetEvent event) {
+ * TextTransfer textTransfer = TextTransfer.getInstance();
+ * String data = (String)textTransfer.nativeToJava(event.currentDataType);
+ * if (data !is null) {
+ * System.out.println("Data to be dropped is (Text)"+data);
+ * }
+ * };
+ *
+ *
+ * @param event the information associated with the drag over event
+ *
+ * @see DropTargetEvent
+ */
+public void dragOver(DropTargetEvent event);
+
+/**
+ * The data is being dropped. The data field contains java format of the data being dropped.
+ * To determine the type of the data object, refer to the documentation for the Transfer subclass
+ * specified in event.currentDataType.
+ *
+ * The following fields in DropTargetEvent apply: + *
The application can refuse to perform the drop operation by setting the detail + * field to DND.DROP_NONE.
+ * + * @param event the information associated with the drop event + * + * @see DropTargetEvent + */ +public void drop(DropTargetEvent event); + +/** + * The drop is about to be performed. + * The drop target is given a last chance to change the nature of the drop. + * + *The following fields in the DropTargetEvent apply: + *
The application can veto the drop by setting the event.detail
field to
+ * DND.DROP_NONE
.
The application can change the operation that will be performed by modifying the
+ * detail
field but the choice must be one of the values in the
+ * operations
field.
The application can also change the type of data being requested by modifying the
+ * currentDataTypes
field but the value must be one of the values in the <
+ * code>dataTypes list.
FileTransfer
provides a platform specific mechanism
+ * for converting a list of files represented as a java String[]
to a
+ * platform specific representation of the data and vice versa.
+ * Each String
in the array contains the absolute path for a single
+ * file or directory.
+ * See Transfer
for additional information.
+ *
+ * An example of a java String[]
containing a list of files is shown
+ * below:
+ * File file1 = new File("C:\temp\file1");
+ * File file2 = new File("C:\temp\file2");
+ * String[] fileData = new String[2];
+ * fileData[0] = file1.getAbsolutePath();
+ * fileData[1] = file2.getAbsolutePath();
+ *
+ */
+public class FileTransfer : ByteArrayTransfer {
+
+ private static FileTransfer _instance = new FileTransfer();
+ private static final String CF_HDROP = "CF_HDROP "; //$NON-NLS-1$
+ private static final int CF_HDROPID = COM.CF_HDROP;
+ private static final String CF_HDROP_SEPARATOR = "\0"; //$NON-NLS-1$
+
+private this() {}
+
+/**
+ * Returns the singleton instance of the FileTransfer class.
+ *
+ * @return the singleton instance of the FileTransfer class
+ */
+public static FileTransfer getInstance () {
+ return _instance;
+}
+
+/**
+ * This implementation of javaToNative
converts a list of file names
+ * represented by a java String[]
to a platform specific representation.
+ * Each String
in the array contains the absolute path for a single
+ * file or directory. For additional information see
+ * Transfer#javaToNative
.
+ *
+ * @param object a java String[]
containing the file names to be
+ * converted
+ * @param transferData an empty TransferData
object; this
+ * object will be filled in on return with the platform specific format of the data
+ */
+public void javaToNative(Object object, TransferData transferData) {
+ if (!checkFile(object) || !isSupportedType(transferData)) {
+ DND.error(DND.ERROR_INVALID_DATA);
+ }
+ String[] fileNames = (String[]) object;
+ StringBuffer allFiles = new StringBuffer();
+ for (int i = 0; i < fileNames.length; i++) {
+ allFiles.append(fileNames[i]);
+ allFiles.append(CF_HDROP_SEPARATOR); // each name is null terminated
+ }
+ TCHAR buffer = new TCHAR(0, allFiles.toString(), true); // there is an extra null terminator at the very end
+ DROPFILES dropfiles = new DROPFILES();
+ dropfiles.pFiles = DROPFILES.sizeof;
+ dropfiles.pt_x = dropfiles.pt_y = 0;
+ dropfiles.fNC = 0;
+ dropfiles.fWide = OS.IsUnicode ? 1 : 0;
+ // Allocate the memory because the caller (DropTarget) has not handed it in
+ // The caller of this method must release the data when it is done with it.
+ int byteCount = buffer.length() * TCHAR.sizeof;
+ int newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, DROPFILES.sizeof + byteCount);
+ OS.MoveMemory(newPtr, dropfiles, DROPFILES.sizeof);
+ OS.MoveMemory(newPtr + DROPFILES.sizeof, buffer, byteCount);
+ transferData.stgmedium = new STGMEDIUM();
+ transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
+ transferData.stgmedium.unionField = newPtr;
+ transferData.stgmedium.pUnkForRelease = 0;
+ transferData.result = COM.S_OK;
+}
+
+/**
+ * This implementation of nativeToJava
converts a platform specific
+ * representation of a list of file names to a java String[]
.
+ * Each String in the array contains the absolute path for a single file or directory.
+ * For additional information see Transfer#nativeToJava
.
+ *
+ * @param transferData the platform specific representation of the data to be
+ * been converted
+ * @return a java String[]
containing a list of file names if the
+ * conversion was successful; otherwise null
+ */
+public Object nativeToJava(TransferData transferData) {
+ if (!isSupportedType(transferData) || transferData.pIDataObject is 0) return null;
+
+ // get file names from IDataObject
+ IDataObject dataObject = new IDataObject(transferData.pIDataObject);
+ dataObject.AddRef();
+ FORMATETC formatetc = new FORMATETC();
+ formatetc.cfFormat = COM.CF_HDROP;
+ formatetc.ptd = 0;
+ formatetc.dwAspect = COM.DVASPECT_CONTENT;
+ formatetc.lindex = -1;
+ formatetc.tymed = COM.TYMED_HGLOBAL;
+ STGMEDIUM stgmedium = new STGMEDIUM();
+ stgmedium.tymed = COM.TYMED_HGLOBAL;
+ transferData.result = dataObject.GetData(formatetc, stgmedium);
+ dataObject.Release();
+ if (transferData.result !is COM.S_OK) return null;
+ // How many files are there?
+ int count = OS.DragQueryFile(stgmedium.unionField, 0xFFFFFFFF, null, 0);
+ String[] fileNames = new String[count];
+ for (int i = 0; i < count; i++) {
+ // How long is the name ?
+ int size = OS.DragQueryFile(stgmedium.unionField, i, null, 0) + 1;
+ TCHAR lpszFile = new TCHAR(0, size);
+ // Get file name and append it to string
+ OS.DragQueryFile(stgmedium.unionField, i, lpszFile, size);
+ fileNames[i] = lpszFile.toString(0, lpszFile.strlen());
+ }
+ OS.DragFinish(stgmedium.unionField); // frees data associated with HDROP data
+ return fileNames;
+}
+
+protected int[] getTypeIds(){
+ return new int[] {CF_HDROPID};
+}
+
+protected String[] getTypeNames(){
+ return new String[] {CF_HDROP};
+}
+bool checkFile(Object object) {
+ if (object is null || !(object instanceof String[]) || ((String[])object).length is 0) return false;
+ String[] strings = (String[])object;
+ for (int i = 0; i < strings.length; i++) {
+ if (strings[i] is null || strings[i].length() is 0) return false;
+ }
+ return true;
+}
+
+protected bool validate(Object object) {
+ return checkFile(object);
+}
+}
diff -r fa7d7d66b9ed -r 242e33c0e383 dwt/dnd/HTMLTransfer.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/HTMLTransfer.d Wed Feb 13 04:51:22 2008 +0100
@@ -0,0 +1,210 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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
+ * Port to the D programming language:
+ * Frank Benoit HTMLTransfer
provides a platform specific mechanism
+ * for converting text in HTML format represented as a java String
+ * to a platform specific representation of the data and vice versa. See
+ * Transfer
for additional information.
+ *
+ * An example of a java String
containing HTML text is shown
+ * below:
+ * String htmlData = "This is a paragraph of text.
";
+ *
+ */
+public class HTMLTransfer : ByteArrayTransfer {
+
+ static HTMLTransfer _instance = new HTMLTransfer();
+ static final String HTML_FORMAT = "HTML Format"; //$NON-NLS-1$
+ static final int HTML_FORMATID = registerType(HTML_FORMAT);
+ static final String NUMBER = "00000000"; //$NON-NLS-1$
+ static final String HEADER = "Version:0.9\r\nStartHTML:"+NUMBER+"\r\nEndHTML:"+NUMBER+"\r\nStartFragment:"+NUMBER+"\r\nEndFragment:"+NUMBER+"\r\n";
+ static final String PREFIX = ""; //$NON-NLS-1$
+ static final String SUFFIX = ""; //$NON-NLS-1$
+ static final String StartFragment = "StartFragment:"; //$NON-NLS-1$
+ static final String EndFragment = "EndFragment:"; //$NON-NLS-1$
+
+private this() {}
+
+/**
+ * Returns the singleton instance of the HTMLTransfer class.
+ *
+ * @return the singleton instance of the HTMLTransfer class
+ */
+public static HTMLTransfer getInstance () {
+ return _instance;
+}
+
+/**
+ * This implementation of javaToNative
converts HTML-formatted text
+ * represented by a java String
to a platform specific representation.
+ * For additional information see Transfer#javaToNative
.
+ *
+ * @param object a java String
containing HTML text
+ * @param transferData an empty TransferData
object; this
+ * object will be filled in on return with the platform specific format of the data
+ */
+public void javaToNative (Object object, TransferData transferData){
+ if (!checkHTML(object) || !isSupportedType(transferData)) {
+ DND.error(DND.ERROR_INVALID_DATA);
+ }
+ String string = (String)object;
+ int count = string.length();
+ char[] chars = new char[count + 1];
+ string.getChars(0, count, chars, 0);
+ int codePage = OS.GetACP();
+ int cchMultiByte = OS.WideCharToMultiByte(codePage, 0, chars, -1, null, 0, null, null);
+ if (cchMultiByte is 0) {
+ transferData.stgmedium = new STGMEDIUM();
+ transferData.result = COM.DV_E_STGMEDIUM;
+ return;
+ }
+ int startHTML = HEADER.length();
+ int startFragment = startHTML + PREFIX.length();
+ int endFragment = startFragment + cchMultiByte - 1;
+ int endHTML = endFragment + SUFFIX.length();
+
+ StringBuffer buffer = new StringBuffer(HEADER);
+ int maxLength = NUMBER.length();
+ //startHTML
+ int start = buffer.toString().indexOf(NUMBER);
+ String temp = Integer.toString(startHTML);
+ buffer.replace(start + maxLength-temp.length(), start + maxLength, temp);
+ //endHTML
+ start = buffer.toString().indexOf(NUMBER, start);
+ temp = Integer.toString(endHTML);
+ buffer.replace(start + maxLength-temp.length(), start + maxLength, temp);
+ //startFragment
+ start = buffer.toString().indexOf(NUMBER, start);
+ temp = Integer.toString(startFragment);
+ buffer.replace(start + maxLength-temp.length(), start + maxLength, temp);
+ //endFragment
+ start = buffer.toString().indexOf(NUMBER, start);
+ temp = Integer.toString(endFragment);
+ buffer.replace(start + maxLength-temp.length(), start + maxLength, temp);
+
+ buffer.append(PREFIX);
+ buffer.append(string);
+ buffer.append(SUFFIX);
+
+ count = buffer.length();
+ chars = new char[count + 1];
+ buffer.getChars(0, count, chars, 0);
+ cchMultiByte = OS.WideCharToMultiByte(codePage, 0, chars, -1, null, 0, null, null);
+ int lpMultiByteStr = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, cchMultiByte);
+ OS.WideCharToMultiByte(codePage, 0, chars, -1, lpMultiByteStr, cchMultiByte, null, null);
+ transferData.stgmedium = new STGMEDIUM();
+ transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
+ transferData.stgmedium.unionField = lpMultiByteStr;
+ transferData.stgmedium.pUnkForRelease = 0;
+ transferData.result = COM.S_OK;
+ return;
+}
+
+/**
+ * This implementation of nativeToJava
converts a platform specific
+ * representation of HTML text to a java String
.
+ * For additional information see Transfer#nativeToJava
.
+ *
+ * @param transferData the platform specific representation of the data to be
+ * been converted
+ * @return a java String
containing HTML text if the
+ * conversion was successful; otherwise null
+ */
+public Object nativeToJava(TransferData transferData){
+ if (!isSupportedType(transferData) || transferData.pIDataObject is 0) return null;
+ IDataObject data = new IDataObject(transferData.pIDataObject);
+ data.AddRef();
+ STGMEDIUM stgmedium = new STGMEDIUM();
+ FORMATETC formatetc = transferData.formatetc;
+ stgmedium.tymed = COM.TYMED_HGLOBAL;
+ transferData.result = data.GetData(formatetc, stgmedium);
+ data.Release();
+ if (transferData.result !is COM.S_OK) return null;
+ int hMem = stgmedium.unionField;
+
+ try {
+ int lpMultiByteStr = OS.GlobalLock(hMem);
+ if (lpMultiByteStr is 0) return null;
+ try {
+ int codePage = OS.GetACP();
+ int cchWideChar = OS.MultiByteToWideChar (codePage, OS.MB_PRECOMPOSED, lpMultiByteStr, -1, null, 0);
+ if (cchWideChar is 0) return null;
+ char[] lpWideCharStr = new char [cchWideChar - 1];
+ OS.MultiByteToWideChar (codePage, OS.MB_PRECOMPOSED, lpMultiByteStr, -1, lpWideCharStr, lpWideCharStr.length);
+ String string = new String(lpWideCharStr);
+ int fragmentStart = 0, fragmentEnd = 0;
+ int start = string.indexOf(StartFragment) + StartFragment.length();
+ int end = start + 1;
+ while (end < string.length()) {
+ String s = string.substring(start, end);
+ try {
+ fragmentStart = Integer.parseInt(s);
+ end++;
+ } catch (NumberFormatException e) {
+ break;
+ }
+ }
+ start = string.indexOf(EndFragment) + EndFragment.length();
+ end = start + 1;
+ while (end < string.length()) {
+ String s = string.substring(start, end);
+ try {
+ fragmentEnd = Integer.parseInt(s);
+ end++;
+ } catch (NumberFormatException e) {
+ break;
+ }
+ }
+ if (fragmentEnd <= fragmentStart || fragmentEnd > lpWideCharStr.length) return null;
+ /* TO DO:
+ * FragmentStart and FragmentEnd are offsets in original byte stream, not
+ * the wide char version of the byte stream.
+ */
+ String s = string.substring(fragmentStart, fragmentEnd);
+ /*
+ * Firefox includes in the fragment, so remove it.
+ */
+ String foxStart = "\r\n"; //$NON-NLS-1$
+ int prefix = s.indexOf(foxStart);
+ if (prefix !is -1) {
+ prefix += foxStart.length();
+ s = s.substring(prefix);
+ }
+ return s;
+ } finally {
+ OS.GlobalUnlock(hMem);
+ }
+ } finally {
+ OS.GlobalFree(hMem);
+ }
+}
+protected int[] getTypeIds(){
+ return new int[] {HTML_FORMATID};
+}
+protected String[] getTypeNames(){
+ return new String[] {HTML_FORMAT};
+}
+bool checkHTML(Object object) {
+ return (object !is null && object instanceof String && ((String)object).length() > 0);
+}
+protected bool validate(Object object) {
+ return checkHTML(object);
+}
+}
diff -r fa7d7d66b9ed -r 242e33c0e383 dwt/dnd/OleEnumFORMATETC.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/OleEnumFORMATETC.d Wed Feb 13 04:51:22 2008 +0100
@@ -0,0 +1,163 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2003 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
+ * Port to the D programming language:
+ * Frank Benoit RTFTransfer
provides a platform specific mechanism
+ * for converting text in RTF format represented as a java String
+ * to a platform specific representation of the data and vice versa. See
+ * Transfer
for additional information.
+ *
+ * An example of a java String
containing RTF text is shown
+ * below:
+ * String rtfData = "{\\rtf1{\\colortbl;\\red255\\green0\\blue0;}\\uc1\\b\\i Hello World}";
+ *
+ */
+public class RTFTransfer : ByteArrayTransfer {
+
+ private static RTFTransfer _instance = new RTFTransfer();
+ private static final String CF_RTF = "Rich Text Format"; //$NON-NLS-1$
+ private static final int CF_RTFID = registerType(CF_RTF);
+
+private this() {}
+
+/**
+ * Returns the singleton instance of the RTFTransfer class.
+ *
+ * @return the singleton instance of the RTFTransfer class
+ */
+public static RTFTransfer getInstance () {
+ return _instance;
+}
+
+/**
+ * This implementation of javaToNative
converts RTF-formatted text
+ * represented by a java String
to a platform specific representation.
+ * For additional information see Transfer#javaToNative
.
+ *
+ * @param object a java String
containing RTF text
+ * @param transferData an empty TransferData
object; this
+ * object will be filled in on return with the platform specific format of the data
+ */
+public void javaToNative (Object object, TransferData transferData){
+ if (!checkRTF(object) || !isSupportedType(transferData)) {
+ DND.error(DND.ERROR_INVALID_DATA);
+ }
+ // CF_RTF is stored as a null terminated byte array
+ String string = (String)object;
+ int count = string.length();
+ char[] chars = new char[count + 1];
+ string.getChars(0, count, chars, 0);
+ int codePage = OS.GetACP();
+ int cchMultiByte = OS.WideCharToMultiByte(codePage, 0, chars, -1, null, 0, null, null);
+ if (cchMultiByte is 0) {
+ transferData.stgmedium = new STGMEDIUM();
+ transferData.result = COM.DV_E_STGMEDIUM;
+ return;
+ }
+ int lpMultiByteStr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, cchMultiByte);
+ OS.WideCharToMultiByte(codePage, 0, chars, -1, lpMultiByteStr, cchMultiByte, null, null);
+ transferData.stgmedium = new STGMEDIUM();
+ transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
+ transferData.stgmedium.unionField = lpMultiByteStr;
+ transferData.stgmedium.pUnkForRelease = 0;
+ transferData.result = COM.S_OK;
+ return;
+}
+
+/**
+ * This implementation of nativeToJava
converts a platform specific
+ * representation of RTF text to a java String
.
+ * For additional information see Transfer#nativeToJava
.
+ *
+ * @param transferData the platform specific representation of the data to be
+ * been converted
+ * @return a java String
containing RTF text if the
+ * conversion was successful; otherwise null
+ */
+public Object nativeToJava(TransferData transferData){
+ if (!isSupportedType(transferData) || transferData.pIDataObject is 0) return null;
+ IDataObject data = new IDataObject(transferData.pIDataObject);
+ data.AddRef();
+ STGMEDIUM stgmedium = new STGMEDIUM();
+ FORMATETC formatetc = transferData.formatetc;
+ stgmedium.tymed = COM.TYMED_HGLOBAL;
+ transferData.result = data.GetData(formatetc, stgmedium);
+ data.Release();
+ if (transferData.result !is COM.S_OK) return null;
+ int hMem = stgmedium.unionField;
+ try {
+ int lpMultiByteStr = OS.GlobalLock(hMem);
+ if (lpMultiByteStr is 0) return null;
+ try {
+ int codePage = OS.GetACP();
+ int cchWideChar = OS.MultiByteToWideChar (codePage, OS.MB_PRECOMPOSED, lpMultiByteStr, -1, null, 0);
+ if (cchWideChar is 0) return null;
+ char[] lpWideCharStr = new char [cchWideChar - 1];
+ OS.MultiByteToWideChar (codePage, OS.MB_PRECOMPOSED, lpMultiByteStr, -1, lpWideCharStr, lpWideCharStr.length);
+ return new String(lpWideCharStr);
+ } finally {
+ OS.GlobalUnlock(hMem);
+ }
+ } finally {
+ OS.GlobalFree(hMem);
+ }
+}
+
+protected int[] getTypeIds(){
+ return new int[] {CF_RTFID};
+}
+
+protected String[] getTypeNames(){
+ return new String[] {CF_RTF};
+}
+
+bool checkRTF(Object object) {
+ return (object !is null && object instanceof String && ((String)object).length() > 0);
+}
+
+protected bool validate(Object object) {
+ return checkRTF(object);
+}
+}
diff -r fa7d7d66b9ed -r 242e33c0e383 dwt/dnd/TableDragSourceEffect.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/TableDragSourceEffect.d Wed Feb 13 04:51:22 2008 +0100
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * Copyright (c) 2007 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
+ * Port to the D programming language:
+ * Frank Benoit Table
.
+ *
+ * Classes that wish to provide their own source image for a Table
can
+ * extend the TableDragSourceEffect
class, override the
+ * TableDragSourceEffect.dragStart
method and set the field
+ * DragSourceEvent.image
with their own image.
super
method to get the default drag source effect implementation.
+ *
+ * @see DragSourceEffect
+ * @see DragSourceEvent
+ *
+ * @since 3.3
+ */
+public class TableDragSourceEffect : DragSourceEffect {
+ Image dragSourceImage = null;
+
+ /**
+ * Creates a new TableDragSourceEffect
to handle drag effect
+ * from the specified Table
.
+ *
+ * @param table the Table
that the user clicks on to initiate the drag
+ */
+ public this(Table table) {
+ super(table);
+ }
+
+ /**
+ * This implementation of dragFinished
disposes the image
+ * that was created in TableDragSourceEffect.dragStart
.
+ *
+ * Subclasses that override this method should call super.dragFinished(event)
+ * to dispose the image in the default implementation.
+ *
+ * @param event the information associated with the drag finished event
+ */
+ public void dragFinished(DragSourceEvent event) {
+ if (dragSourceImage !is null) dragSourceImage.dispose();
+ dragSourceImage = null;
+ }
+
+ /**
+ * This implementation of dragStart
will create a default
+ * image that will be used during the drag. The image should be disposed
+ * when the drag is completed in the TableDragSourceEffect.dragFinished
+ * method.
+ *
+ * Subclasses that override this method should call super.dragStart(event)
+ * to use the image from the default implementation.
+ *
+ * @param event the information associated with the drag start event
+ */
+ public void dragStart(DragSourceEvent event) {
+ event.image = getDragSourceImage(event);
+ }
+
+ Image getDragSourceImage(DragSourceEvent event) {
+ if (dragSourceImage !is null) dragSourceImage.dispose();
+ dragSourceImage = null;
+ Table table = (Table) control;
+ TableItem[] selection = table.getSelection();
+ if (selection.length is 0) return null;
+ int tableImageList = OS.SendMessage (table.handle, OS.LVM_GETIMAGELIST, OS.LVSIL_SMALL, 0);
+ if (tableImageList !is 0) {
+ int count = Math.min(selection.length, 10);
+ Rectangle bounds = selection[0].getBounds(0);
+ for (int i = 1; i < count; i++) {
+ bounds = bounds.union(selection[i].getBounds(0));
+ }
+ int hDC = OS.GetDC(0);
+ int hDC1 = OS.CreateCompatibleDC(hDC);
+ int bitmap = OS.CreateCompatibleBitmap(hDC, bounds.width, bounds.height);
+ int hOldBitmap = OS.SelectObject(hDC1, bitmap);
+ RECT rect = new RECT();
+ rect.right = bounds.width;
+ rect.bottom = bounds.height;
+ int hBrush = OS.GetStockObject(OS.WHITE_BRUSH);
+ OS.FillRect(hDC1, rect, hBrush);
+ for (int i = 0; i < count; i++) {
+ TableItem selected = selection[i];
+ Rectangle cell = selected.getBounds(0);
+ POINT pt = new POINT();
+ int imageList = OS.SendMessage (table.handle, OS.LVM_CREATEDRAGIMAGE, table.indexOf(selected), pt);
+ OS.ImageList_Draw(imageList, 0, hDC1, cell.x - bounds.x, cell.y - bounds.y, OS.ILD_SELECTED);
+ OS.ImageList_Destroy(imageList);
+ }
+ OS.SelectObject(hDC1, hOldBitmap);
+ OS.DeleteDC (hDC1);
+ OS.ReleaseDC (0, hDC);
+ Display display = table.getDisplay();
+ dragSourceImage = Image.win32_new(display, DWT.BITMAP, bitmap);
+ return dragSourceImage;
+ }
+ return null;
+ }
+}
diff -r fa7d7d66b9ed -r 242e33c0e383 dwt/dnd/TableDropTargetEffect.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/TableDropTargetEffect.d Wed Feb 13 04:51:22 2008 +0100
@@ -0,0 +1,206 @@
+/*******************************************************************************
+ * Copyright (c) 2007 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
+ * Port to the D programming language:
+ * Frank Benoit Table
.
+ *
+ * Classes that wish to provide their own drag under effect for a Table
+ * can extend the TableDropTargetEffect
and override any applicable methods
+ * in TableDropTargetEffect
to display their own drag under effect.
super
method to get the default drag under effect implementation.
+ *
+ * The feedback value is either one of the FEEDBACK constants defined in
+ * class DND
which is applicable to instances of this class,
+ * or it must be built by bitwise OR'ing together
+ * (that is, using the int
"|" operator) two or more
+ * of those DND
effect constants.
+ *
+ *
TableDropTargetEffect
to handle the drag under effect on the specified
+ * Table
.
+ *
+ * @param table the Table
over which the user positions the cursor to drop the data
+ */
+ public this(Table table) {
+ super(table);
+ }
+
+ int checkEffect(int effect) {
+ // Some effects are mutually exclusive. Make sure that only one of the mutually exclusive effects has been specified.
+ if ((effect & DND.FEEDBACK_SELECT) !is 0) effect = effect & ~DND.FEEDBACK_INSERT_AFTER & ~DND.FEEDBACK_INSERT_BEFORE;
+ if ((effect & DND.FEEDBACK_INSERT_BEFORE) !is 0) effect = effect & ~DND.FEEDBACK_INSERT_AFTER;
+ return effect;
+ }
+
+ /**
+ * This implementation of dragEnter
provides a default drag under effect
+ * for the feedback specified in event.feedback
.
+ *
+ * For additional information see DropTargetAdapter.dragEnter
.
+ *
+ * Subclasses that override this method should call super.dragEnter(event)
+ * to get the default drag under effect implementation.
+ *
+ * @param event the information associated with the drag enter event
+ *
+ * @see DropTargetAdapter
+ * @see DropTargetEvent
+ */
+ public void dragEnter(DropTargetEvent event) {
+ scrollBeginTime = 0;
+ scrollIndex = -1;
+ dropHighlight = null;
+ }
+
+ /**
+ * This implementation of dragLeave
provides a default drag under effect
+ * for the feedback specified in event.feedback
.
+ *
+ * For additional information see DropTargetAdapter.dragLeave
.
+ *
+ * Subclasses that override this method should call super.dragLeave(event)
+ * to get the default drag under effect implementation.
+ *
+ * @param event the information associated with the drag leave event
+ *
+ * @see DropTargetAdapter
+ * @see DropTargetEvent
+ */
+ public void dragLeave(DropTargetEvent event) {
+ Table table = (Table) control;
+ int handle = table.handle;
+ if (dropHighlight !is null) {
+ LVITEM lvItem = new LVITEM ();
+ lvItem.stateMask = OS.LVIS_DROPHILITED;
+ OS.SendMessage(handle, OS.LVM_SETITEMSTATE, -1, lvItem);
+ dropHighlight = null;
+ }
+ scrollBeginTime = 0;
+ scrollIndex = -1;
+ }
+
+ /**
+ * This implementation of dragOver
provides a default drag under effect
+ * for the feedback specified in event.feedback
. The class description
+ * lists the FEEDBACK constants that are applicable to the class.
+ *
+ * For additional information see DropTargetAdapter.dragOver
.
+ *
+ * Subclasses that override this method should call super.dragOver(event)
+ * to get the default drag under effect implementation.
+ *
+ * @param event the information associated with the drag over event
+ *
+ * @see DropTargetAdapter
+ * @see DropTargetEvent
+ * @see DND#FEEDBACK_SELECT
+ * @see DND#FEEDBACK_SCROLL
+ */
+ public void dragOver(DropTargetEvent event) {
+ Table table = (Table) getControl();
+ int effect = checkEffect(event.feedback);
+ int handle = table.handle;
+ Point coordinates = new Point(event.x, event.y);
+ coordinates = table.toControl(coordinates);
+ LVHITTESTINFO pinfo = new LVHITTESTINFO();
+ pinfo.x = coordinates.x;
+ pinfo.y = coordinates.y;
+ OS.SendMessage(handle, OS.LVM_HITTEST, 0, pinfo);
+ if ((effect & DND.FEEDBACK_SCROLL) is 0) {
+ scrollBeginTime = 0;
+ scrollIndex = -1;
+ } else {
+ if (pinfo.iItem !is -1 && scrollIndex is pinfo.iItem && scrollBeginTime !is 0) {
+ if (System.currentTimeMillis() >= scrollBeginTime) {
+ int top = Math.max (0, OS.SendMessage (handle, OS.LVM_GETTOPINDEX, 0, 0));
+ int count = OS.SendMessage (handle, OS.LVM_GETITEMCOUNT, 0, 0);
+ int index = (scrollIndex - 1 < top) ? Math.max(0, scrollIndex - 1) : Math.min(count - 1, scrollIndex + 1);
+ bool scroll = true;
+ if (pinfo.iItem is top) {
+ scroll = pinfo.iItem !is index;
+ } else {
+ RECT itemRect = new RECT ();
+ itemRect.left = OS.LVIR_BOUNDS;
+ if (OS.SendMessage (handle, OS.LVM_GETITEMRECT, pinfo.iItem, itemRect) !is 0) {
+ RECT rect = new RECT ();
+ OS.GetClientRect (handle, rect);
+ POINT pt = new POINT ();
+ pt.x = itemRect.left;
+ pt.y = itemRect.top;
+ if (OS.PtInRect (rect, pt)) {
+ pt.y = itemRect.bottom;
+ if (OS.PtInRect (rect, pt)) scroll = false;
+ }
+ }
+ }
+ if (scroll) {
+ OS.SendMessage (handle, OS.LVM_ENSUREVISIBLE, index, 0);
+ table.redraw();
+ }
+ scrollBeginTime = 0;
+ scrollIndex = -1;
+ }
+ } else {
+ scrollBeginTime = System.currentTimeMillis() + SCROLL_HYSTERESIS;
+ scrollIndex = pinfo.iItem;
+ }
+ }
+
+ if (pinfo.iItem !is -1 && (effect & DND.FEEDBACK_SELECT) !is 0) {
+ TableItem item = table.getItem(pinfo.iItem);
+ if (dropHighlight !is item) {
+ LVITEM lvItem = new LVITEM();
+ lvItem.stateMask = OS.LVIS_DROPHILITED;
+ OS.SendMessage(handle, OS.LVM_SETITEMSTATE, -1, lvItem);
+ lvItem.state = OS.LVIS_DROPHILITED;
+ OS.SendMessage(handle, OS.LVM_SETITEMSTATE, pinfo.iItem, lvItem);
+ dropHighlight = item;
+ }
+ } else {
+ if (dropHighlight !is null) {
+ LVITEM lvItem = new LVITEM ();
+ lvItem.stateMask = OS.LVIS_DROPHILITED;
+ OS.SendMessage(handle, OS.LVM_SETITEMSTATE, -1, lvItem);
+ dropHighlight = null;
+ }
+ }
+ }
+}
diff -r fa7d7d66b9ed -r 242e33c0e383 dwt/dnd/TextTransfer.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/TextTransfer.d Wed Feb 13 04:51:22 2008 +0100
@@ -0,0 +1,186 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2005 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
+ * Port to the D programming language:
+ * Frank Benoit TextTransfer
provides a platform specific mechanism
+ * for converting plain text represented as a java String
+ * to a platform specific representation of the data and vice versa.
+ *
+ * An example of a java String
containing plain text is shown
+ * below:
+ * String textData = "Hello World";
+ *
+ *
+ * @see Transfer
+ */
+public class TextTransfer : ByteArrayTransfer {
+
+ private static TextTransfer _instance = new TextTransfer();
+ private static final String CF_UNICODETEXT = "CF_UNICODETEXT"; //$NON-NLS-1$
+ private static final String CF_TEXT = "CF_TEXT"; //$NON-NLS-1$
+ private static final int CF_UNICODETEXTID = COM.CF_UNICODETEXT;
+ private static final int CF_TEXTID = COM.CF_TEXT;
+
+private this() {}
+
+/**
+ * Returns the singleton instance of the TextTransfer class.
+ *
+ * @return the singleton instance of the TextTransfer class
+ */
+public static TextTransfer getInstance () {
+ return _instance;
+}
+
+/**
+ * This implementation of javaToNative
converts plain text
+ * represented by a java String
to a platform specific representation.
+ *
+ * @param object a java String
containing text
+ * @param transferData an empty TransferData
object; this object
+ * will be filled in on return with the platform specific format of the data
+ *
+ * @see Transfer#javaToNative
+ */
+public void javaToNative (Object object, TransferData transferData){
+ if (!checkText(object) || !isSupportedType(transferData)) {
+ DND.error(DND.ERROR_INVALID_DATA);
+ }
+ transferData.result = COM.E_FAIL;
+ String string = (String)object;
+ switch (transferData.type) {
+ case COM.CF_UNICODETEXT: {
+ int charCount = string.length ();
+ char[] chars = new char[charCount+1];
+ string.getChars (0, charCount, chars, 0);
+ int byteCount = chars.length * 2;
+ int newPtr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, byteCount);
+ OS.MoveMemory(newPtr, chars, byteCount);
+ transferData.stgmedium = new STGMEDIUM();
+ transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
+ transferData.stgmedium.unionField = newPtr;
+ transferData.stgmedium.pUnkForRelease = 0;
+ transferData.result = COM.S_OK;
+ break;
+ }
+ case COM.CF_TEXT: {
+ int count = string.length();
+ char[] chars = new char[count + 1];
+ string.getChars(0, count, chars, 0);
+ int codePage = OS.GetACP();
+ int cchMultiByte = OS.WideCharToMultiByte(codePage, 0, chars, -1, null, 0, null, null);
+ if (cchMultiByte is 0) {
+ transferData.stgmedium = new STGMEDIUM();
+ transferData.result = COM.DV_E_STGMEDIUM;
+ return;
+ }
+ int lpMultiByteStr = OS.GlobalAlloc(COM.GMEM_FIXED | COM.GMEM_ZEROINIT, cchMultiByte);
+ OS.WideCharToMultiByte(codePage, 0, chars, -1, lpMultiByteStr, cchMultiByte, null, null);
+ transferData.stgmedium = new STGMEDIUM();
+ transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
+ transferData.stgmedium.unionField = lpMultiByteStr;
+ transferData.stgmedium.pUnkForRelease = 0;
+ transferData.result = COM.S_OK;
+ break;
+ }
+ }
+ return;
+}
+
+/**
+ * This implementation of nativeToJava
converts a platform specific
+ * representation of plain text to a java String
.
+ *
+ * @param transferData the platform specific representation of the data to be converted
+ * @return a java String
containing text if the conversion was successful; otherwise null
+ *
+ * @see Transfer#nativeToJava
+ */
+public Object nativeToJava(TransferData transferData){
+ if (!isSupportedType(transferData) || transferData.pIDataObject is 0) return null;
+
+ IDataObject data = new IDataObject(transferData.pIDataObject);
+ data.AddRef();
+ FORMATETC formatetc = transferData.formatetc;
+ STGMEDIUM stgmedium = new STGMEDIUM();
+ stgmedium.tymed = COM.TYMED_HGLOBAL;
+ transferData.result = data.GetData(formatetc, stgmedium);
+ data.Release();
+ if (transferData.result !is COM.S_OK) return null;
+ int hMem = stgmedium.unionField;
+ try {
+ switch (transferData.type) {
+ case CF_UNICODETEXTID: {
+ /* Ensure byteCount is a multiple of 2 bytes */
+ int size = OS.GlobalSize(hMem) / 2 * 2;
+ if (size is 0) return null;
+ char[] chars = new char[size/2];
+ int ptr = OS.GlobalLock(hMem);
+ if (ptr is 0) return null;
+ try {
+ OS.MoveMemory(chars, ptr, size);
+ int length = chars.length;
+ for (int i=0; iTransfer
provides a mechanism for converting between a java
+ * representation of data and a platform specific representation of data and
+ * vice versa. It is used in data transfer operations such as drag and drop and
+ * clipboard copy/paste.
+ *
+ * You should only need to become familiar with this class if you are + * implementing a Transfer subclass and you are unable to subclass the + * ByteArrayTransfer class.
+ * + * @see ByteArrayTransfer + */ +public abstract class Transfer { + +/** + * Returns a list of the platform specific data types that can be converted using + * this transfer agent. + * + *Only the data type fields of the TransferData
objects are filled
+ * in.
TransferData
data type can be converted
+ * using this transfer agent, or false otherwise (including if transferData is
+ * null
).
+ *
+ * @param transferData a platform specific description of a data type; only the data
+ * type fields of the TransferData
object need to be filled in
+ *
+ * @return true if the transferData data type can be converted using this transfer
+ * agent
+ */
+abstract public bool isSupportedType(TransferData transferData);
+
+/**
+ * Returns the platform specific ids of the data types that can be converted using
+ * this transfer agent.
+ *
+ * @return the platform specific ids of the data types that can be converted using
+ * this transfer agent
+ */
+abstract protected int[] getTypeIds();
+
+/**
+ * Returns the platform specific names of the data types that can be converted
+ * using this transfer agent.
+ *
+ * @return the platform specific names of the data types that can be converted
+ * using this transfer agent.
+ */
+abstract protected char[][] getTypeNames();
+
+/**
+ * Converts a java representation of data to a platform specific representation of
+ * the data.
+ *
+ * On a successful conversion, the transferData.result field will be set as follows: + *
If this transfer agent is unable to perform the conversion, the transferData.result + * field will be set to a failure value as follows: + *
Transfer
subclass.
+ *
+ * @param transferData an empty TransferData object; this object will be
+ * filled in on return with the platform specific representation of the data
+ *
+ * @exception dwt.DWTException null
null
then
+ * null
is returned. The type of Object that is returned is
+ * dependent on the Transfer
subclass.
+ */
+abstract public Object nativeToJava(TransferData transferData);
+
+/**
+ * Registers a name for a data type and returns the associated unique identifier.
+ *
+ * You may register the same type more than once, the same unique identifier + * will be returned if the type has been previously registered.
+ * + *Note: On windows, do not call this method with pre-defined + * Clipboard Format types such as CF_TEXT or CF_BITMAP because the + * pre-defined identifier will not be returned
+ * + * @param formatName the name of a data type + * + * @return the unique identifier associated with this data type + */ +public static int registerType(char[] formatName) { + // Look name up in the registry + // If name is not in registry, add it and return assigned value. + // If name already exists in registry, return its assigned value + TCHAR chFormatName = new TCHAR(0, formatName, true); + return OS.RegisterClipboardFormat(chFormatName); +} + +/** + * Test that the object is of the correct format for this Transfer class. + * + * @param object a java representation of the data to be converted + * + * @return true if object is of the correct form for this transfer type + * + * @since 3.1 + */ +public bool validate(Object object) { + return true; +} +} diff -r fa7d7d66b9ed -r 242e33c0e383 dwt/dnd/TransferData.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/dnd/TransferData.d Wed Feb 13 04:51:22 2008 +0100 @@ -0,0 +1,109 @@ +/******************************************************************************* + * Copyright (c) 2000, 2004 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 + * Port to the D programming language: + * Frank BenoitTransferData
class is a platform specific data structure for
+ * describing the type and the contents of data being converted by a transfer agent.
+ *
+ * As an application writer, you do not need to know the specifics of + * TransferData. TransferData instances are passed to a subclass of Transfer + * and the Transfer object manages the platform specific issues. + * You can ask a Transfer subclass if it can handle this data by calling + * Transfer.isSupportedType(transferData).
+ * + *You should only need to become familiar with the fields in this class if you + * are implementing a Transfer subclass and you are unable to subclass the + * ByteArrayTransfer class.
+ */ +public class TransferData { + /** + * The type is a unique identifier of a system format or user defined format. + * (Warning: This field is platform dependent) + *+ * IMPORTANT: This field is not part of the DWT + * public API. It is marked public only so that it can be shared + * within the packages provided by DWT. It is not available on all + * platforms and should never be accessed from application code. + *
+ */ + public int type; + + /** + * The formatetc structure is a generalized data transfer format, enhanced to + * encompass a target device, the aspect, or view of the data, and + * a storage medium. + * (Warning: This field is platform dependent) + *+ * IMPORTANT: This field is not part of the DWT + * public API. It is marked public only so that it can be shared + * within the packages provided by DWT. It is not available on all + * platforms and should never be accessed from application code. + *
+ */ + public FORMATETC* formatetc; + + /** + * The stgmedium structure is a generalized global memory handle used for + * data transfer operations. + * (Warning: This field is platform dependent) + *+ * IMPORTANT: This field is not part of the DWT + * public API. It is marked public only so that it can be shared + * within the packages provided by DWT. It is not available on all + * platforms and should never be accessed from application code. + *
+ */ + public STGMEDIUM* stgmedium; + + /** + * The result field contains the result of converting a + * java data type into a platform specific value. + * (Warning: This field is platform dependent) + *+ * IMPORTANT: This field is not part of the DWT + * public API. It is marked public only so that it can be shared + * within the packages provided by DWT. It is not available on all + * platforms and should never be accessed from application code. + *
+ *The value of result is 1 if the conversion was successful. + * The value of result is 0 if the conversion failed.
+ */ + public int result = COM.E_FAIL; + + /** + * The pIDataObject is the address of an IDataObject OLE Interface which + * provides access to the data associated with the transfer. + * (Warning: This field is platform dependent) + *+ * IMPORTANT: This field is not part of the DWT + * public API. It is marked public only so that it can be shared + * within the packages provided by DWT. It is not available on all + * platforms and should never be accessed from application code. + *
+ */ + public IDataObject pIDataObject; + + static bool sameType(TransferData data1, TransferData data2) { + if (data1 is data2) return true; + if (data1 is null || data2 is null) return false; + return (data1.type is data2.type && + data1.formatetc.cfFormat is data2.formatetc.cfFormat && + data1.formatetc.dwAspect is data2.formatetc.dwAspect && + data1.formatetc.tymed is data2.formatetc.tymed); + } + +} diff -r fa7d7d66b9ed -r 242e33c0e383 dwt/dnd/TreeDragSourceEffect.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/dnd/TreeDragSourceEffect.d Wed Feb 13 04:51:22 2008 +0100 @@ -0,0 +1,119 @@ +/******************************************************************************* + * Copyright (c) 2007 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 + * Port to the D programming language: + * Frank BenoitTree
.
+ *
+ * Classes that wish to provide their own source image for a Tree
can
+ * extend TreeDragSourceEffect
class and override the TreeDragSourceEffect.dragStart
+ * method and set the field DragSourceEvent.image
with their own image.
super
method to get the default drag under effect implementation.
+ *
+ * @see DragSourceEffect
+ * @see DragSourceEvent
+ *
+ * @since 3.3
+ */
+public class TreeDragSourceEffect : DragSourceEffect {
+ Image dragSourceImage = null;
+
+ /**
+ * Creates a new TreeDragSourceEffect
to handle drag effect
+ * from the specified Tree
.
+ *
+ * @param tree the Tree
that the user clicks on to initiate the drag
+ */
+ public this(Tree tree) {
+ super(tree);
+ }
+
+ /**
+ * This implementation of dragFinished
disposes the image
+ * that was created in TreeDragSourceEffect.dragStart
.
+ *
+ * Subclasses that override this method should call super.dragFinished(event)
+ * to dispose the image in the default implementation.
+ *
+ * @param event the information associated with the drag finished event
+ */
+ public void dragFinished(DragSourceEvent event) {
+ if (dragSourceImage !is null) dragSourceImage.dispose();
+ dragSourceImage = null;
+ }
+
+ /**
+ * This implementation of dragStart
will create a default
+ * image that will be used during the drag. The image should be disposed
+ * when the drag is completed in the TreeDragSourceEffect.dragFinished
+ * method.
+ *
+ * Subclasses that override this method should call super.dragStart(event)
+ * to use the image from the default implementation.
+ *
+ * @param event the information associated with the drag start event
+ */
+ public void dragStart(DragSourceEvent event) {
+ event.image = getDragSourceImage(event);
+ }
+
+ Image getDragSourceImage(DragSourceEvent event) {
+ if (dragSourceImage !is null) dragSourceImage.dispose();
+ dragSourceImage = null;
+ Tree tree = (Tree) control;
+ TreeItem[] selection = tree.getSelection();
+ if (selection.length is 0) return null;
+ int treeImageList = OS.SendMessage (tree.handle, OS.TVM_GETIMAGELIST, OS.TVSIL_NORMAL, 0);
+ if (treeImageList !is 0) {
+ int count = Math.min(selection.length, 10);
+ Rectangle bounds = selection[0].getBounds(0);
+ for (int i = 1; i < count; i++) {
+ bounds = bounds.union(selection[i].getBounds(0));
+ }
+ int hDC = OS.GetDC(0);
+ int hDC1 = OS.CreateCompatibleDC(hDC);
+ int bitmap = OS.CreateCompatibleBitmap(hDC, bounds.width, bounds.height);
+ int hOldBitmap = OS.SelectObject(hDC1, bitmap);
+ RECT rect = new RECT();
+ rect.right = bounds.width;
+ rect.bottom = bounds.height;
+ int hBrush = OS.GetStockObject(OS.WHITE_BRUSH);
+ OS.FillRect(hDC1, rect, hBrush);
+ for (int i = 0; i < count; i++) {
+ TreeItem selected = selection[i];
+ Rectangle cell = selected.getBounds(0);
+ int imageList = OS.SendMessage(tree.handle, OS.TVM_CREATEDRAGIMAGE, 0, selected.handle);
+ OS.ImageList_Draw(imageList, 0, hDC1, cell.x - bounds.x, cell.y - bounds.y, OS.ILD_SELECTED);
+ OS.ImageList_Destroy(imageList);
+ }
+ OS.SelectObject(hDC1, hOldBitmap);
+ OS.DeleteDC (hDC1);
+ OS.ReleaseDC (0, hDC);
+ Display display = tree.getDisplay();
+ dragSourceImage = Image.win32_new(display, DWT.BITMAP, bitmap);
+ return dragSourceImage;
+ }
+ return null;
+ }
+}
diff -r fa7d7d66b9ed -r 242e33c0e383 dwt/dnd/TreeDropTargetEffect.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/TreeDropTargetEffect.d Wed Feb 13 04:51:22 2008 +0100
@@ -0,0 +1,280 @@
+/*******************************************************************************
+ * Copyright (c) 2007 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
+ * Port to the D programming language:
+ * Frank Benoit Tree
.
+ *
+ * Classes that wish to provide their own drag under effect for a Tree
+ * can extend the TreeDropTargetEffect
class and override any applicable methods
+ * in TreeDropTargetEffect
to display their own drag under effect.
super
method to get the default drag under effect implementation.
+ *
+ * The feedback value is either one of the FEEDBACK constants defined in
+ * class DND
which is applicable to instances of this class,
+ * or it must be built by bitwise OR'ing together
+ * (that is, using the int
"|" operator) two or more
+ * of those DND
effect constants.
+ *
+ *
+ * Note: Only one of the styles FEEDBACK_SELECT, FEEDBACK_INSERT_BEFORE or + * FEEDBACK_INSERT_AFTER may be specified. + *
+ * + * @see DropTargetAdapter + * @see DropTargetEvent + * + * @since 3.3 + */ +public class TreeDropTargetEffect : DropTargetEffect { + static final int SCROLL_HYSTERESIS = 200; // milli seconds + static final int EXPAND_HYSTERESIS = 1000; // milli seconds + + int dropIndex; + int scrollIndex; + long scrollBeginTime; + int expandIndex; + long expandBeginTime; + TreeItem insertItem; + bool insertBefore; + + /** + * Creates a newTreeDropTargetEffect
to handle the drag under effect on the specified
+ * Tree
.
+ *
+ * @param tree the Tree
over which the user positions the cursor to drop the data
+ */
+ public this(Tree tree) {
+ super(tree);
+ }
+
+ int checkEffect(int effect) {
+ // Some effects are mutually exclusive. Make sure that only one of the mutually exclusive effects has been specified.
+ if ((effect & DND.FEEDBACK_SELECT) !is 0) effect = effect & ~DND.FEEDBACK_INSERT_AFTER & ~DND.FEEDBACK_INSERT_BEFORE;
+ if ((effect & DND.FEEDBACK_INSERT_BEFORE) !is 0) effect = effect & ~DND.FEEDBACK_INSERT_AFTER;
+ return effect;
+ }
+
+ /**
+ * This implementation of dragEnter
provides a default drag under effect
+ * for the feedback specified in event.feedback
.
+ *
+ * For additional information see DropTargetAdapter.dragEnter
.
+ *
+ * Subclasses that override this method should call super.dragEnter(event)
+ * to get the default drag under effect implementation.
+ *
+ * @param event the information associated with the drag enter event
+ *
+ * @see DropTargetAdapter
+ * @see DropTargetEvent
+ */
+ public void dragEnter(DropTargetEvent event) {
+ dropIndex = -1;
+ insertItem = null;
+ expandBeginTime = 0;
+ expandIndex = -1;
+ scrollBeginTime = 0;
+ scrollIndex = -1;
+ }
+
+ /**
+ * This implementation of dragLeave
provides a default drag under effect
+ * for the feedback specified in event.feedback
.
+ *
+ * For additional information see DropTargetAdapter.dragLeave
.
+ *
+ * Subclasses that override this method should call super.dragLeave(event)
+ * to get the default drag under effect implementation.
+ *
+ * @param event the information associated with the drag leave event
+ *
+ * @see DropTargetAdapter
+ * @see DropTargetEvent
+ */
+ public void dragLeave(DropTargetEvent event) {
+ Tree tree = (Tree) control;
+ int handle = tree.handle;
+ if (dropIndex !is -1) {
+ TVITEM tvItem = new TVITEM ();
+ tvItem.hItem = dropIndex;
+ tvItem.mask = OS.TVIF_STATE;
+ tvItem.stateMask = OS.TVIS_DROPHILITED;
+ tvItem.state = 0;
+ OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+ dropIndex = -1;
+ }
+ if (insertItem !is null) {
+ tree.setInsertMark(null, false);
+ insertItem = null;
+ }
+ expandBeginTime = 0;
+ expandIndex = -1;
+ scrollBeginTime = 0;
+ scrollIndex = -1;
+ }
+
+ /**
+ * This implementation of dragOver
provides a default drag under effect
+ * for the feedback specified in event.feedback
.
+ *
+ * For additional information see DropTargetAdapter.dragOver
.
+ *
+ * Subclasses that override this method should call super.dragOver(event)
+ * to get the default drag under effect implementation.
+ *
+ * @param event the information associated with the drag over event
+ *
+ * @see DropTargetAdapter
+ * @see DropTargetEvent
+ * @see DND#FEEDBACK_SELECT
+ * @see DND#FEEDBACK_INSERT_BEFORE
+ * @see DND#FEEDBACK_INSERT_AFTER
+ * @see DND#FEEDBACK_SCROLL
+ */
+ public void dragOver(DropTargetEvent event) {
+ Tree tree = (Tree) getControl();
+ int effect = checkEffect(event.feedback);
+ int handle = tree.handle;
+ Point coordinates = new Point(event.x, event.y);
+ coordinates = tree.toControl(coordinates);
+ TVHITTESTINFO lpht = new TVHITTESTINFO ();
+ lpht.x = coordinates.x;
+ lpht.y = coordinates.y;
+ OS.SendMessage (handle, OS.TVM_HITTEST, 0, lpht);
+ int hItem = lpht.hItem;
+ if ((effect & DND.FEEDBACK_SCROLL) is 0) {
+ scrollBeginTime = 0;
+ scrollIndex = -1;
+ } else {
+ if (hItem !is -1 && scrollIndex is hItem && scrollBeginTime !is 0) {
+ if (System.currentTimeMillis() >= scrollBeginTime) {
+ int topItem = OS.SendMessage(handle, OS.TVM_GETNEXTITEM, OS.TVGN_FIRSTVISIBLE, 0);
+ int nextItem = OS.SendMessage(handle, OS.TVM_GETNEXTITEM, hItem is topItem ? OS.TVGN_PREVIOUSVISIBLE : OS.TVGN_NEXTVISIBLE, hItem);
+ bool scroll = true;
+ if (hItem is topItem) {
+ scroll = nextItem !is 0;
+ } else {
+ RECT itemRect = new RECT ();
+ itemRect.left = nextItem;
+ if (OS.SendMessage (handle, OS.TVM_GETITEMRECT, 1, itemRect) !is 0) {
+ RECT rect = new RECT ();
+ OS.GetClientRect (handle, rect);
+ POINT pt = new POINT ();
+ pt.x = itemRect.left;
+ pt.y = itemRect.top;
+ if (OS.PtInRect (rect, pt)) {
+ pt.y = itemRect.bottom;
+ if (OS.PtInRect (rect, pt)) scroll = false;
+ }
+ }
+ }
+ if (scroll) {
+ OS.SendMessage (handle, OS.TVM_ENSUREVISIBLE, 0, nextItem);
+ tree.redraw();
+ }
+ scrollBeginTime = 0;
+ scrollIndex = -1;
+ }
+ } else {
+ scrollBeginTime = System.currentTimeMillis() + SCROLL_HYSTERESIS;
+ scrollIndex = hItem;
+ }
+ }
+ if ((effect & DND.FEEDBACK_EXPAND) is 0) {
+ expandBeginTime = 0;
+ expandIndex = -1;
+ } else {
+ if (hItem !is -1 && expandIndex is hItem && expandBeginTime !is 0) {
+ if (System.currentTimeMillis() >= expandBeginTime) {
+ if (OS.SendMessage (handle, OS.TVM_GETNEXTITEM, OS.TVGN_CHILD, hItem) !is 0) {
+ TVITEM tvItem = new TVITEM ();
+ tvItem.hItem = hItem;
+ tvItem.mask = OS.TVIF_HANDLE | OS.TVIF_STATE;
+ OS.SendMessage (handle, OS.TVM_GETITEM, 0, tvItem);
+ if ((tvItem.state & OS.TVIS_EXPANDED) is 0) {
+ OS.SendMessage (handle, OS.TVM_EXPAND, OS.TVE_EXPAND, hItem);
+ tree.redraw();
+ }
+ }
+ expandBeginTime = 0;
+ expandIndex = -1;
+ }
+ } else {
+ expandBeginTime = System.currentTimeMillis() + EXPAND_HYSTERESIS;
+ expandIndex = hItem;
+ }
+ }
+ if (dropIndex !is -1 && (dropIndex !is hItem || (effect & DND.FEEDBACK_SELECT) is 0)) {
+ TVITEM tvItem = new TVITEM ();
+ tvItem.hItem = dropIndex;
+ tvItem.mask = OS.TVIF_STATE;
+ tvItem.stateMask = OS.TVIS_DROPHILITED;
+ tvItem.state = 0;
+ OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+ dropIndex = -1;
+ }
+ if (hItem !is -1 && hItem !is dropIndex && (effect & DND.FEEDBACK_SELECT) !is 0) {
+ TVITEM tvItem = new TVITEM ();
+ tvItem.hItem = hItem;
+ tvItem.mask = OS.TVIF_STATE;
+ tvItem.stateMask = OS.TVIS_DROPHILITED;
+ tvItem.state = OS.TVIS_DROPHILITED;
+ OS.SendMessage (handle, OS.TVM_SETITEM, 0, tvItem);
+ dropIndex = hItem;
+ }
+ if ((effect & DND.FEEDBACK_INSERT_BEFORE) !is 0 || (effect & DND.FEEDBACK_INSERT_AFTER) !is 0) {
+ bool before = (effect & DND.FEEDBACK_INSERT_BEFORE) !is 0;
+ /*
+ * Bug in Windows. When TVM_SETINSERTMARK is used to set
+ * an insert mark for a tree and an item is expanded or
+ * collapsed near the insert mark, the tree does not redraw
+ * the insert mark properly. The fix is to hide and show
+ * the insert mark whenever an item is expanded or collapsed.
+ * Since the insert mark can not be queried from the tree,
+ * use the Tree API rather than calling the OS directly.
+ */
+ TreeItem item = (TreeItem)tree.getDisplay().findWidget(tree.handle, hItem);
+ if (item !is null) {
+ if (item !is insertItem || before !is insertBefore) {
+ tree.setInsertMark(item, before);
+ }
+ insertItem = item;
+ insertBefore = before;
+ } else {
+ if (insertItem !is null) {
+ tree.setInsertMark(null, false);
+ }
+ insertItem = null;
+ }
+ } else {
+ if (insertItem !is null) {
+ tree.setInsertMark(null, false);
+ }
+ insertItem = null;
+ }
+ }
+}
diff -r fa7d7d66b9ed -r 242e33c0e383 dwt/dnd/URLTransfer.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwt/dnd/URLTransfer.d Wed Feb 13 04:51:22 2008 +0100
@@ -0,0 +1,151 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 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
+ * Port to the D programming language:
+ * Frank Benoit URLTransfer
provides a platform specific mechanism
+ * for converting text in URL format represented as a java String[]
+ * to a platform specific representation of the data and vice versa. See
+ * Transfer
for additional information. The first string in the
+ * array is mandatory and must contain the fully specified url. The second
+ * string in the array is optional and if present contains the title for the
+ * page.
+ *
+ * An example of a java String[]
containing a URL is shown
+ * below:
+ * String[] urlData = new String[] {"http://www.eclipse.org", "Eclipse.org Main Page"};
+ *
+ */
+/*public*/ class URLTransfer : ByteArrayTransfer {
+
+ static URLTransfer _instance = new URLTransfer();
+ static final String CFSTR_INETURL = "UniformResourceLocator"; //$NON-NLS-1$
+ static final int CFSTR_INETURLID = registerType(CFSTR_INETURL);
+
+private this() {}
+
+/**
+ * Returns the singleton instance of the URLTransfer class.
+ *
+ * @return the singleton instance of the URLTransfer class
+ */
+public static URLTransfer getInstance () {
+ return _instance;
+}
+
+/**
+ * This implementation of javaToNative
converts a URL and optionally a title
+ * represented by a java String[]
to a platform specific representation.
+ * For additional information see Transfer#javaToNative
.
+ *
+ * @param object a java String[]
containing a URL and optionally, a title
+ * @param transferData an empty TransferData
object; this
+ * object will be filled in on return with the platform specific format of the data
+ */
+public void javaToNative (Object object, TransferData transferData){
+ if (!checkURL(object) || !isSupportedType(transferData)) {
+ DND.error(DND.ERROR_INVALID_DATA);
+ }
+ transferData.result = COM.E_FAIL;
+ // URL is stored as a null terminated byte array
+ String url = ((String[])object)[0];
+ int count = url.length();
+ char[] chars = new char[count + 1];
+ url.getChars(0, count, chars, 0);
+ int codePage = OS.GetACP();
+ int cchMultiByte = OS.WideCharToMultiByte(codePage, 0, chars, -1, null, 0, null, null);
+ if (cchMultiByte is 0) {
+ transferData.stgmedium = new STGMEDIUM();
+ transferData.result = COM.DV_E_STGMEDIUM;
+ return;
+ }
+ int lpMultiByteStr = OS.GlobalAlloc(OS.GMEM_FIXED | OS.GMEM_ZEROINIT, cchMultiByte);
+ OS.WideCharToMultiByte(codePage, 0, chars, -1, lpMultiByteStr, cchMultiByte, null, null);
+ transferData.stgmedium = new STGMEDIUM();
+ transferData.stgmedium.tymed = COM.TYMED_HGLOBAL;
+ transferData.stgmedium.unionField = lpMultiByteStr;
+ transferData.stgmedium.pUnkForRelease = 0;
+ transferData.result = COM.S_OK;
+ return;
+}
+
+/**
+ * This implementation of nativeToJava
converts a platform specific
+ * representation of a URL and optionally, a title to a java String[]
.
+ * For additional information see Transfer#nativeToJava
.
+ *
+ * @param transferData the platform specific representation of the data to be
+ * been converted
+ * @return a java String[]
containing a URL and optionally a title if the
+ * conversion was successful; otherwise null
+ */
+public Object nativeToJava(TransferData transferData){
+ if (!isSupportedType(transferData) || transferData.pIDataObject is 0) return null;
+ IDataObject data = new IDataObject(transferData.pIDataObject);
+ data.AddRef();
+ STGMEDIUM stgmedium = new STGMEDIUM();
+ FORMATETC formatetc = transferData.formatetc;
+ stgmedium.tymed = COM.TYMED_HGLOBAL;
+ transferData.result = data.GetData(formatetc, stgmedium);
+ data.Release();
+ if (transferData.result !is COM.S_OK) return null;
+ int hMem = stgmedium.unionField;
+ try {
+ int lpMultiByteStr = OS.GlobalLock(hMem);
+ if (lpMultiByteStr is 0) return null;
+ try {
+ int codePage = OS.GetACP();
+ int cchWideChar = OS.MultiByteToWideChar (codePage, OS.MB_PRECOMPOSED, lpMultiByteStr, -1, null, 0);
+ if (cchWideChar is 0) return null;
+ char[] lpWideCharStr = new char [cchWideChar - 1];
+ OS.MultiByteToWideChar (codePage, OS.MB_PRECOMPOSED, lpMultiByteStr, -1, lpWideCharStr, lpWideCharStr.length);
+ return new String[]{new String(lpWideCharStr)};
+ } finally {
+ OS.GlobalUnlock(hMem);
+ }
+ } finally {
+ OS.GlobalFree(hMem);
+ }
+}
+
+protected int[] getTypeIds(){
+ return new int[] {CFSTR_INETURLID};
+}
+
+protected String[] getTypeNames(){
+ return new String[] {CFSTR_INETURL};
+}
+
+bool checkURL(Object object) {
+ if (object is null || !(object instanceof String[]) || ((String[])object).length is 0) return false;
+ String[] strings = (String[])object;
+ if (strings[0] is null || strings[0].length() is 0) return false;
+ try {
+ new URL(strings[0]);
+ } catch (java.net.MalformedURLException e) {
+ return false;
+ }
+ return true;
+}
+
+protected bool validate(Object object) {
+ return checkURL(object);
+}
+}