Here is a simple example that shows how to enable your Adobe AIR application to accept native drag and drop operations.
This is a simple application that allows you to drag a text file into the application and then view its contents.
DragAndDropExample.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication
creationComplete="onCreationComplete()"
xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script source="DragAndDropExampleClass.as" />
<mx:TextArea top="10" right="10" bottom="10" left="251"
id="outputField" />
<mx:Text text="Drag a Text File into the Application"
width="233" height="148" top="11" left="10"/>
</mx:WindowedApplication>
DragAndDropExampleClass.as
import flash.desktop.ClipboardFormats;
import flash.desktop.DragManager;
import flash.events.NativeDragEvent;
import flash.filesystem.File;
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;
//called when app has initialized and is about to display
private function onCreationComplete():void
{
//register for the drag enter event
addEventListener(NativeDragEvent.NATIVE_DRAG_ENTER, onDragIn);
//register for the drag drop event
addEventListener(NativeDragEvent.NATIVE_DRAG_DROP, onDragDrop);
}
//called when the user drags an item into the component area
private function onDragIn(e:NativeDragEvent):void
{
//check and see if files are being drug in
if(e.clipboard.hasFormat(ClipboardFormats.FILE_LIST_FORMAT))
{
//get the array of files
var files:Array = e.clipboard.getData(ClipboardFormats.FILE_LIST_FORMAT) as Array;
//make sure only one file is dragged in (i.e. this app doesn't
//support dragging in multiple files)
if(files.length == 1)
{
//accept the drag action
DragManager.acceptDragDrop(this);
}
}
}
//called when the user drops an item over the component
private function onDragDrop(e:NativeDragEvent):void
{
//get the array of files being drug into the app
var arr:Array = e.clipboard.getData(ClipboardFormats.FILE_LIST_FORMAT) as Array;
//grab the files file
var f:File = File(arr[0]);
//create a FileStream to work with the file
var fs:FileStream = new FileStream();
//open the file for reading
fs.open(f, FileMode.READ);
//read the file as a string
var data:String = fs.readUTFBytes(fs.bytesAvailable);
//close the file
fs.close();
//display the contents of the file
outputField.text = data;
}
One of the cool things about the API, is that you can have specific components within your application accept native drag and drop operations (and not just your entire app).
As part of my Flash on the Beach Intro to AIR Session, I built a simple HTML Editor with a live preview. I have added comments to the code, and uploaded it to the on AIR tour google repository.
This example demonstrates:
Here is the code if you just want to glance at it:
Continuing my series of posts of interesting, but not too useful ActionScript tips (which I learned from studying Objective-C), did you know that you don’t have to initialize your counter variable within a for loop.
For example, this is perfectly valid:
package {
import flash.display.Sprite;
public class LoopTest extends Sprite
{
public function LoopTest()
{
var i:int = 0;
for(; i < 5; i++)
{
trace(i);
}
}
}
}
As you can see, the variable is initialized outside of the loop.
I have been studying some Objective-C in my spare time, and was reading up on Bitwise operators tonight. I came across a simple way to exchange the value of two variables using the Exclusive-OR (XOR) operator that doesn’t require creating a temporary variable.
Normally, if you wanted to exchange the value of two variables, you would have to create a temp variable to store values temporarily (which uses additional memory). For example:
In one of the projects I am working one with the Adobe AIR bus tour, I had a need to serialize instance of File class to the file system. Normally you can do this with File.writeObject(), but as the player serializer / de-serializer does not know about the File class, this would not work for me.
I came up with a simple solution that I wanted to share. Basically, you need to extend the File class and provide the meta data for it to tell the player how to serialize and de-serialize the class. This will then allow it to be serialized to the file system.
Sean Moore has just posted a useful ActionScript 2 to ActionScript 3 Migration Cheatsheet.
You can check it out here.
If you need to get a reference to a class in ActionScript 3, but only know the class name, then you can use the flash.utils.getDefinitionByName to create an instance of the class.
For example:
package
{
import flash.display.Sprite;
import flash.utils.getDefinitionByName;
public class DynamicCall extends Sprite
{
public function DynamicCall()
{
var ClassReference:Class = getDefinitionByName("String") as Class;
var s:String = (new ClassReference("foo=") as String);
trace(s);
}
}
}
This basically creates an instance of the String class, from the class name “String”. getDefinitionByName takes the entire class path, so if you wanted to create an instance of MovieClip, you would provide the entire path:
Ted Patrick has a good write-up of the new ActionScript 3 flash.util.Proxy class. What is the Proxy class? From the API docs:
The Proxy class lets you override the default behavior of ActionScript operations (such as retrieving and modifying properties) on an object.
…
The Proxy class is a replacement for the Object.__resolve and Object.addProperty features of ActionScript 2.0, which are no longer available in ActionScript 3.0. The Object.addProperty() feature allowed you to dynamically create get and set methods in ActionScript 2.0. Although ActionScript 3.0 provides get and set methods at compile time, you cannot dynamically assign one to an object unless you use the Proxy class.
If you need to get a quick view into an Object or class instance, you can use the mx.utils.ObjectUtil.toString() API included in the Flex 2 Framework.
package
{
import flash.display.Sprite;
public class ViewType extends Sprite
{
import mx.utils.ObjectUtil;
import flash.util.trace;
public function ViewType()
{
var o:Object = new Object();
o.foo = "bar";
o.arr = [{name:"Homer"}, {name:"Bart"}];
trace(ObjectUtil.toString(o));
}
}
}
This will output the object in a more human readable format like so:
(Object)#0
arr = (Array)#1
[0] (Object)#2
name = "Homer"
[1] (Object)#3
name = "Bart"
foo = "bar"
You can view the docs for the api here.
Werner Sharp (one of the Flash Player engineers responsible for E4X in the player) posted an example on the FlexCoders list showing how to dynamically iterate over XML attributes and their values using E4X in ActionScript 3. I wanted to post it here as it is useful to know, and to store for future reference.
This code below actually shows two ways to do this. The first using a for each in loop, and the second using a for loop.