Drag and Drop Errors

Hello everyone,
I am having some trouble trying to code drag & drop in my app. Every command after the “return true” doesn’t work. I tried adding the “return true” to the end of the subroutine, but when I do this Console says that theProgress isn’t defined. If this is my problem, how do I hook it up in IB and in my script? Thanks!


script DragAndDrop
	property parent : class "NSImageView"
	
	on draggingEntered_(info)
		return current application's NSDragOperationCopy
	end draggingEntered_
	
	on performDragOperation_(info)
		set pb to info's draggingPasteboard()
		set theURL to pb's readObjectsForClasses_options_({current application's NSURL}, missing value)'s lastObject()
		set theApp to theURL's lastPathComponent()
		set theExt to theURL's pathExtension()
		if theExt as text is "app" then
			log theApp
			theProgress's setHidden_(0)
			theProgress's setDoubleValue_(0)
			theUTI's setStringValue_("Processing...")
			tell theUTI to setFont_(current application's NSFont's fontWithName_size_("Calibri", 20))
			showSheet()
			theProgress's setHidden_(1)
			theUTI's setStringValue_(theID)
			return true
		else
			log "Non-Application file dropped."
			return false
		end if
	end performDragOperation_
end script

What do you mean by that? There are no commands after return true unless your if clause isn’t satisfied, and you go into the else clause. Is that what you mean?

Ric

Sorry, I meant when I try to put “return true” as my first line, it doesn’t work but I think that is normal. Any ideas on hooking up to IB?

What is theProgress? I don’t see that you have it defined as a property in this script. Is it defined in another script? I also don’t see any definition for theUTI or theID.

Also, I’m not sure it’s a good idea to show a sheet in the middle of a drop operation. I would call that from a performSelector_withObject or performSelector_withObject_afterDelay method, so that the drop operation can finish up before the sheet is shown.

Ric

All my variables are defined in my AppDelegate. Also, how would I use the performSelector_withObject method? Could you give an example?

To use performSelector_withObject_

performSelector_withObject_("showTheSheet",missing value)
    
    on showTheSheet()
        showSheet()
    end showSheet

You could also put any of the other lines after “log theApp” and before “return true” that you want to into the showTheSheet method.

As far as your properties. If they are all defined in your app delegate, then you need to have a property in this script that points to the app delegate blue cube. If we call that appDel, then any mentions of properties in the app delegate need to be prefaced by app del’s, so: appDel’s theProgress’s setHidden_(0) etc.

Ric

After edit: On second thought, it would be easier to just put in a concludeDragOperation_ method. This is called after the drag operation is complete. You could put your showSheet() method and anything else you want to do after the drop in there. That way you don’t need the performSelector_withObject method.

Thanks a lot! One more question, would the property just be property Appdel : missing value? And then in IB I hook it up to the cube?

Yes

hmmm still doesn’t work… This is my script but in my console it keeps saying: 2012-01-26 21:26:25.885 Identifier[8504:a0f] *** -[DragAndDrop concludeDragOperation:]: Can’t get theProgress of missing value. (error -1728)


script DragAndDrop
	property parent : class "NSImageView"
	property appDel : missing value
	
	on draggingEntered_(info)
		return current application's NSDragOperationCopy
	end draggingEntered_
	
	on performDragOperation_(info)
		set pb to info's draggingPasteboard()
		set theURL to pb's readObjectsForClasses_options_({current application's NSURL}, missing value)'s lastObject()
		set theApp to theURL's lastPathComponent()
		set theExt to theURL's pathExtension()
		if theExt as text is "app" then
			log theApp
			return true
		else
			log "Non-Application file dropped."
			return false
		end if
	end performDragOperation_
	
	on concludeDragOperation_()
		appDel's theProgress's setHidden_(0)
		appDel's theProgress's setDoubleValue_(0)
		tell theUTI to setFont_(current application's NSFont's fontWithName_size_("Calibri", 20))
		showSheet()
		appDel's theProgress's setHidden_(1)
		appDel's theUTI's setStringValue_(theID)
	end concludeDragOperation_
end script

That error message would suggest that appDel is not hooked up correctly to your app delegate. Can you describe how you did that. Try putting the statement “log appDel” as the first line in your concludeDragOperation method and see what you get in the log.

Ric

In IB, I control dragged from the Drag & Drop to the Identifier App Delegate and I connected it to appDel. This is what I am getting in the Console when I added the “log appDel”: 2012-01-27 10:09:56.799 Identifier[8780:a0f] Automator.app
2012-01-27 10:09:56.801 Identifier[8780:a0f] (null)
2012-01-27 10:09:56.903 Identifier[8780:a0f] *** -[DragAndDrop concludeDragOperation:]: Can’t get theProgress of missing value. (error -1728)

