Tuesday, February 14, 2012

Creating a Flex AIR Screenshot app: Part 24

In this tutorial we will work on exporting the cropped image.

Go to the cropsettings NavigatorContent and replace the existing placeholder Image object with 2 radio buttons (cropRadioJPEG and cropRadioPNG), a slider (cropQualitySlider) and 2 buttons - Back and Export. This is somewhat similar to the content displayed in the screenshot settings window.

Set the Back button's click event handler to cropBack() and Export button's click event handler to startExportCrop():

<s:NavigatorContent id="cropsettings">
<s:VGroup width="100%" horizontalAlign="center" paddingTop="20">
<s:Label styleName="descriptionText2">Export as:</s:Label>
<s:HGroup>
<s:RadioButton id="cropRadioJPEG" label="JPEG" groupName="screenshotFormat" change="formatChange('JPEG');" styleName="descriptionText2" /> 
<s:RadioButton id="cropRadioPNG" label="PNG" groupName="screenshotFormat" change="formatChange('PNG');" styleName="descriptionText2" /> 
</s:HGroup>
<s:Label styleName="descriptionText2">Quality:</s:Label>
<s:HSlider id="cropQualitySlider" width="310" minimum="1" maximum="100" liveDragging="true" enabled="{pref_format=='JPEG'}" value="@{pref_quality}" />

<s:Label/>

<s:HGroup>
<s:Button label="Back" click="cropBack();" />
<s:Button label="Export" click="startExportCrop();" />
</s:HGroup>
</s:VGroup>
</s:NavigatorContent>

In changeState() function change the contents of the final condition to this:

if (stack.selectedChild == cropsettings) {
contentBox.setStyle("horizontalAlign", "center");
loadCropSettings();
}

Now let's do all the functions that havent yet been created, but are already being called in our code.

The loadCropSettings() function - sets values for cropRadioJPEG and cropRadioPNG according to pref_format:

private function loadCropSettings():void {
if (pref_format == "JPEG") {
cropRadioJPEG.selected = true;
} else {
cropRadioPNG.selected = true;
}
}

The cropBack() function - returns to first page, removes tempHTML, calls saveCropSettings():

private function cropBack():void {
saveCropSettings();
stack.selectedChild = loadpage;
removeElement(tempHTML);
}

The saveCropSettings() function - saves all preference values that are related to cropping:

private function saveCropSettings():void {
preferences.data.format = pref_format;
preferences.data.quality = pref_quality;
preferences.flush();
}

Now, the startExportCrop() function, which is a bit more complex than the other ones. Here we declare 4 variables - encoder, byteArray, file and fileStream. Check pref_format value to properly set encoder's class (JPEGEncoder or PNGEncoder)

Then we encode the bitmap data and set the results as the byteArray value. After that, we create a File object, call browseForSave() and add a listener for the SELECT event of the file. When file location is selected, we add the needed extension to the nativePath, create a filestream and write bytes from the bytearray into the file. Then we call cropBack() to return to the first page:

private function startExportCrop():void {
var encoder:IImageEncoder;
var byteArray:ByteArray;
var file:File;
var fileStream:FileStream;

if (pref_format == "JPEG") {
encoder = new JPEGEncoder(pref_quality);
}
if (pref_format == "PNG") {
encoder = new PNGEncoder();
}

byteArray = encoder.encode(cropBD);
file = File.documentsDirectory.resolvePath("crop." + pref_format);
file.browseForSave("Save cropped image");
file.addEventListener(Event.SELECT, saveSelect);

function saveSelect():void {
file.nativePath += "." + pref_format;
fileStream = new FileStream();
fileStream.open(file, FileMode.WRITE);
fileStream.writeBytes(byteArray);
fileStream.close();
cropBack();
}
}

And there we go!

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:custom="*"
                       xmlns:mx="library://ns.adobe.com/flex/mx" showStatusBar="false"
   width="550" height="600" creationComplete="init();">
   
   
<fx:Declarations>
<mx:ArrayCollection id="headerTitles">
<fx:Object step="Step one:" description="load a web page." />
<fx:Object step="Loading..." description="please wait." />
<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="Exporting:" description="please wait." />
</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;
}

.descriptionText2{
fontSize: 16;
color: #fff;
}

.settingText{
fontSize: 16;
color: #fff;
}

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

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

