First you should decide which CAPI pane(s) and interfaces will support dropping, where exactly dropping should be allowed, and what should occur on dropping for each data format that is made available.
To implement dropping in list-panel or tree-view or output-pane, supply the :drop-callback
initarg.
You can also supply :drop-callback
for an interface. When the user drags an object over a window, the system first tries to call the
drop-callback
of any pane under the mouse and otherwise calls the
drop-callback
of the top-level interface, if supplied.
The drop-callback receives as arguments a drop-object which is used to communicate information about the dropping operation and stage which is a keyword. The drop-callback is called at several stages: when the pane is displayed; when the user drags over the pane; and when the user drops over the pane. Various functions are provided which you can use to query the drop-object and set attributes appropriately.
You will use set-drop-object-supported-formats to specify the data formats that it wants to receive. The :string
format can be used to receive a string from another application and the :filename-list
format can be used to receive a list of filenames from another application such as the Macintosh Finder or the Windows Explorer. Any other keyword in formats is assumed to be a private format that can only be used to receive objects from within the same Lisp image.
You can use drop-object-provides-format to query whether a given data format is actually available, and then you can call (setf drop-object-drop-effect)
to modify the effect of the dropping operation .
Finally, at the :drop
stage, you will use drop-object-get-object to retrieve (for each data format) the object which was returned by the
drag-callback
, and then do something with this object, typically copying or moving it to the pane in some way.
Additionally within the drop-callback of a list-panel or tree-view you can use drop-object-collection-index (or drop-object-collection-item) to query the index (or item) where the object would currently be dropped.
This drop-callback simply appends the dropped string at the end of the list:
(defun list-drop-callback (pane drop-object stage)
(format t "list drop callback ~S ~S ~S" pane drop-object stage)
(case stage
(:formats
(set-drop-object-supported-formats drop-object
(list :string)))
((:enter :drag)
(when (and (drop-object-provides-format drop-object
:string)
(drop-object-allows-drop-effect-p drop-object
:copy))
(setf (drop-object-drop-effect drop-object) :copy)))
(:drop
(when (and (drop-object-provides-format drop-object
:string)
(drop-object-allows-drop-effect-p drop-object
:copy))
(setf (drop-object-drop-effect drop-object) :copy)
(add-list-item pane drop-object)))))
(defun add-list-item (pane drop-object)
(append-items
pane
(list (string-capitalize
(drop-object-get-object drop-object
pane :string)))))
(contain
(make-instance 'list-panel
:title "Shopping list"
:items (list "Tea" "Bread")
:drop-callback 'list-drop-callback))
Try dragging an item from the tree-view created in Example: dragging from a tree.
Below is a more sophisticated version of add-list-item
which inserts the item at the expected position within the list. This position is obtained using drop-object-collection-index:
(defun add-list-item (pane drop-object)
(multiple-value-bind (index placement)
(drop-object-collection-index drop-object)
(list-panel-add-item pane
(string-capitalize
(drop-object-get-object
drop-object pane :string))
index placement)))
(defun list-panel-add-item (pane item index placement)
(let ((item-count (count-collection-items pane)))
(let ((adjusted-index (if (eq placement :above)
index
(1+ index)))
(current-items (collection-items pane)))
(setf (collection-items pane)
(concatenate 'simple-vector
(subseq current-items 0 adjusted-index)
(vector item)
(subseq current-items adjusted-index
item-count))))))
Supply the special
drop-callback
:default
to implement dropping text in an editor-pane.
Additionally within the drop-callback of an output-pane, you can use drop-object-pane-x and drop-object-pane-y to query the coordinates in the pane that the object is being dropped over.
CAPI User Guide and Reference Manual (Macintosh version) - 3 Aug 2017