Pages

Wednesday, February 4, 2015

Creating a Flex AIR Annotator app Part 2

In this part we will add functionality to import a picture to our application.

First, lets change the content of our VGroup.

The text we had before will be changed with a BigButton component (a custom component). However, well include it in a ViewStack as well. Give the stack an id of "stack" and set change event handelr to stackChange(). Add 2 NavigatorContent objects for now - one containing our BigButton control and another containing an mx:Image control with an id of imgHolder.

Now, more about the BigButton object. It has an icon property which works the same way that icons in IconButton works. We direct it to a folder.png picture in the lib folder, which is this picture:


We also give it a subtext property with a value of "Import picture". Two more unusual properties are bWidth and bHeight. Set those to 300 and 200 (the same size that drawArea is for now). Add an event listener for the click event - set handler to importPicture().

<s:VGroup width="100%" height="100%" gap="0">
<mx:HBox backgroundColor="#ccccdd" width="100%" height="68">
<custom:IconButton icon="@Embed(../lib/bubble.png)" toolTip="Annotation" enabled="true" buttonMode="true" />
<custom:IconButton icon="@Embed(../lib/bubble.png)" toolTip="Annotation" enabled="false" buttonMode="true" />
</mx:HBox>
<mx:Canvas width="100%" height="100%" horizontalScrollPolicy="on" verticalScrollPolicy="on">
<mx:Box backgroundColor="#eeeeee" width="100%" height="100%" verticalAlign="middle" horizontalAlign="center" horizontalScrollPolicy="off" verticalScrollPolicy="off">
<mx:Box id="drawArea" backgroundColor="#ffffff" width="300" height="200" horizontalScrollPolicy="off" verticalScrollPolicy="off">
<mx:ViewStack id="stack" change="stackChange();">
<s:NavigatorContent>
<custom:BigButton icon="@Embed(../lib/folder.png)" subtext="Import picture" toolTip="Open file" enabled="true" buttonMode="true" bWidth="300" bHeight="200" click="importPicture();" />
</s:NavigatorContent>
<s:NavigatorContent>
<mx:Image id="imgHolder" />
</s:NavigatorContent>
</mx:ViewStack>
</mx:Box>
</mx:Box>
</mx:Canvas>
</s:VGroup>

Lets create this BigButton component. Create a new file called BigButton.mxml. Its based off spark:Button, and has a skin of bigSkin. Add the 4 properties to the class:

<?xml version="1.0" encoding="utf-8"?>
<s:Button xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" skinClass="bigSkin">

<fx:Metadata>
[Style(name="icon",type="*")]
[Style(name="subtext",type="*")]
[Style(name="bWidth",type="*")]
[Style(name="bHeight",type="*")]
</fx:Metadata>

</s:Button>

Now create another file called bigSkin.mxml. It basically consists of a VGroup with a picture and the text in it:

<?xml version="1.0" encoding="utf-8"?>
<s:SparkSkin name="iconSkin"
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
minWidth="128" minHeight="128"
alpha.disabled="0.5">

<s:states>
<s:State name="up" />
<s:State name="over" />
<s:State name="down" />
<s:State name="disabled" />
</s:states>

<fx:Metadata>
[HostComponent("spark.components.Button")]
</fx:Metadata>

<s:Rect width="{hostComponent.getStyle(bWidth)}" height="{hostComponent.getStyle(bHeight)}" alpha.up="0" alpha.over="0.4" alpha.disabled="0">
<s:fill>
<s:SolidColor color="#ababef"/>
</s:fill>
</s:Rect>
<s:VGroup width="{hostComponent.getStyle(bWidth)}" height="{hostComponent.getStyle(bHeight)}" horizontalAlign="center" verticalAlign="middle">
<s:BitmapImage source="{hostComponent.getStyle(icon)}" top="2" right="2" left="2" bottom="2" alpha.disabled="0.5" />
<s:Label fontSize="24" color="#6666ff" text="{hostComponent.getStyle(subtext)}" />
</s:VGroup>

</s:SparkSkin>

Now go back to Main.mxml.

Create a function called importPicture(), the one thats called when the button is pressed.

Here we create a new File object, an ImageFilter, and use the files browseForOpen() method to let the user import a picture:

private function importPicture():void {
var file:File = new File();
var imageFilter:FileFilter = new FileFilter("Images", "*.jpg;*jpeg;*.gif;*.png");
file.browseForOpen("Import picture", [imageFilter]);
file.addEventListener(Event.SELECT, fileSelect);
}