<fx:Script>
<![CDATA[
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.filesystem.File;
import flash.filesystem.FileStream;
import flash.filters.GlowFilter;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.net.URLRequest;
import flash.utils.ByteArray;
import flash.utils.Timer;
import mx.controls.HTML;
import mx.core.FlexHTMLLoader;
import mx.events.FlexNativeWindowBoundsEvent;
import mx.controls.Alert;
import mx.events.ResizeEvent;
import mx.graphics.codec.IImageEncoder;
import mx.graphics.codec.JPEGEncoder;
import mx.graphics.codec.PNGEncoder;
import mx.graphics.ImageSnapshot;
import spark.components.Scroller;
import spark.primitives.BitmapImage;
import flash.filesystem.FileMode;
import mx.managers.PopUpManager;

[Bindable]
private var urlString:String;
private var tempHTML:HTML = new HTML();

private var preferences:SharedObject = SharedObject.getLocal("kirshotPreferences");
[Bindable]
private var pref_screensizes:Array;
[Bindable]
private var pref_format:String;
[Bindable]
private var pref_quality:int;
[Bindable]
private var pref_folder:Boolean;
[Bindable]
private var pref_destination:String;
[Bindable]
private var exportText:String;
private var screenGo:String;
private var drawing:Boolean = false;
private var dragging:Boolean = false;
private var resizing:Boolean = false;
private var inDragArea:Boolean = false;
private var inResizeArea:Boolean = false;
private var drawingRect:Array = [];
private var dragOffsetX:int = 0;
private var dragOffsetY:int = 0;
[Bindable]
private var drawPreviousX:int = 0;
[Bindable]
private var drawPreviousY:int = 0;
private var resizeDirection:String;
[Bindable]
private var canExportCrop:Boolean = false;

[Embed(source="../lib/cursor_crop.png")]
private var cropCursor:Class;

[Embed(source="../lib/cursor_move.png")]
private var dragCursor:Class;

[Embed(source="../lib/cursor_resize_vertical.png")]
private var resizeVerticalCursor:Class;
[Embed(source="../lib/cursor_resize_horizontal.png")]
private var resizeHorizontalCursor:Class;
[Embed(source="../lib/cursor_resize_diag1.png")]
private var resizeDiag1Cursor:Class;
[Embed(source="../lib/cursor_resize_diag2.png")]
private var resizeDiag2Cursor:Class;

private var screenSettings:Array;
private var cropBD:BitmapData;

private function init():void {
//preferences.data.firsttime = null;

// Set preferences if loaded for the first time
if (preferences.data.firsttime == null) {
preferences.data.firsttime = true;
preferences.data.screensizes = [ 
{ checked:true },
{ checked:true, w:1280, h:1024 },
{ checked:true, w:1280, h:800 },
{ checked:true, w:1024, h:768 },
{ checked:false, w:"", h:"" },
{ checked:false, w:"", h:"" },
{ checked:false, w:"", h:"" } ];
preferences.data.format = "JPEG";
preferences.data.quality = 100;
preferences.data.folder = true;
preferences.data.destination = File.documentsDirectory.nativePath;
preferences.flush();
}

// Set preferences loaded from local storage
pref_screensizes = preferences.data.screensizes;
pref_format = preferences.data.format;
pref_quality = preferences.data.quality;
pref_folder = preferences.data.folder;
pref_destination = preferences.data.destination;

addElement(tempHTML);
removeElement(tempHTML);
}

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 goScreenshot(screen:String):void {
screenGo = screen;
stack.selectedChild = screenshotloading;
urlString = urlInput.text;

addElement(tempHTML);
tempHTML.htmlLoader.useCache = false;
tempHTML.horizontalScrollPolicy = "off";
tempHTML.verticalScrollPolicy = "off";
tempHTML.visible = false;
tempHTML.addEventListener(Event.COMPLETE, onTempLoad);
tempHTML.htmlLoader.load(new URLRequest(urlString));
}

private function onTempLoad(evt:Event):void {
tempHTML.removeEventListener(Event.COMPLETE, onTempLoad);
if(screenGo=="screenshot"){
stack.selectedChild = screenshotsettings;
}
if (screenGo == "crop") {
if(tempHTML.contentWidth <= 4096 && tempHTML.contentHeight <= 4096){
var t:Timer = new Timer(1000, 1);
t.addEventListener(TimerEvent.TIMER_COMPLETE, tComplete);
t.start();
tempHTML.width = tempHTML.contentWidth;
tempHTML.height = tempHTML.contentHeight;
function tComplete(evt:TimerEvent):void {
stack.selectedChild = crop;
}
}else {
Alert.show("Dimensions of a screenshot cannot exceed 4096 pixels.", "Sorry...");
stack.selectedChild = loadpage;
}
}
}

private function cancelLoading():void {
tempHTML.removeEventListener(Event.COMPLETE, onTempLoad);
tempHTML.cancelLoad();
stack.selectedChild = loadpage;
removeElement(tempHTML);
}

private function screenshotBack():void {
saveScreenshotSettings();
stack.selectedChild = loadpage;
removeElement(tempHTML);
}

private function changeState():void {
if (stack.selectedChild == loadpage) {
contentBox.setStyle("horizontalAlign", "center");
urlInput.text = urlString;
tempHTML.width = 1;
tempHTML.height = 1;
tempHTML.removeEventListener(Event.COMPLETE, onTempLoad);
tempHTML.htmlLoader.loadString("<html></html>");
}
if (stack.selectedChild == crop) {
maximize();
contentBox.setStyle("horizontalAlign", "left");
var bd:BitmapData = new BitmapData(tempHTML.width, tempHTML.height, false);
bd.draw(tempHTML);
var b:Bitmap = new Bitmap(bd, "auto", true);
cropHTML.source = b;
drawArea.addEventListener(MouseEvent.MOUSE_DOWN, drawDown);
addEventListener(MouseEvent.MOUSE_UP, drawUp);
drawArea.addEventListener(MouseEvent.MOUSE_MOVE, drawMove);
displayWidth.filters = [new GlowFilter(0xffffff, 1, 3, 3, 50)];
displayHeight.filters = [new GlowFilter(0xffffff, 1, 3, 3, 50)];
drawArea.addEventListener(MouseEvent.MOUSE_OVER, drawOver);
drawArea.addEventListener(MouseEvent.MOUSE_OUT, drawOut);
displayHeight.text = "";
displayWidth.text = "";
cropDraw.graphics.clear();
canExportCrop = false;
}
if (stack.selectedChild == screenshotsettings) {
screenSettings = [set2, set3, set4, set5, set6, set7];
contSize.text = "Full size (" + tempHTML.contentWidth + "x" + tempHTML.contentHeight + ")";
loadScreenshotSettings();
}
if (stack.selectedChild == cropsettings) {
contentBox.setStyle("horizontalAlign", "center");
loadCropSettings();
}
}

private function loadScreenshotSettings():void {
set1checkbox.selected = pref_screensizes[0].checked;

for (var i:int = 0; i < screenSettings.length; i++) {
screenSettings[i].checked = pref_screensizes[i + 1].checked;
screenSettings[i].w = pref_screensizes[i + 1].w;
screenSettings[i].h = pref_screensizes[i + 1].h;
}

if (pref_format == "JPEG") {
screenRadioJPEG.selected = true;
} else {
screenRadioPNG.selected = true;
}
}

private function saveScreenshotSettings():void {
pref_screensizes[0].checked = set1checkbox.selected;

for (var i:int = 0; i < screenSettings.length; i++) {
pref_screensizes[i + 1].checked = screenSettings[i].checked;
pref_screensizes[i + 1].w = screenSettings[i].w;
pref_screensizes[i + 1].h = screenSettings[i].h;
}

if (screenRadioJPEG.selected == true) {
pref_format == "JPEG";
} else {
pref_format == "PNG";
}

preferences.data.screensizes = pref_screensizes;
preferences.data.format = pref_format;
preferences.data.quality = pref_quality;
preferences.data.folder = pref_folder;
preferences.data.destination = pref_destination;
preferences.flush();
}

private function formatChange(newformat:String):void {
pref_format = newformat;
}

private function startExportScreenshot():void {
var canExport:Boolean = true;

for (var i:int = 0; i < screenSettings.length; i++) {
if (screenSettings[i].checked && ((screenSettings[i].w == "" || screenSettings[i].w == 0) || (screenSettings[i].h == "" || screenSettings[i].h == 0))) {
canExport = false;
}
}

if (canExport) {
if ((pref_folder && folderField.text != "") || !pref_folder) {
saveScreenshotSettings();
exportScreen();
}else {
Alert.show("Folder name should not be blank!", "Oops...");
}
}else {
Alert.show("One or more selected screen sizes are not entered or are invalid!", "Oops...");
}
}

private function screenshotDestination():void {
var newDestination:File = new File(pref_destination);
newDestination.browseForDirectory("Select directory");
newDestination.addEventListener(Event.SELECT, destinationSelect);

function destinationSelect(evt:Event):void {
pref_destination = newDestination.nativePath;
}
}

private function exportScreen():void {
var encoder:IImageEncoder;
var bd:BitmapData;
var byteArray:ByteArray;
var folderName:String = (pref_folder)?(folderField.text):("");
var fileName:String;
var file:File;
var fileStream:FileStream;
var screensToExport:Array = [];
stack.selectedChild = export;

if (pref_format == "JPEG") {
encoder = new JPEGEncoder(pref_quality);
}
if (pref_format == "PNG") {
encoder = new PNGEncoder();
}

// add full-size screen to array if checked
if (pref_screensizes[0].checked) {
screensToExport = [ { w:tempHTML.contentWidth, h: tempHTML.contentHeight, full:true} ];
}

// add the rest screens to array if checked
for (var i:int = 0; i < screenSettings.length; i++) {
if (pref_screensizes[i + 1].checked) {
screensToExport.push( { w: pref_screensizes[i + 1].w, h:pref_screensizes[i + 1].h } );
}
}

// if nothing is checked, go to first page and stop code
if (screensToExport.length == 0) {
removeElement(tempHTML);
stack.selectedChild = loadpage;
return;
}

// create a timer that repeats itself as many times as many items there are in the array
var timer:Timer = new Timer(2000, screensToExport.length);
timer.addEventListener(TimerEvent.TIMER, onTimer);
// set sizes to the first size of the array
if (screensToExport[0].full) {
tempHTML.horizontalScrollPolicy = "off";
tempHTML.verticalScrollPolicy = "off";
}else {
tempHTML.horizontalScrollPolicy = "auto";
tempHTML.verticalScrollPolicy = "auto";
}
if(screensToExport[0].h <= 4096 && screensToExport[0].w <= 4096){
tempHTML.height = screensToExport[0].h;
tempHTML.width = screensToExport[0].w;
}
updateExportText(screensToExport[0].w, screensToExport[0].h, 1, screensToExport.length);
timer.start();

function onTimer(evt:TimerEvent):void {
// do export for the current size
if(screensToExport[timer.currentCount-1].h <= 4096 && screensToExport[timer.currentCount-1].w <= 4096){
timer.stop();
doExport();
timer.start();
}else {
Alert.show("Cannot export " + screensToExport[timer.currentCount-1].w + "x" + screensToExport[timer.currentCount-1].h + " - dimensions of a screenshot cannot extend 4096.","Sorry");
}
// change the size if this was not the last size in the array
if (timer.currentCount != screensToExport.length) {
tempHTML.horizontalScrollPolicy = "auto";
tempHTML.verticalScrollPolicy = "auto";
if(screensToExport[timer.currentCount].h <= 4096 && screensToExport[timer.currentCount].w <= 4096){
tempHTML.height = screensToExport[timer.currentCount].h;
tempHTML.width = screensToExport[timer.currentCount].w;
}
updateExportText(screensToExport[timer.currentCount].w, screensToExport[timer.currentCount].h, timer.currentCount+1, screensToExport.length);
}else {
// if it was the last size in the array, return to first page
timer.stop();
removeElement(tempHTML);
stack.selectedChild = loadpage;
}
}

function doExport():void {
bd = new BitmapData(tempHTML.width, tempHTML.height, false);
bd.draw(tempHTML, null, null, null, null, true);
byteArray = encoder.encode(bd);
fileName = pref_destination + File.separator + folderName + File.separator + tempHTML.width + "x" + tempHTML.height + "." + pref_format;
file = new File(fileName);
fileStream = new FileStream();
fileStream.open(file, FileMode.WRITE);
fileStream.writeBytes(byteArray);
fileStream.close();
}

function updateExportText(w:int, h:int, current:int, total:int):void {
exportText = "Exporting " + w + "x" + h + "." + pref_format + " (" + current + "/" + total + ")";
}
}

private function drawDown(evt:MouseEvent):void {
if(!inDragArea && !inResizeArea){
drawing = true;
drawingRect = [evt.target.mouseX, evt.target.mouseY, 0, 0];
drawPreviousX = evt.target.mouseX;
drawPreviousY = evt.target.mouseY;
drawRectangle();
}
if (inDragArea && !inResizeArea) {
dragging = true;
dragOffsetX = evt.target.mouseX - drawingRect[0];
dragOffsetY = evt.target.mouseY - drawingRect[1];
}
if (inResizeArea) {
resizing = true;
setResizingCoordinates();
}
}

private function drawUp(evt:MouseEvent):void{
drawing = false;
dragging = false;
resizing = false;
}

private function drawMove(evt:MouseEvent):void{
if (drawing) {
// bottom - right
if (evt.target.mouseX > drawPreviousX  && evt.target.mouseY > drawPreviousY) {
drawingRect[0] = drawPreviousX;
drawingRect[1] = drawPreviousY;
drawingRect[2] = evt.target.mouseX - drawPreviousX;
drawingRect[3] = evt.target.mouseY - drawPreviousY;
drawRectangle();
}
// bottom - left
if (evt.target.mouseX < drawPreviousX  && evt.target.mouseY > drawPreviousY) {
drawingRect[0] = evt.target.mouseX;
drawingRect[1] = drawPreviousY;
drawingRect[2] = drawPreviousX - evt.target.mouseX;
drawingRect[3] = evt.target.mouseY - drawPreviousY;
drawRectangle();
}
// top - right
if (evt.target.mouseX > drawPreviousX  && evt.target.mouseY < drawPreviousY) {
drawingRect[0] = drawPreviousX;
drawingRect[1] = evt.target.mouseY;
drawingRect[2] = evt.target.mouseX - drawPreviousX;
drawingRect[3] = drawPreviousY - evt.target.mouseY;
drawRectangle();
}
// top - left
if (evt.target.mouseX < drawPreviousX  && evt.target.mouseY < drawPreviousY) {
drawingRect[0] = evt.target.mouseX;
drawingRect[1] = evt.target.mouseY;
drawingRect[2] = drawPreviousX - evt.target.mouseX;
drawingRect[3] = drawPreviousY - evt.target.mouseY;
drawRectangle();
}
}

if (dragging) {
var newX:int = evt.target.mouseX - dragOffsetX;
var newY:int = evt.target.mouseY - dragOffsetY;
drawingRect[0] = newX;
drawingRect[1] = newY;
validSelectionPositionCheck();
drawRectangle();
}

if (resizing) {
if (resizeDirection == "downright" && evt.target.mouseX > drawPreviousX  && evt.target.mouseY > drawPreviousY) {
drawingRect[2] = evt.target.mouseX - drawPreviousX;
drawingRect[3] = evt.target.mouseY - drawPreviousY;
}
if (resizeDirection == "upleft" && evt.target.mouseX < drawPreviousX  && evt.target.mouseY < drawPreviousY) {
drawingRect[0] = evt.target.mouseX;
drawingRect[1] = evt.target.mouseY;
drawingRect[2] = drawPreviousX - evt.target.mouseX;
drawingRect[3] = drawPreviousY - evt.target.mouseY;
}
if (resizeDirection == "downleft" && evt.target.mouseX < drawPreviousX  && evt.target.mouseY > drawPreviousY) {
drawingRect[0] = evt.target.mouseX;
drawingRect[1] = drawPreviousY;
drawingRect[2] = drawPreviousX - evt.target.mouseX;
drawingRect[3] = evt.target.mouseY - drawPreviousY;
}
if (resizeDirection == "upright" && evt.target.mouseX > drawPreviousX  && evt.target.mouseY < drawPreviousY) {
drawingRect[0] = drawPreviousX;
drawingRect[1] = evt.target.mouseY;
drawingRect[2] = evt.target.mouseX - drawPreviousX;
drawingRect[3] = drawPreviousY - evt.target.mouseY;
}
if (resizeDirection == "top" && evt.target.mouseY < drawPreviousY) {
drawingRect[1] = evt.target.mouseY;
drawingRect[3] = drawPreviousY - evt.target.mouseY;
}
if (resizeDirection == "bottom" && evt.target.mouseY > drawPreviousY) {
drawingRect[1] = drawPreviousY;
drawingRect[3] = evt.target.mouseY - drawPreviousY;
}
if (resizeDirection == "right" && evt.target.mouseX > drawPreviousX) {
drawingRect[0] = drawPreviousX;
drawingRect[2] = evt.target.mouseX - drawPreviousX;
}
if (resizeDirection == "left" && evt.target.mouseX < drawPreviousX) {
drawingRect[0] = evt.target.mouseX;
drawingRect[2] = drawPreviousX - evt.target.mouseX;
}
drawRectangle();
}

if (!drawing && !dragging && !resizing){
cursorManager.removeAllCursors();
var lineClickArea:int = 8;
if (Math.abs(evt.target.mouseX - drawingRect[0])<lineClickArea && Math.abs(evt.target.mouseY - drawingRect[1])<lineClickArea) {
cursorManager.setCursor(resizeDiag2Cursor, 2, -9, -9);
inDragArea = false;
inResizeArea = true;
resizeDirection = "upleft";
}else
if (Math.abs(evt.target.mouseX - (drawingRect[0]+drawingRect[2]))<lineClickArea && Math.abs(evt.target.mouseY - (drawingRect[1]+drawingRect[3]))<lineClickArea) {
cursorManager.setCursor(resizeDiag2Cursor, 2, -9, -9);
inDragArea = false;
inResizeArea = true;
resizeDirection = "downright";
}else
if (Math.abs(evt.target.mouseX - drawingRect[0])<lineClickArea && Math.abs(evt.target.mouseY - (drawingRect[1]+drawingRect[3]))<lineClickArea) {
cursorManager.setCursor(resizeDiag1Cursor, 2, -9, -9);
inDragArea = false;
inResizeArea = true;
resizeDirection = "downleft";
}else
if (Math.abs(evt.target.mouseX - (drawingRect[0]+drawingRect[2]))<lineClickArea && Math.abs(evt.target.mouseY - drawingRect[1])<lineClickArea) {
cursorManager.setCursor(resizeDiag1Cursor, 2, -9, -9);
inDragArea = false;
inResizeArea = true;
resizeDirection = "upright";
}else
if (evt.target.mouseX > drawingRect[0] && evt.target.mouseX < drawingRect[0] + drawingRect[2] && Math.abs(evt.target.mouseY - drawingRect[1])<lineClickArea) {
cursorManager.setCursor(resizeVerticalCursor, 2, -9, -9);
inDragArea = false;
inResizeArea = true;
resizeDirection = "top";
}else
if (evt.target.mouseX > drawingRect[0] && evt.target.mouseX < drawingRect[0] + drawingRect[2] && Math.abs(evt.target.mouseY - (drawingRect[1]+drawingRect[3]))<lineClickArea) {
cursorManager.setCursor(resizeVerticalCursor, 2, -9, -9);
inDragArea = false;
inResizeArea = true;
resizeDirection = "bottom";
}else
if (evt.target.mouseY > drawingRect[1] && evt.target.mouseY < drawingRect[1] + drawingRect[3] && Math.abs(evt.target.mouseX - drawingRect[0])<lineClickArea) {
cursorManager.setCursor(resizeHorizontalCursor, 2, -9, -9);
inDragArea = false;
inResizeArea = true;
resizeDirection = "left";
}else
if (evt.target.mouseY > drawingRect[1] && evt.target.mouseY < drawingRect[1] + drawingRect[3] && Math.abs(evt.target.mouseX - (drawingRect[0] + drawingRect[2]))<lineClickArea) {
cursorManager.setCursor(resizeHorizontalCursor, 2, -9, -9);
inDragArea = false;
inResizeArea = true;
resizeDirection = "right";
}else
if (evt.target.mouseX > drawingRect[0] && evt.target.mouseX < drawingRect[0] + drawingRect[2] && evt.target.mouseY > drawingRect[1] && evt.target.mouseY < drawingRect[1] + drawingRect[3]) {
cursorManager.setCursor(dragCursor, 2, -9, -9);
inDragArea = true;
inResizeArea = false;
}else {
cursorManager.setCursor(cropCursor, 2, -9, -9);
inDragArea = false;
inResizeArea = false;
}
}
}

private function setResizingCoordinates():void {
if (resizeDirection == "downright") {
drawPreviousX = drawingRect[0];
drawPreviousY = drawingRect[1];
}else
if (resizeDirection == "upleft") {
drawPreviousX = drawingRect[0] + drawingRect[2];
drawPreviousY = drawingRect[1] + drawingRect[3];
}else
if (resizeDirection == "downleft") {
drawPreviousX = drawingRect[0] + drawingRect[2];
drawPreviousY = drawingRect[1];
}else
if (resizeDirection == "upright") {
drawPreviousX = drawingRect[0];
drawPreviousY = drawingRect[1] + drawingRect[3];
}else
if (resizeDirection == "top") {
drawPreviousY = drawingRect[1] + drawingRect[3];
}else
if (resizeDirection == "bottom") {
drawPreviousY = drawingRect[1];
}else
if (resizeDirection == "left") {
drawPreviousX = drawingRect[0] + drawingRect[2];
}else
if (resizeDirection == "right") {
drawPreviousX = drawingRect[0];
}
}

private function drawRectangle():void {
displayWidth.x = drawingRect[0];
if (displayWidth.x + displayWidth.width > cropDraw.width) {
displayWidth.x -= displayWidth.width;
}
displayWidth.y = drawingRect[1] - 12;
if (displayWidth.y < 0) {
displayWidth.y += displayWidth.height;
}
displayWidth.text = Math.abs(drawingRect[2]) + "px";
displayHeight.x = drawingRect[0] + drawingRect[2] + 4;
if (displayHeight.x + displayHeight.width > cropDraw.width) {
displayHeight.x -= (displayHeight.width + 4);
}
displayHeight.y = drawingRect[1] + drawingRect[3] - 12;
if (displayHeight.y < 0) {
displayHeight.y += displayHeight.height;
}
displayHeight.text = Math.abs(drawingRect[3]) + "px";
cropDraw.graphics.clear();
cropDraw.graphics.lineStyle(1, 0xff0000);
cropDraw.graphics.beginFill(0x00ff00, 0.15);
cropDraw.graphics.drawRect(drawingRect[0], drawingRect[1], drawingRect[2], drawingRect[3]);
cropDraw.graphics.endFill();
if (drawingRect[2] > 0 && drawingRect[3] > 0) {
canExportCrop = true;
}else {
canExportCrop = false;
}
}

private function drawOver(evt:MouseEvent):void {
if (dragging) {
cursorManager.setCursor(dragCursor, 2, -9, -9);
} else 
if (resizing) {
switch(resizeDirection) {
case "upleft":
case "downright":
cursorManager.setCursor(resizeDiag2Cursor, 2, -9, -9);
break;
case "upright":
case "downleft":
cursorManager.setCursor(resizeDiag1Cursor, 2, -9, -9);
break;
case "left":
case "right":
cursorManager.setCursor(resizeHorizontalCursor, 2, -9, -9);
break;
case "top":
case "bottom":
cursorManager.setCursor(resizeVerticalCursor, 2, -9, -9);
break;
}
} else {
cursorManager.setCursor(cropCursor, 2, -9, -9);
}
}

private function drawOut(evt:MouseEvent):void {
cursorManager.removeAllCursors();
}

private function validSelectionPositionCheck():void {
if (drawingRect[0] < 0) {
drawingRect[0] = 0;
}
if (drawingRect[0] > drawArea.width - drawingRect[2]) {
drawingRect[0] = drawArea.width - drawingRect[2];
}
if (drawingRect[1] < 0) {
drawingRect[1] = 0;
}
if (drawingRect[1] > drawArea.height - drawingRect[3]) {
drawingRect[1] = drawArea.height - drawingRect[3];
}
}

private function doExportCrop():void {
cropBD = new BitmapData(drawingRect[2], drawingRect[3], false);
cropBD.draw(cropHTML, new Matrix(1, 0, 0, 1, -drawingRect[0], -drawingRect[1]));
stack.selectedChild = cropsettings;
}

private function loadCropSettings():void {
if (pref_format == "JPEG") {
cropRadioJPEG.selected = true;
} else {
cropRadioPNG.selected = true;
}
}

private function cropBack():void {
saveCropSettings();
stack.selectedChild = loadpage;
removeElement(tempHTML);
}

private function saveCropSettings():void {
preferences.data.format = pref_format;
preferences.data.quality = pref_quality;
preferences.flush();
}

private function startExportCrop():void {
var encoder:IImageEncoder;
var byteArray:ByteArray;
var file:File;
var fileStream:FileStream;

if (pref_format == "JPEG") {
encoder = new JPEGEncoder(pref_quality);
}
if (pref_format == "PNG") {
encoder = new PNGEncoder();
}

byteArray = encoder.encode(cropBD);
file = File.documentsDirectory.resolvePath("crop." + pref_format);
file.browseForSave("Save cropped image");
file.addEventListener(Event.SELECT, saveSelect);

function saveSelect():void {
file.nativePath += "." + pref_format;
fileStream = new FileStream();
fileStream.open(file, FileMode.WRITE);
fileStream.writeBytes(byteArray);
fileStream.close();
cropBack();
}
}
]]>
</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" text="http://" /><s:Button label="Browse local..." click="doBrowse();" />
</s:HGroup>
<s:HGroup>
<custom:ImageButton img="@Embed('../lib/b_screenshot.png')" over="@Embed('../lib/b_screenshot_over.png')" toolTip="Take screenshots" click="goScreenshot('screenshot');" buttonMode="true" enabled="{urlInput.text!=''}" />
<custom:ImageButton img="@Embed('../lib/b_cut.png')" over="@Embed('../lib/b_cut_over.png')" toolTip="Crop area" click="goScreenshot('crop');" buttonMode="true" enabled="{urlInput.text!=''}" />
</s:HGroup>
</s:VGroup>
</s:NavigatorContent>

