Wednesday, January 25, 2012

Creating a Flex AIR Screenshot app: Part 4

Today we continue making our program - we start adding functionality a little by little.

In this tutorial we will add some content to the "crop" stage. When the user is cropping an image, the whole site should be displayed in the application somehow. This is done using the HtmlLoader class - in Flex we use HTML control.

Go to the crop NavigatorContent object and add a HTML with id cropHTML:

<s:NavigatorContent id="crop">
<mx:HTML width="100%" height="100%" id="cropHTML" />
</s:NavigatorContent>

Right now the content Box object has property paddingTop set to 20 - take that away and set this parameter for VGroup in the loadpage NavigatorContent instead. Give the content Box object an id of contentBox.

Find the "Browse local" buton and set its click event handler to doBrose() function. Set the "Crop" button's click event handler to goCrop().

Now, the big VGroup looks like this:

<s:VGroup width="100%" height="100%" gap="0">
<mx:HBox backgroundColor="#333333" height="46" width="100%" paddingTop="10" paddingLeft="10">
<s:Label id="headStep" text="{headerTitles.getItemAt(stack.selectedIndex).step}" />
<s:Label id="headDesc" text="{headerTitles.getItemAt(stack.selectedIndex).description}" />
</mx:HBox>
<mx:Box backgroundColor="#666666" width="100%" height="100%" id="contentBox" horizontalAlign="center">
<mx:ViewStack id="stack" change="changeState();">
<s:NavigatorContent id="loadpage">
<s:VGroup width="100%" horizontalAlign="center" paddingTop="20">
<s:Label styleName="descriptionText">Enter the link to the page:</s:Label>
<s:HGroup>
<s:TextInput width="250" id="urlInput" /><s:Button label="Browse local..." click="doBrowse();" />
</s:HGroup>
<s:HGroup>
<s:Button label="Take screenshot" />
<s:Button label="Crop specific area" click="goCrop();" />
</s:HGroup>
</s:VGroup>
</s:NavigatorContent>

<s:NavigatorContent id="screenshotsettings">

</s:NavigatorContent>

<s:NavigatorContent id="crop">
<mx:HTML width="100%" height="100%" id="cropHTML" />
</s:NavigatorContent>

<s:NavigatorContent id="cropsettings">

</s:NavigatorContent>

<s:NavigatorContent id="export">

</s:NavigatorContent>
</mx:ViewStack>
</mx:Box>
</s:VGroup>

Now, go to the root tags of the application and set width and height of the window to 450 and 300, also set its creationComplete event listener to init():

<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" showStatusBar="false"
   width="450" height="300" creationComplete="init();">

Now it is time to add the Script tags to our code!

Declare one variable called urlString first. It will hold the url the user specified:

private var urlString:String;

Let's add the functions we mentioned one by one.

First goes the init() function. Here, for now we just add one listener for the WINDOW_RESIZE event and make it call onResize:

private function init():void {
addEventListener(FlexNativeWindowBoundsEvent.WINDOW_RESIZE, onResize);
}

The onResize() function checks if the selectedChild of the view stack is crop, and if it is - update width and height of the cropHTML object. This is needed because the HTML component doesn't scale itself.

private function onResize(evt:Event):void {
if (stack.selectedChild == crop) {
cropHTML.width = contentBox.width;
cropHTML.height = contentBox.height;
}
}

The doBrowse() function, which is called when "Browse local" is pressed, has to open a new browsing window, where the user can look up and select a file. Put that file's path into the text field:

private function doBrowse():void{
var file:File = new File();
file.addEventListener(Event.SELECT, browseSelect);
file.browseForOpen("Load a webpage");

function browseSelect(evt:Event):void {
urlInput.text = file.nativePath;
}
}

The goCrop() function will set the selectedChild of the viewstack to crop and set urlString's value:

private function goCrop():void {
stack.selectedChild = crop;
urlString = urlInput.text;
}

One function left - changeState() - it is called every time the view stack changes state. Right now we only have 2 states working - loadpage and crop. When the state is set to crop, the cropHTML object's htmlLoader should load the webpage using the url provided, the size of the HTML object should also be updated. The window itself should be maximized for more user convenience (since the initial size is so small), and the horizontalAlign property of the contentBox should be set to left. When the state is loadpage, though - horizontalAlign should be set to center.

