Friday, October 23, 2020

#1 2013-07-10 07:58:36 am

ame
Member
Registered: 2011-06-28
Posts: 178

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


Filed under: folder, drag, drop

Offline

 

#2 2013-07-10 10:51:48 am

StefanK
Member
From:: St. Gallen, Switzerland
Registered: 2006-10-21
Posts: 11697
Website

Re: Drag and Drop on drop area

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

Applescript:


#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

Applescript:


#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:fileURLs];
}
}
   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

Applescript:


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

Last edited by StefanK (2013-07-10 12:49:35 pm)


regards

Stefan

Offline

 

#3 2013-07-10 05:01:50 pm

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 6470

Re: Drag and Drop on drop area

I don't understand the:

"The you need to make your script the delegate of the window


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


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/
latenightsw.com

Offline

 

#4 2013-07-11 03:47:36 am

ame
Member
Registered: 2011-06-28
Posts: 178

Re: Drag and Drop on drop area

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

Offline

 

#5 2013-07-11 03:52:02 am

StefanK
Member
From:: St. Gallen, Switzerland
Registered: 2006-10-21
Posts: 11697
Website

Re: Drag and Drop on drop area

ame wrote:

Most of us will desire a short and syntax simple commands.


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


regards

Stefan

Offline

 

#6 2013-07-11 05:23:32 am

ame
Member
Registered: 2011-06-28
Posts: 178

Re: Drag and Drop on drop area

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

Ame

Offline

 

#7 2013-07-11 12:32:38 pm

StefanK
Member
From:: St. Gallen, Switzerland
Registered: 2006-10-21
Posts: 11697
Website

Re: Drag and Drop on drop area

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

Last edited by StefanK (2013-07-11 12:37:10 pm)


regards

Stefan

Offline

 

#8 2013-07-12 07:30:40 am

ame
Member
Registered: 2011-06-28
Posts: 178

Re: Drag and Drop on drop area

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


Filed under: drag, drop, ImageWell

Offline

 

Board footer

Powered by FluxBB

RSS (new topics) RSS (active topics)