Search code examples
applescript-objc

How to create an ImageView as drag and drop?


I would like to know how to make an ImageView drag and drop, I will drag a certain file to an ImageView and it will render an action.

I know I can use the code below in a Script Editor and save it as a application could then drag the files into it and do an action but would like to know how it would be done in an ImageView.

Thanks in advance!

on open myItems
    repeat with one_item in myItems
        ---Blablabla        
    end repeat
end open

Solution

  • An NSImageView's parent class is NSControl, so like any other control it has a target/action you can specify, for example:

    use AppleScript version "2.4" -- Yosemite (10.10) or later
    use framework "Foundation"
    use scripting additions
    
    property mainWindow : missing value
    
    on run -- Script Editor example
        my performSelectorOnMainThread:"doWindowStuff" withObject:(missing value) waitUntilDone:true
    end run
    
    on doWindowStuff() -- window stuff needs to be done on the main thread
        try
            set my mainWindow to makeWindow out of {{0, 0}, {400, 200}} given title:"Drag an image:"
            set imageView to makeImageView out of {{100, 50}, {200, 100}}
            mainWindow's contentView's addSubview:imageView
            mainWindow's makeKeyAndOrderFront:me
        on error errmess
            display alert "Error" message errmess
        end try
    end doWindowStuff
    
    to makeWindow out of frame given title:title : "" -- make and return a window
        tell (current application's NSWindow's alloc()'s initWithContentRect:frame styleMask:7 backing:2 defer:yes) -- styleMask of 7 includes title, close and minimize buttons
            if first item of frame is {0, 0} then tell it to |center|()
            its setAutorecalculatesKeyViewLoop:true
            its setTitle:title
            return it
        end tell
    end makeWindow
    
    to makeImageView out of frame -- make and return an image view
        tell (current application's NSImageView's alloc()'s initWithFrame:frame)
            its setTarget:me
            its setAction:"imageDragged:"
            its setEditable:true
            its setImageScaling:(current application's NSImageScaleProportionallyUpOrDown)
            return it
        end tell
    end makeImageView
    
    on imageDragged:sender
        activate me
        display dialog "An image was dragged into the image view."
    end imageDragged:
    

    To do something like get the file path for a dropped image, NSImageView will need to be subclassed. For an Xcode project, add a new .applescript file for the subclass, and set it as the class of your imageView in IB's Identity Inspector:

    script MyImageView -- NSImageView subclass
    
        property parent : class "NSImageView"
        property imagePath : missing value
    
        on draggingEntered:sender
            # additional stuff as desired
            return current application's NSDragOperationCopy
        end draggingEntered:
    
        on performDragOperation:sender
            set pasteboard to sender's draggingPasteboard()
            set theOptions to {NSPasteboardURLReadingFileURLsOnlyKey:1}
            set imageURLs to pasteboard's readObjectsForClasses:{current application's |NSURL|} options:theOptions
            set draggedURL to first item of (imageURLs as list)
            set my imagePath to draggedURL as text
            return true -- data accepted
        end performDragOperation:
    
    end script
    

    You should also register the acceptable drag type(s) for your imageView somewhere in the AppDelegate's setup:

    imageView's registerForDraggedTypes:{"public.image"}
    

    The file path will then be available in the imageView's imagePath property when you drag something to the view. See Apple's Drag and Drop Programming Topics for more information.