Wednesday, February 22, 2012

Creating a Flex AIR Annotator app: Part 3

In this tutorial we will add new stuff to our toolbar.

I am going to use 6 icons of the same style for the program. These are new.png, move.png, draw.png, bubble.png, cut.png and save.png.

Put them all in your lib folder:








You can see that these icons are smaller than the temporary placeholders we have in their place right now. So go to iconSkin.mxml and change the sizes in it this way:

<?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>

In the main mxml file, find the HBox that contains the IconButtons and set its height to 52:

<mx:HBox backgroundColor="#ccccdd" width="100%" height="52">

Now delete those IconButtons and put these ones in their place:

<custom:IconButton icon="@Embed('../lib/new.png')" toolTip="New" enabled="true" buttonMode="true" />
<custom:IconButton icon="@Embed('../lib/move.png')" toolTip="Move" enabled="true" buttonMode="true" click="toolbarStack.selectedIndex=0;" />
<custom:IconButton icon="@Embed('../lib/draw.png')" toolTip="Draw" enabled="true" buttonMode="true" click="toolbarStack.selectedIndex=1;" />
<custom:IconButton icon="@Embed('../lib/bubble.png')" toolTip="Annotation" enabled="true" buttonMode="true" click="toolbarStack.selectedIndex=2;" />
<custom:IconButton icon="@Embed('../lib/cut.png')" toolTip="Cut" enabled="true" buttonMode="true" click="toolbarStack.selectedIndex=3;" />
<custom:IconButton icon="@Embed('../lib/save.png')" toolTip="Save" enabled="true" buttonMode="true" />

You can see that I set click event listeners for some of these buttons and made tem change selectedIndex of a viewstack called toolbarStack, which we will create shortly.

Right after these buttons, add a ViewStack object, with an id of toolbarStack.

Inside of it, there are 4 NavigatorContent objects. Those will be the options for Move, Draw, Annotation and Cut tools.

The Move one just contains a label with tool description, the Draw one, however, has ToggleButtonBar and ColorPicker objects in it. Set the ToggleButtonBar's dataProvider to toolbarToggle array collection.

The Annotation NavigatorContent contains a text inptu and a color picker. The last one, Cut, contains a label and a button.

The whole viewstack looks like this:

<mx:ViewStack id="toolbarStack" width="100%" height="100%">
<s:NavigatorContent>
<s:VGroup width="100%" height="44" top="4">
<s:Label fontSize="18" color="#333333">Selected: Move</s:Label>
<s:Label>Click and hold your mouse on annotations to move them.</s:Label>
</s:VGroup>
</s:NavigatorContent>
<s:NavigatorContent>
<s:VGroup width="100%" height="44" top="4">
<s:Label fontSize="18" color="#333333">Selected: Draw</s:Label>
<s:HGroup>
<mx:ToggleButtonBar dataProvider="{toolbarToggle}" width="100" />
<mx:ColorPicker />
</s:HGroup>
</s:VGroup>
</s:NavigatorContent>
<s:NavigatorContent>
<s:VGroup width="100%" height="44" top="4">
<s:Label fontSize="18" color="#333333">Selected: Annotation</s:Label>
<s:HGroup>
<s:TextInput width="180" text="Insert text here" />
<mx:ColorPicker />
</s:HGroup>
</s:VGroup>
</s:NavigatorContent>
<s:NavigatorContent>
<s:VGroup width="100%" height="44" top="4">
<s:Label fontSize="18" color="#333333">Selected: Cut</s:Label>
<s:HGroup>
<s:Label>Select an area to crop.</s:Label>
<s:Button label="Crop selected area" />
</s:HGroup>
</s:VGroup>
</s:NavigatorContent>
</mx:ViewStack>

Now, let's declare this toolbarToggle array collection. It is an array of 4 objects that have their "icon" properties set to 4 icons in the lib folder.