<s:NavigatorContent id="screenshotloading">
<s:VGroup width="100%" horizontalAlign="center" paddingTop="20">
<s:Label styleName="descriptionText">The page is being loaded...</s:Label>
<s:Button label="Cancel" click="cancelLoading();" />
</s:VGroup>
</s:NavigatorContent>

<s:NavigatorContent id="screenshotsettings">
<s:VGroup width="100%" horizontalAlign="center" paddingTop="20">
<s:Label styleName="descriptionText2">Select screenshot screen sizes:</s:Label>
<s:SkinnableContainer backgroundColor="#999999" width="310" height="18" >
<s:CheckBox toolTip="Use this screen size" x="4" id="set1checkbox" />
<s:Label id="contSize" styleName="settingText" x="22" y="3" />
</s:SkinnableContainer>
<custom:ScreenSetting id="set2" />
<custom:ScreenSetting id="set3" />
<custom:ScreenSetting id="set4" />
<custom:ScreenSetting id="set5" />
<custom:ScreenSetting id="set6" />
<custom:ScreenSetting id="set7" />

<s:Label/>

<s:Label styleName="descriptionText2">Export as:</s:Label>
<s:HGroup>
<s:RadioButton id="screenRadioJPEG" label="JPEG" groupName="screenshotFormat" change="formatChange('JPEG');" styleName="descriptionText2" /> 
<s:RadioButton id="screenRadioPNG" label="PNG" groupName="screenshotFormat" change="formatChange('PNG');" styleName="descriptionText2" /> 
</s:HGroup>
<s:Label styleName="descriptionText2">Quality:</s:Label>
<s:HSlider id="screenQualitySlider" width="310" minimum="1" maximum="100" liveDragging="true" enabled="{pref_format=='JPEG'}" value="@{pref_quality}" />

