User interface programming / Drag & drop |
If a drag & drop is intended to work only in the same application, data can be passed with variables in the context of the current program. For example, in a program using two tables where the user can drag & drop elements between the two lists, identify the selected rows and update the program arrays accordingly. When drag & drop is limited to the current application, avoid the drop outside the current application.
When a drag & drop operation comes from (or goes to) external applications, data can be of various types/formats: plain text, formatted text, documents, images, sounds, videos, and so on. In order to handle the drag & drop data, you must identify the type of data held in the drag & drop buffer. The type of data in the buffer is identified by the MIME type (Multiple Internet Mail Extensions). MIME types are a widely used internet standard specification, first introduced to identify the content of e-mail attachments.
Only text data can be passed with drag & drop; binary data is not supported. However, you can pass files by using the fgl_getfile() file transfer function, and identify the file with a URI (text-uri-list MIME type). For a working example, see the demos in FGLDIR/demo/DragAndDrop.
Example of MIME types:
You can also define your own MIME type, as long as it does not conflict with existing standard MIME types. For example:
If you do not specify a MIME type when the drag starts, the type defaults to text/plain, and the dialog will by default copy the data from selected rows into the drag & drop buffer. To prevent drag & drop to external applications, you must pass an application-specific MIME type to the ui.DragDrop.setMimeType() method, to be sure that other applications do not recognize the MIME type and will deny the drop.
If the program implements drag & drop of objects that can be dropped to external programs, you must specify the MIME type of the object and copy the data to the drag & drop buffer, so that the external application can identify the data format and receive it.
In the ON DRAG_START block, you must call the ui.DragDrop.setMimeType() method to define the MIME type of the object, and copy the text data into the buffer with the ui.DragDrop.setBuffer() method.
DEFINE dnd ui.DragDrop ... DISPLAY ARRAY arr TO sr.* ... ... ON DRAG_START(dnd) -- Define the MIME type and copy text data to DnD buffer CALL dnd.setMimeType("text/x-vcard") CALL dnd.setBuffer( buildVCardData( arr[arr_curr()].cid ) ) CALL dnd.setOperation("copy") ... END DISPLAY
This describes how to handle the drop action when the target dialog receives an object dragged from an external source, by identifying the MIME type of the object.
In the ON DRAG_ENTER block, you must call the ui.DragDrop.selectMimeType() method to check that data is available in a format identified by the MIME type, passed as a parameter. If the type of data is available in the buffer, the method returns TRUE. Later, when the dragged object is dropped (ON DROP), you can get the previously selected MIME type with ui.DragDrop.getSelectedMimeType() before calling ui.DragDrop.getBuffer() to retrieve the actual data.
DEFINE dnd ui.DragDrop ... DISPLAY ARRAY arr TO sr.* ... ... ON DRAG_ENTER(dnd) -- Set operation to NULL if unexpected MIME type found CASE WHEN dnd.selectMimeType("text/plain") WHEN dnd.selectMimeType("text/uri-list") OTHERWISE CALL dnd.setOperation(NULL) END CASE ... ON DROP(dnd) -- Select MIME type and get data from buffer LET row = dnd.getLocationRow() CALL DIALOG.insertRow("sr", row) IF dnd.getSelectMimeType() == "text/plain" THEN LET arr[row].text_data = dnd.getBuffer() END IF ... END DISPLAY