<fx:Declarations>
<mx:ArrayCollection id="toolbarToggle">
<fx:Object icon="@Embed('../lib/ic_pen.png')" />
<fx:Object icon="@Embed('../lib/ic_ellipse.png')"/>
<fx:Object icon="@Embed('../lib/ic_rect.png')"/>
<fx:Object icon="@Embed('../lib/ic_line.png')"/>
</mx:ArrayCollection>
</fx:Declarations>

Add these icons to the lib folder: ic_pen.png, ic_ellipse.png, ic_rect.png and ic_line.png:





And that's all for today.

Full code:

<?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="700" minHeight="400"
   width="700" height="500">

<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;
drawGroup.width = content.width;
drawGroup.height = content.height;
}
}
]]>
</fx:Script>

<fx:Declarations>
<mx:ArrayCollection id="toolbarToggle">
<fx:Object icon="@Embed('../lib/ic_pen.png')" />
<fx:Object icon="@Embed('../lib/ic_ellipse.png')"/>
<fx:Object icon="@Embed('../lib/ic_rect.png')"/>
<fx:Object icon="@Embed('../lib/ic_line.png')"/>
</mx:ArrayCollection>
</fx:Declarations>

<s:VGroup width="100%" height="100%" gap="0">
<mx:HBox backgroundColor="#ccccdd" width="100%" height="52">
<custom:IconButton icon="@Embed('../lib/new.png')" toolTip="New" enabled="true" buttonMode="true" />
<custom:IconButton icon="@Embed('../lib/move.png')" toolTip="Move" enabled="true" buttonMode="true" click="toolbarStack.selectedIndex=0;" />
<custom:IconButton icon="@Embed('../lib/draw.png')" toolTip="Draw" enabled="true" buttonMode="true" click="toolbarStack.selectedIndex=1;" />
<custom:IconButton icon="@Embed('../lib/bubble.png')" toolTip="Annotation" enabled="true" buttonMode="true" click="toolbarStack.selectedIndex=2;" />
<custom:IconButton icon="@Embed('../lib/cut.png')" toolTip="Cut" enabled="true" buttonMode="true" click="toolbarStack.selectedIndex=3;" />
<custom:IconButton icon="@Embed('../lib/save.png')" toolTip="Save" enabled="true" buttonMode="true" />
<mx:ViewStack id="toolbarStack" width="100%" height="100%">
<s:NavigatorContent>
<s:VGroup width="100%" height="44" top="4">
<s:Label fontSize="18" color="#333333">Selected: Move</s:Label>
<s:Label>Click and hold your mouse on annotations to move them.</s:Label>
</s:VGroup>
</s:NavigatorContent>
<s:NavigatorContent>
<s:VGroup width="100%" height="44" top="4">
<s:Label fontSize="18" color="#333333">Selected: Draw</s:Label>
<s:HGroup>
<mx:ToggleButtonBar dataProvider="{toolbarToggle}" width="100" />
<mx:ColorPicker />
</s:HGroup>
</s:VGroup>
</s:NavigatorContent>
<s:NavigatorContent>
<s:VGroup width="100%" height="44" top="4">
<s:Label fontSize="18" color="#333333">Selected: Annotation</s:Label>
<s:HGroup>
<s:TextInput width="180" text="Insert text here" />
<mx:ColorPicker />
</s:HGroup>
</s:VGroup>
</s:NavigatorContent>
<s:NavigatorContent>
<s:VGroup width="100%" height="44" top="4">
<s:Label fontSize="18" color="#333333">Selected: Cut</s:Label>
<s:HGroup>
<s:Label>Select an area to crop.</s:Label>
<s:Button label="Crop selected area" />
</s:HGroup>
</s:VGroup>
</s:NavigatorContent>
</mx:ViewStack>
</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>
<s:Group id="drawGroup">
<s:SpriteVisualElement id="drawSprite" width="100%" height="100%" />
</s:Group>
<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