When you say from the Drag & Drop, do you mean the view itself, or do you have a blue cube whose class is set to DragAndDrop? Something is still not hooked up right, that’s why you get null on the log. There shouldn’t be a blue cube for the class DragAndDrop, and your image view’s class should be set to DragAndDrop.

Ric

There is no blue cube for DragAndDrop, I just have a NSImageView. The NSImageView’s class is DragAndDrop. Wonder what is wrong…

Hmmm… This is puzzling. If you right click on your image view in IB (either the view itself or the name in the objects list) it should bring up a black window. There should be appDel there in the outlets list – if you roll over that with the mouse it should highlight the blue cube that is your app delegate. Does it do that?

Ric

It does exactly what you said it should…

Well, I’m baffled. It should work. I tried it and it works for me. Another way that you could try that works to get a reference to the application delegate is to use the delegate() method of NSApplication. Put an awakeFromNib() method in your DragAndDrop script and include the line: set appDel to current application’s NSApp’s |delegate|(). That should work without any connections needed in IB (you should probably get rid of those, and you would still need appDel to be a property). Still, for future reference, it would be good to figure out why the way we’ve been discussing doesn’t work.

Ric

Thanks you so much rdelmar, I know this must be a challenge for you. I will definitely try to figure out where I went wrong… I just have a few more questions, if that’s okay with you. In the preformDragOperation subroutine, I am setting a value for a variable. When I ask to do something with that variable in the concludeDragOperation subroutine, the console says that that variable is not defined. Thanks again rdelmar, I think you may have completed by app’s puzzle.

Do you have that variable defined as a property? It needs to be if you’re using it in more than one method. If you want, you could PM me, and send me a copy of your app so I can look at the project structure and see if I can figure out what’s going on.

Ric

Thanks, I’m still a beginner so I hadn’t made a property for it. If you want to you can look at my script, you can, but I think that it isn’t the projects problem, it’s just that I have a lot of questions! If you want to know what I am creating, it is an app that will tell you what the UTI of an app is. Yeah, I know you can just make a really simple script in script editor to do it but it is my first “real” app and this is what I am starting with. Just another problem I encountered, (hopefully, it seems it should be the last…), it is relating to drag and drop. I am using this simple command “set theApp to get id of thisApp” to find the UTI. The question is how would I find the app’s id? I keep getting this error in Console: Can’t get id of «class ocid» id «data kptr00000000E040380002000000». (error -1728). Here is the section of my script that relates to this:

		set pb to info's draggingPasteboard()
		set theURL to pb's readObjectsForClasses_options_({current application's NSURL}, missing value)'s lastObject()
		set thePath to theURL's lastPathComponent()
		set theExt to theURL's pathExtension()
		set theApp to theURL]
on concludeDragOperation_()
		log appDel
		set theID to get id of theApp
		if theID is "????" then
			set theID to "Not Applicable"
		end if

I’m not familiar with “get id”, I would do it using cocoa methods in the NSWorkspace class. You would need to add a line in the awake from nib method to get the sharedWorkspace, and then get the full path to the app and use typeOfFile_error_ to get the UTI. So like this:

on awakeFromNib()
        set ws to current application's NSWorkspace's sharedWorkspace()
        set appDel to current application's NSApp's |delegate|()
    end

        on draggingEntered_(info)
            return current application's NSDragOperationCopy
        end draggingEntered_
        
        on performDragOperation_(info)
            set pb to info's draggingPasteboard()
            set theURL to pb's readObjectsForClasses_options_({current application's NSURL}, missing value)'s lastObject()
            if theURL's pathExtension() as text is "app" then
                set thePath to ws's fullPathForApplication_(theURL's lastPathComponent())
                set theID to ws's typeOfFile_error_(thePath,missing value)
                return true
                else
                return false
            end if
        end performDragOperation_
    
    on concludeDragOperation_()
        appDel's progress's setHidden_(0)
        appDel's progress's setDoubleValue_(0)
        appDel's theUTI's setFont_(current application's NSFont's fontWithName_size_("Calibri", 20))
        showSheet()
        appDel's progress's setHidden_(1)
        appDel's theUTI's setStringValue_(theID)
    end concludeDragOperation_

Of course, theID would also have to be a property.

And I still would like to see your app – something is wrong, and it certainly would be useful to you to know how to access one script from another correctly.

Ric