The fileSelect() function, which is the event handler for files SELECT event uses a Loader class to load the image with the provided url:

private function fileSelect(evt:Event):void {
var file:File = evt.target as File;
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);
loader.load(new URLRequest(file.url));
}

The loadComplete() function takes data from the loaders content and creates a BitmapData out of it. Then the selectedIndex of stack is set to 1:

private function loadComplete(evt:Event):void {
content = evt.target.content;
bitmapData = new BitmapData(content.width, content.height, false);
bitmapData.draw(content, new Matrix(), null, null, null, true);
stack.selectedIndex = 1;
}

Now create a function called stackChange(), which is called when the selectedIndex of the stack changes. Add a conditional checking if the index is 1, if it is - set the images source to a Bitmap object with our bitmapData, and set the size of drawArea and imgHolder to size of content.

private function stackChange():void {
if (stack.selectedIndex == 1) {
imgHolder.source = new Bitmap(bitmapData);
drawArea.width = content.width;
drawArea.height = content.height;
imgHolder.width = content.width;
imgHolder.height = content.height;
}
}

And there we go.

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:custom="*"
showStatusBar="false"
creationComplete="init();" minWidth="400" minHeight="400"
width="600" height="500">

<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>

<fx:Script>
<![CDATA[
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.FocusDirection;
import flash.display.Loader;
import flash.events.Event;
import flash.filesystem.File;
import flash.filesystem.FileStream;
import flash.filters.DropShadowFilter;
import flash.geom.Matrix;
import flash.net.FileFilter;
import flash.net.URLRequest;
import flash.utils.ByteArray;
import mx.controls.Alert;
import flash.filesystem.FileMode;

private var bitmapData:BitmapData;
private var content:*;

private function init():void{
drawArea.filters = [new DropShadowFilter(4, 60, 0, 0.7, 10, 10, 1, 3)];
}

private function importPicture():void {
var file:File = new File();
var imageFilter:FileFilter = new FileFilter("Images", "*.jpg;*jpeg;*.gif;*.png");
file.browseForOpen("Import picture", [imageFilter]);
file.addEventListener(Event.SELECT, fileSelect);
}

private function fileSelect(evt:Event):void {
var file:File = evt.target as File;
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);
loader.load(new URLRequest(file.url));
}

private function loadComplete(evt:Event):void {
content = evt.target.content;
bitmapData = new BitmapData(content.width, content.height, false);
bitmapData.draw(content, new Matrix(), null, null, null, true);
stack.selectedIndex = 1;
}

private function stackChange():void {
if (stack.selectedIndex == 1) {
imgHolder.source = new Bitmap(bitmapData);
drawArea.width = content.width;
drawArea.height = content.height;
imgHolder.width = content.width;
imgHolder.height = content.height;
}
}
]]>
</fx:Script>

<s:VGroup width="100%" height="100%" gap="0">
<mx:HBox backgroundColor="#ccccdd" width="100%" height="68">
<custom:IconButton icon="@Embed(../lib/bubble.png)" toolTip="Annotation" enabled="true" buttonMode="true" />
<custom:IconButton icon="@Embed(../lib/bubble.png)" toolTip="Annotation" enabled="false" buttonMode="true" />
</mx:HBox>
<mx:Canvas width="100%" height="100%" horizontalScrollPolicy="on" verticalScrollPolicy="on">
<mx:Box backgroundColor="#eeeeee" width="100%" height="100%" verticalAlign="middle" horizontalAlign="center" horizontalScrollPolicy="off" verticalScrollPolicy="off">
<mx:Box id="drawArea" backgroundColor="#ffffff" width="300" height="200" horizontalScrollPolicy="off" verticalScrollPolicy="off">
<mx:ViewStack id="stack" change="stackChange();">
<s:NavigatorContent>
<custom:BigButton icon="@Embed(../lib/folder.png)" subtext="Import picture" toolTip="Open file" enabled="true" buttonMode="true" bWidth="300" bHeight="200" click="importPicture();" />
</s:NavigatorContent>
<s:NavigatorContent>
<mx:Image id="imgHolder" />
</s:NavigatorContent>
</mx:ViewStack>
</mx:Box>
</mx:Box>
</mx:Canvas>
</s:VGroup>

</s:WindowedApplication>

Thanks for reading!

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.