Handle drag & drop data with MIME types
How to handle MIME types with 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 Multipurpose Internet Mail Extensions (MIME) type. 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.
getBuffer()
method can contain URL-encoded characters such as
%5E
, which represents the ^
caret. Therefore, you must URL-decode
strings returned from getBuffer()
with util.Strings.urlDecode()
. When
setting the drag & drop buffer content, if required by the front-end platform, the string can be
URL-encoded using util.Strings.urlEncode()
for setBuffer()
. However, URL-encoding
file paths for setBuffer()
is usually not required.Example of MIME types:
- text/plain
- text/uri-list
- text/x-vcard
You can also define your own MIME type, as long as it does not conflict with existing standard MIME types. For example:
- text/my-remote-file
- text/my-customer-record
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 ensure that other applications do not recognize the MIME type and
therefore reject the drop.
Preparing the dragged object for external targets
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.
DISPLAY ARRAY
dialog preparing the drag &
drop buffer to export VCard data from a dragged row: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
Receiving the dragged object from external sources
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.
ON DRAG_ENTER
,
the program checks available MIME types, and denies the drop operation if the buffer
does not hold any of the MIME types that can be treated by the program. In
ON DROP
, the program calls getSelectMimeType()
to
check what MIME type was selected, retrieves the data with getBuffer()
,
then inserts a new row and puts the data in dedicated fields depending on the MIME
type: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