private function changeState():void {
if (stack.selectedChild == loadpage) {
contentBox.setStyle("horizontalAlign", "center");
}
if (stack.selectedChild == crop) {
maximize();
contentBox.setStyle("horizontalAlign", "left");
cropHTML.htmlLoader.load(new URLRequest(urlString));
cropHTML.width = contentBox.width;
cropHTML.height = contentBox.height;
}
}

And this concludes today's tutorial.

Full code so far:

<?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" showStatusBar="false"
   width="450" height="300" creationComplete="init();">
   
   
<fx:Declarations>
<mx:ArrayCollection id="headerTitles">
<fx:Object step="Step one:" description="load a web page." />
<fx:Object step="Step two:" description="set your export preferences." />
<fx:Object step="Step two:" description="select the area you wish to crop." />
<fx:Object step="Step three:" description="set your export preferences for the cropped image." />
<fx:Object step="Final step:" description="please wait while your images are being expored." />
</mx:ArrayCollection>
</fx:Declarations>

<fx:Style>
@namespace s "library://ns.adobe.com/flex/spark";
@namespace mx "library://ns.adobe.com/flex/mx";

.descriptionText{
fontSize: 24;
color: #fff;
}

#headStep{
fontSize: 30;
fontWeight: bold;
color: #ffffbb;
}

#headDesc{
fontSize: 30;
color: #ffffff;
}
</fx:Style>

<fx:Script>
<![CDATA[
import flash.events.Event;
import flash.filesystem.File;
import flash.net.URLRequest;
import mx.events.FlexNativeWindowBoundsEvent;

private var urlString:String;

private function init():void {
addEventListener(FlexNativeWindowBoundsEvent.WINDOW_RESIZE, onResize);
}

private function doBrowse():void{
var file:File = new File();
file.addEventListener(Event.SELECT, browseSelect);
file.browseForOpen("Load a webpage");

function browseSelect(evt:Event):void {
urlInput.text = file.nativePath;
}
}

private function goCrop():void {
stack.selectedChild = crop;
urlString = urlInput.text;
}

private function changeState():void {
if (stack.selectedChild == loadpage) {
contentBox.setStyle("horizontalAlign", "center");
}
if (stack.selectedChild == crop) {
maximize();
contentBox.setStyle("horizontalAlign", "left");
cropHTML.htmlLoader.load(new URLRequest(urlString));
cropHTML.width = contentBox.width;
cropHTML.height = contentBox.height;
}
}

private function onResize(evt:Event):void {
if (stack.selectedChild == crop) {
cropHTML.width = contentBox.width;
cropHTML.height = contentBox.height;
}
}
]]>
</fx:Script>
   
<s:VGroup width="100%" height="100%" gap="0">
<mx:HBox backgroundColor="#333333" height="46" width="100%" paddingTop="10" paddingLeft="10">
<s:Label id="headStep" text="{headerTitles.getItemAt(stack.selectedIndex).step}" />
<s:Label id="headDesc" text="{headerTitles.getItemAt(stack.selectedIndex).description}" />
</mx:HBox>
<mx:Box backgroundColor="#666666" width="100%" height="100%" id="contentBox" horizontalAlign="center">
<mx:ViewStack id="stack" change="changeState();">
<s:NavigatorContent id="loadpage">
<s:VGroup width="100%" horizontalAlign="center" paddingTop="20">
<s:Label styleName="descriptionText">Enter the link to the page:</s:Label>
<s:HGroup>
<s:TextInput width="250" id="urlInput" /><s:Button label="Browse local..." click="doBrowse();" />
</s:HGroup>
<s:HGroup>
<s:Button label="Take screenshot" />
<s:Button label="Crop specific area" click="goCrop();" />
</s:HGroup>
</s:VGroup>
</s:NavigatorContent>

<s:NavigatorContent id="screenshotsettings">

</s:NavigatorContent>

<s:NavigatorContent id="crop">
<mx:HTML width="100%" height="100%" id="cropHTML" />
</s:NavigatorContent>

<s:NavigatorContent id="cropsettings">

</s:NavigatorContent>

<s:NavigatorContent id="export">

</s:NavigatorContent>
</mx:ViewStack>
</mx:Box>
</s:VGroup>

</s:WindowedApplication>

Thanks for reading!

No comments:

Post a Comment