<s:Label/>

<s:Label styleName="descriptionText2">Export destination:</s:Label>
<s:HGroup width="310">
<s:TextInput editable="false" width="100%" toolTip="Destination" text="{pref_destination}" />
<s:Button label="Browse" click="screenshotDestination();" />
</s:HGroup>
<s:CheckBox id="folderCheckbox" label="Create new folder with exported images" styleName="descriptionText2" selected="@{pref_folder}" />
<s:TextInput id="folderField" width="100%" toolTip="Folder name" maxChars="200" enabled="{folderCheckbox.selected}" restrict="a-zA-Z0-9._-=+" />
<s:HGroup>
<s:Button label="Back" click="screenshotBack();" />
<s:Button label="Export" click="startExportScreenshot();" />
</s:HGroup>
</s:VGroup>
</s:NavigatorContent>

<s:NavigatorContent id="crop">
<s:VGroup width="{contentBox.width}" height="100%" gap="0" horizontalAlign="center">
<mx:HBox backgroundColor="#999999" width="100%" height="24" verticalScrollPolicy="off" verticalAlign="middle" paddingLeft="2">
<s:Button label="Back" click="{stack.selectedChild = loadpage;}" />
<s:Button label="Export selection" enabled="{canExportCrop}" click="doExportCrop();" />
</mx:HBox>
<s:Scroller width="{(contentBox.width>cropHTML.width+15)?(cropHTML.width+15):(contentBox.width)}" height="{contentBox.height-24}" id="scrollHTML">
<s:Group>
<mx:Image id="cropHTML" />
<s:SpriteVisualElement id="cropDraw" width="{cropHTML.width}" height="{cropHTML.height}" />
<mx:Box width="{cropHTML.width}" height="{cropHTML.height}" alpha="0" id="drawArea" backgroundColor="#000000"/>
<s:Label id="displayWidth" color="#000000" mouseEnabled="false" />
<s:Label id="displayHeight" color="#000000" mouseEnabled="false" />
</s:Group>
</s:Scroller>
</s:VGroup>
</s:NavigatorContent>

