Drag and Droop

The database has been created and an interface class (DAO) has been created.  Now I need to get some data into the system. To do that I need some kind of data input screen that will take in text and multimedia files (images, videos, etc.)  In the interests of making things easy on the user I didn’t want to use an open file dialog.  I find that they are unpleasant to use, especially for non-technical users.  Drag and drop is much more intuitive.

According to the hype, it’s very easy to drag and drop files from a user’s desktop into an AIR application. I figured a five minute Google would give me a dozen or so examples of how to do it.  Well, yes and no.  There were many examples (875,000 returns on AIR drag and drop), but most were written for the Beta versions of AIR.  It seemed like every sample I found used the DragManager object which (I found out later) was transformed into the NativeDragManager object when AIR was released.  Other samples were so complicated that peeling back the layers to a simple sample took more time that it was worth.

What I need to do is really quite simple.  Have an image field onto which a user can drag and drop an image file.  Once the file was dropped onto the field I want the image to change to the new one and the file contents to be available in binary form.  The last requirement is so the file can be uploaded to the database.

Step 1 – Create a target for the operation – an image field:

<mx:Image x="10" y="10" id="displayImage" source="DropHere.jpg"/>

Step 2 – Add a listener for both the drag and the drop operations. This was done by adding a simple function that is called on the createComplete event of the canvas:

public function initDrop():void{
//Listeners to manage the drop of files on the first panel
 displayImage.addEventListener(NativeDragEvent.NATIVE_DRAG_ENTER,acceptDrag);
 displayImage.addEventListener(NativeDragEvent.NATIVE_DRAG_DROP,dragDrop);
}

Step 3 – Add some code to allow the drag operation. Nothing too complicated here; its just a function that allows the drag operation into the image field:

//Accept drag and drop on the first panel
public function acceptDrag(event:NativeDragEvent):void{
        NativeDragManager.acceptDragDrop(displayImage);
}

Step 4 – Add some code to handle the drop operation.  Here I want to change the image to the new file and to put the contents of the file into a byte array.  To prove to myself that it was working, I echoed the file size to the screen.  This will be replaced later with a call to the DAO for a database update:

import flash.filesystem.File;
private var imageBytes:ByteArray = new ByteArray();  //the byte array can not be null!!!

…..

//On drop collect the files
public function dragDrop(event:NativeDragEvent):void{
        var imageList:Array = event.clipboard.getData(ClipboardFormats.FILE_LIST_FORMAT) as Array;
        var droppedFile:File = imageList[0];

         //load the file into the image
        displayImage.source= droppedFile.url;                             

        //get the byte array for the image
        var fileStream:FileStream = new FileStream();
        fileStream.open(droppedFile, FileMode.READ);                         

        fileStream.readBytes(imageBytes);
        fileSize.text = imageBytes.length.toString();             

   }

There are a couple of things to note about the dragDrop function.  First the result of the drag and drop is always an array of the files.  This is because the system allows you to drag more than one file at a time (very useful in some circumstances).  I took the cheap and cheesy route of just using the first element in the array.

Second I’m not using a Loader object to change the image contents as is suggested on many web pages.  I tried this at first and the image was not replaced, but instead the second image was overlaid on top.  I fiddled around a bit with the image layers but I couldn’t quite get it to work properly.  Simply re-setting the image source was a simple solution to the problem.

There you go.  Not much to it, but it works well and functions properly with the 1.0 release of AIR.

I split this bit of the application into a separate app so you can download it without all of the rest of the overhead.  You can find it here.