All Manuals > CAPI User Guide and Reference Manual > 17 Drag and Drop

NextPrevUpTopContentsIndex

17.3 Dropping

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.

17.3.1 The drop callback

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.

17.3.2 Dropping in a choice

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.

17.3.2.1 Example: dropping in a list

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))))))

17.3.3 Dropping text in an editor-pane

Supply the special drop-callback :default to implement dropping text in an editor-pane.

17.3.4 Dropping in an output-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

NextPrevUpTopContentsIndex