macosnspathcontrol

How do I detect and handle a drag from NSPathControl to the Trash dock icon?


The Finder can show an NSPathControl at the bottom of its windows. If the user drags an item from that path control to the Dock's Trash icon, the item gets trashed accordingly.

I like to achieve the same in my program. However, I cannot figure out how to accomplish this because there is no draggingSession:endedAtPoint:operation: as there are with other controls such as NSTableView.

How do track a dragging session of NSPathControl in order to learn that the item was dragged to the Trash so that I can delete it then? Or is there a way to have the deletion happen automatically?

(Of course, I've set the draggingSourceOperationMask to NSDragOperationEvery and dragging to the trash is possible - it's just that the dragged item then doesn't get deleted.)


Solution

  • I suggest you to try following way:

    1. Subclass the NSPathControl class, let's say you name it MyNSPathControl

    2. Declare your NSPathControlDelegate, and allow the drag operations (according to https://developer.apple.com/documentation/appkit/nspathcontroldelegate)

    class DragDelegate : NSObject, NSPathControlDelegate {
        func pathControl(_ pathControl: NSPathControl, shouldDrag pathItem: NSPathControlItem, with pasteboard: NSPasteboard) -> Bool {
            return true;
        }
    }
    
    1. Set delegate into MyNSPathControl
    class MyNSPathControl : NSPathControl {
        var myDelegate = DragDelegate()
        override func awakeFromNib() {
            super.awakeFromNib()
            self.delegate = myDelegate
        }
    }
    
    1. Declare the extension for MyNSPathControl implements NSDraggingSource
    extension DraggableView: NSDraggingSource {
        func draggingSession(_ session: NSDraggingSession, sourceOperationMaskFor context: NSDraggingContext) -> NSDragOperation {
            return .every
        }
    
        func draggingSession(_ session: NSDraggingSession, willBeginAt screenPoint: NSPoint) {
            
        }
    
        func draggingSession(_ session: NSDraggingSession, movedTo screenPoint: NSPoint) {
    
        }
    
        func draggingSession(_ session: NSDraggingSession, endedAt screenPoint: NSPoint, operation: NSDragOperation) {
        //  Here it goes
        }
    }
    

    I'm able to have the NSDragOperation.delete in operation argument when dragging to the Trash. To access the content dragged you should access the pasteboard from session, and then its items.

    Regarding the deletion itself: I think you will need to do it manually.