<s:NavigatorContent id="cropsettings">
<s:VGroup width="100%" horizontalAlign="center" paddingTop="20">
<s:Label styleName="descriptionText2">Export as:</s:Label>
<s:HGroup>
<s:RadioButton id="cropRadioJPEG" label="JPEG" groupName="screenshotFormat" change="formatChange('JPEG');" styleName="descriptionText2" /> 
<s:RadioButton id="cropRadioPNG" label="PNG" groupName="screenshotFormat" change="formatChange('PNG');" styleName="descriptionText2" /> 
</s:HGroup>
<s:Label styleName="descriptionText2">Quality:</s:Label>
<s:HSlider id="cropQualitySlider" width="310" minimum="1" maximum="100" liveDragging="true" enabled="{pref_format=='JPEG'}" value="@{pref_quality}" />

<s:Label/>

<s:HGroup>
<s:Button label="Back" click="cropBack();" />
<s:Button label="Export" click="startExportCrop();" />
</s:HGroup>
</s:VGroup>
</s:NavigatorContent>

<s:NavigatorContent id="export">
<s:VGroup width="100%" horizontalAlign="center" paddingTop="20">
<s:Label styleName="descriptionText" text="{exportText}" />
</s:VGroup>
</s:NavigatorContent>
</mx:ViewStack>
</mx:Box>
</s:VGroup>

</s:WindowedApplication>

Thanks for reading!

No comments:

Post a Comment