Drag and Drop on drop area

Hi,

I need to drop folder on imageWell object (the imageWell show a PNG with “Drop folder here…”) located on window.

I followed one of the Shane post:

Instead of the mainWindow I inserted the dropBoxObject (imageWell). I correctly linked the object to the blue box AppDelegate.


Shane Post:

First you have to register your window for drag an drop, probably in applicationWillFinishLaunching_

Open this Scriplet in your Editor:
on applicationWillFinishLaunching_(aNotification)
– Register for drag and drop
mainWindow’s registerForDraggedTypes_({“public.file-url”})
end applicationWillFinishLaunching_

The you need to make your script the delegate of the window, and include at least two handlers. If you’re going to accept any files, they should be something like this:

Open this Scriplet in your Editor:

on draggingEntered_(sender)
set pb to sender’s draggingPasteboard()
set theOptions to {NSPasteboardURLReadingFileURLsOnlyKey:1}
return pb’s canReadObjectForClasses_options_({current application’s|NSURL|}, theOptions)
end draggingEntered_

on performDragOperation_(sender)
– Get the file path
set pb to sender’s draggingPasteboard()
set theOptions to {NSPasteboardURLReadingFileURLsOnlyKey:1}
set imageURLs to pb’s readObjectsForClasses_options_({current application’s |NSURL|}, theOptions)
set draggedURL to item 1 of (imageURLs as list)
set filePath to draggedURL’s |path|()
return true – otherwise it doesn’t happen
end performDragOperation_


I have done all but when I run the sample project the drop area don’t accept drop.
I don’t understand the:

“The you need to make your script the delegate of the window, and include at least two handlers. If you’re going to accept any files, they should be something like this”

I have also to connect imageWell to receivedActions performDragOperation_ and draggingEntered_?
In this case only one action can be assigned to the imageWell object.

Ame

Hi,

this is a solution with a bit Objective-C code, using a custom view instead of an image view
The generic folder icon with the drop badge is drawn by default,
when the mouse enters the drag area, the open folder icon is drawn.

It’s assumed that the project runs with Automatic Reference Counting (ARC)

#1 Create a new Objective-C class, name it SKView
#2 Replace the contents of the .h file with


#import <Cocoa/Cocoa.h>

@protocol SKViewDragDelegate <NSObject>
- (void)didDragItems:(NSArray *)draggedItems;
@end


@interface SKView : NSView

@property (strong) NSImage *folderImage;
@property (strong) NSImage *openFolderImage;
@property (strong) NSImage *badge;
@property (assign, nonatomic) BOOL highlighted;

@property (weak) IBOutlet id<SKViewDragDelegate> delegate;

@end


#3 replace the contents of the .m file with


#import "SKView.h"

NSString *coreTypesFolder = @"/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources";

@implementation SKView

- (id)initWithFrame:(NSRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self registerForDraggedTypes:@[NSURLPboardType]];
        NSImage* (^ImageForIcon)(NSString*) = ^(NSString* icon) {
            return [[NSImage alloc] initWithContentsOfFile:[coreTypesFolder stringByAppendingPathComponent:icon]];
        };
        _folderImage = ImageForIcon(@"GenericFolderIcon.icns");
        _openFolderImage = ImageForIcon(@"OpenFolderIcon.icns");
        _badge = ImageForIcon(@"DropFolderBadgeIcon.icns");
    }
    return self;
}

- (void)drawRect:(NSRect)dirtyRect
{
    NSImage *imageToDraw;
	imageToDraw = (self.highlighted) ? self.openFolderImage : self.folderImage;
	[imageToDraw drawInRect:dirtyRect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0f];
    [self.badge drawInRect:dirtyRect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0f];
}

- (void)dealloc {[self unregisterDraggedTypes];}

- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender {return YES;}

- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender
{
    if ((NSDragOperationCopy & [sender draggingSourceOperationMask]) == NSDragOperationCopy) {
        NSPasteboard* thePasteboard = [sender draggingPasteboard];
		NSString *type = [thePasteboard availableTypeFromArray:@[NSURLPboardType]];
		if (type != nil) {
			self.highlighted = YES;
			return NSDragOperationCopy;
		}
	}
	return NSDragOperationNone;
}

- (void)draggingExited:(id <NSDraggingInfo>)sender {self.highlighted = NO;}

- (void)concludeDragOperation:(id <NSDraggingInfo>)sender
{
	NSPasteboard *pboard = [sender draggingPasteboard];
    if ( [[pboard types] containsObject:NSURLPboardType] ) {
        NSArray *fileURLs = [pboard readObjectsForClasses:@[[NSURL class]] options:@{NSPasteboardURLReadingFileURLsOnlyKey : @YES}];
        if (_delegate && [_delegate respondsToSelector:@selector(didDragItems:)]) {
            [_delegate didDragItems];
        }
    }
	self.highlighted = NO;
}

- (void)setHighlighted:(BOOL)flag
{
	_highlighted = flag;
	[self setNeedsDisplay:YES];
}


@end

#4 In Interface builder replace the image well with a custom view (NSView)
#5 Set the class of the custom view to SKView
#6 Connect the delegate property of the custom view to the blue cube of the app delegate script

#7 in the app delegate script implement the delegate method


    on didDragItems_(draggedItems) -- returns an array of file URL's
        log draggedItems as list
    end didDragItems_

You control-click on the window, and drag from where it says delegate across to the blue cube representing the script.

Hi Shane,

thanks for the reply. All works making all window area droppable.
But what I want to do is to have an area in the window (ImageWell with image that say Drop files/folders here…) where I can drop items.
I spent a lot of time searching in Google and/or MacScripter but I can’t find any example about how to make droppable a particular object, in this case imageWell.

Thanks to StefanK too even if his version is for Obj-C Developers. I think that only a limited numbers of “scripters” that browse every day MacScripter.net can understand the routine. Most of us will desire a short and syntax simple commands.
Unfortunately Asoc make some previous ASS things much much more complicated than before with API syntax not very easy.

Ame

To add drag & drop functionality to a specific UI element in a window you have to subclass this element.
Unfortunately in most cases it’s neither short nor simple :wink:

Thanks Stefan for the answer.
Any workaround not using imageWell but using other objects that can receive drop actions?

Ame

To add d&d it’s necessary to override some methods for defining custom types and behavior.

BTW: In post #2 I tried first subclassing in ASObjC but to no avail (app crashed).
The ObjC code is easier to implement than it looks like

After googling and many hours this is my workaround:

Create new project.
In the main AppDelegate no extra code except for the two handlers created by default
Create new file called for example DragAndDrop.applescript and populate it with:

script DragAndDrop

property parent: class “NSImageView”

on draggingEntered_(info)
log “Enter Dragging”
return current application’s NSDragOperationCopy
end draggingEntered_

on performDragOperation_(sender)
– Get the file path
set pb to sender’s draggingPasteboard()
set theOptions to {NSPasteboardURLReadingFileURLsOnlyKey:1}
set imageURLs to pb’s readObjectsForClasses_options_({current application’s |NSURL|}, theOptions)
set draggedURL to item 1 of (imageURLs as list)
set filePath to draggedURL’s |path|()
log imageURLs
log filePath as string
return true – otherwise it doesn’t happen
end performDragOperation_

end script

Now in Interface builder in the main Window insert a “custom view” and from identity Inspector change the class to “DragAndDrop”, the name of new script file created.
Now insert a imageWell with customized image png like “Drop files and folder here…” and send it back to custom view. If the imageWell is on the top the drag and drop don’t works because cover the customView area.
So the order will be: Window, imageWell and on the top the customView

I don’t know if all is correct but all works accepting and logging files and folders path (what I need)
Strange but in the main AppDelegate seems not required the command
imageView’s registerForDraggedTypes_({“public.file-url”})

Ame