Drag and drop

Like the clipboard, drag and drop is a way to transfer data between different applications.

Most operating systems implement the drag and drop system in the same way with clipboard, and in Yue dragged data are represented as instances of the Clipboard::Data.

For code examples on handling drag and drop, please see the sample app in yue-sample-apps/drag_source.

Drag destination

A View can be made a drag destination by using the View.RegisterDraggedTypes API, which gives the view abilities to accept dropped data.

view.registerDraggedTypes(['image'])

When users drag data with registered types to the view, drag related events will be emitted in sequence:

  1. The handle_drag_enter and on_drag_leave will be called when the cursor enters or leaves the view while dragging.
  2. The handle_drag_update will be called while cursor moves in the view while dragging.
  3. The handle_drop will be called user releases cursor and drops the data on the view.

To accept dropped data, the handle_drag_enter should be implemented first to decide which DragOperation to perform when cursor is dropped. Depending on the returned drag operation, the cursor may have different icons.

view.handleDragEnter = (self, info, point) => {
  isDragging = true
  return gui.DraggingInfo.dragOperationCopy
}

If you are implementing some visual effects when there are data being dragged to the view, you may want to do some cleanup in on_drag_leave, which is called when cursor moves out of the view and before users drops the data on the view.

view.onDragLeave = (self) => {
  isDragging = true
}

If the view supports different drag operations depending on the cursor position, you may want to implement handle_drag_update, and return the drag operation according to the cursor position in the view.

If you don't implement handle_drag_update, the return value of previous handle_drag_enter call will be used.

view.handledragUpdate = (self, info, point) => {
  if (pointInDragArea(point))
    return gui.DraggingInfo.dragOperationCopy
  else
    return gui.DraggingInfo.dragOperationNone
}

Finally, by implementing handle_drop, you can read the dragged data from the passed DraggingInfo instance.

view.handleDrop = (self, info, point) => {
  if (info.isDataAvailable('image')) {
    displayImage(info.getData('image').value)
    return true
  }
  return false
}

Drag source

To make it possible for users to drag some data from current applications to other destinations, you can listen to mouse down events and use the View.DoDrag API.

source.setMouseDownCanMoveWindow(false)
source.onMouseDown = (self) => {
  const ret = self.doDrag([{type: 'file-paths', value: [filePath]}],
                          gui.DraggingInfo.dragOperationCopy | gui.DraggingInfo.dragOperationLink)
  if (ret == gui.DraggingInfo.dragOperationCopy)
    copyData()
  else if (ret == gui.DraggingInfo.dragOperationLink)
    linkData()
  return true
}

The API should be called with the data to provide, and the supported drag operations. The call will be blocked until the user cancels the dragging or drops the data, and it will return the drag operation used by the destination.